[Pkg-owncloud-commits] [owncloud] 43/49: Imported Upstream version 6.0.0~rc3+dfsg
David Prévot
taffit at moszumanska.debian.org
Thu Dec 5 16:02:57 UTC 2013
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to branch master
in repository owncloud.
commit 9da08170f055f2d7dbc98b423f93858ec9e9f05a
Merge: e31443b 4d50fe5
Author: David Prévot <taffit at debian.org>
Date: Thu Dec 5 09:41:58 2013 -0400
Imported Upstream version 6.0.0~rc3+dfsg
apps/bookmarks/l10n/ar/bookmarks.po | 4 +-
apps/bookmarks/l10n/bg_BG/bookmarks.po | 4 +-
apps/bookmarks/l10n/bn_BD/bookmarks.po | 4 +-
apps/bookmarks/l10n/ca.php | 1 +
apps/bookmarks/l10n/ca/bookmarks.po | 9 +-
apps/bookmarks/l10n/cs_CZ/bookmarks.po | 4 +-
apps/bookmarks/l10n/cy_GB/bookmarks.po | 4 +-
apps/bookmarks/l10n/da/bookmarks.po | 4 +-
apps/bookmarks/l10n/de/bookmarks.po | 6 +-
apps/bookmarks/l10n/de_CH/bookmarks.po | 6 +-
apps/bookmarks/l10n/de_DE/bookmarks.po | 8 +-
apps/bookmarks/l10n/el/bookmarks.po | 4 +-
apps/bookmarks/l10n/en_GB/bookmarks.po | 4 +-
apps/bookmarks/l10n/eo/bookmarks.po | 4 +-
apps/bookmarks/l10n/es/bookmarks.po | 4 +-
apps/bookmarks/l10n/es_AR/bookmarks.po | 4 +-
apps/bookmarks/l10n/et_EE/bookmarks.po | 4 +-
apps/bookmarks/l10n/eu/bookmarks.po | 4 +-
apps/bookmarks/l10n/fa/bookmarks.po | 4 +-
apps/bookmarks/l10n/fi_FI/bookmarks.po | 4 +-
apps/bookmarks/l10n/fr/bookmarks.po | 4 +-
apps/bookmarks/l10n/gl/bookmarks.po | 4 +-
apps/bookmarks/l10n/he/bookmarks.po | 4 +-
apps/bookmarks/l10n/hr/bookmarks.po | 4 +-
apps/bookmarks/l10n/hu_HU/bookmarks.po | 4 +-
apps/bookmarks/l10n/ia/bookmarks.po | 4 +-
apps/bookmarks/l10n/id/bookmarks.po | 4 +-
apps/bookmarks/l10n/is/bookmarks.po | 4 +-
apps/bookmarks/l10n/it/bookmarks.po | 4 +-
apps/bookmarks/l10n/ja_JP/bookmarks.po | 4 +-
apps/bookmarks/l10n/ka_GE/bookmarks.po | 4 +-
apps/bookmarks/l10n/ko/bookmarks.po | 4 +-
apps/bookmarks/l10n/ku_IQ/bookmarks.po | 4 +-
apps/bookmarks/l10n/lb/bookmarks.po | 4 +-
apps/bookmarks/l10n/lt_LT/bookmarks.po | 4 +-
apps/bookmarks/l10n/lv/bookmarks.po | 4 +-
apps/bookmarks/l10n/mk/bookmarks.po | 4 +-
apps/bookmarks/l10n/ms_MY/bookmarks.po | 4 +-
apps/bookmarks/l10n/nb_NO/bookmarks.po | 4 +-
apps/bookmarks/l10n/nl.php | 1 +
apps/bookmarks/l10n/nl/bookmarks.po | 8 +-
apps/bookmarks/l10n/nn_NO/bookmarks.po | 4 +-
apps/bookmarks/l10n/oc/bookmarks.po | 4 +-
apps/bookmarks/l10n/pl/bookmarks.po | 4 +-
apps/bookmarks/l10n/pt_BR/bookmarks.po | 4 +-
apps/bookmarks/l10n/pt_PT.php | 1 +
apps/bookmarks/l10n/pt_PT/bookmarks.po | 9 +-
apps/bookmarks/l10n/ro/bookmarks.po | 4 +-
apps/bookmarks/l10n/ru.php | 1 +
apps/bookmarks/l10n/ru/bookmarks.po | 9 +-
apps/bookmarks/l10n/ru_RU.php | 1 +
apps/bookmarks/l10n/ru_RU/bookmarks.po | 6 +-
apps/bookmarks/l10n/si_LK/bookmarks.po | 4 +-
apps/bookmarks/l10n/sk_SK.php | 1 +
apps/bookmarks/l10n/sk_SK/bookmarks.po | 8 +-
apps/bookmarks/l10n/sl/bookmarks.po | 4 +-
apps/bookmarks/l10n/sq/bookmarks.po | 4 +-
apps/bookmarks/l10n/sr/bookmarks.po | 4 +-
apps/bookmarks/l10n/sr at latin/bookmarks.po | 4 +-
apps/bookmarks/l10n/sv/bookmarks.po | 4 +-
apps/bookmarks/l10n/ta_LK/bookmarks.po | 4 +-
apps/bookmarks/l10n/templates/bookmarks.pot | 2 +-
apps/bookmarks/l10n/th_TH/bookmarks.po | 4 +-
apps/bookmarks/l10n/tr/bookmarks.po | 6 +-
apps/bookmarks/l10n/ug/bookmarks.po | 4 +-
apps/bookmarks/l10n/uk/bookmarks.po | 4 +-
apps/bookmarks/l10n/vi/bookmarks.po | 4 +-
apps/bookmarks/l10n/zh_CN/bookmarks.po | 4 +-
apps/bookmarks/l10n/zh_HK/bookmarks.po | 4 +-
apps/bookmarks/l10n/zh_TW/bookmarks.po | 4 +-
apps/documents/ajax/sessionController.php | 20 +-
apps/documents/css/style.css | 7 -
apps/documents/css/viewer/odfviewer.css | 15 +-
apps/documents/js/3rdparty/webodf/editor/Editor.js | 90 +-
.../js/3rdparty/webodf/editor/EditorSession.js | 52 +-
.../3rdparty/webodf/editor/server/ServerFactory.js | 3 +-
.../webodf/editor/server/owncloud/ServerFactory.js | 4 +-
.../editor/server/pullbox/OperationRouter.js | 188 +-
.../webodf/editor/server/pullbox/Server.js | 43 +-
.../webodf/editor/server/pullbox/ServerFactory.js | 4 +-
.../webodf/editor/server/pullbox/SessionList.js | 2 +
.../webodf/editor/widgets/paragraphStyles.js | 2 +-
apps/documents/js/3rdparty/webodf/webodf-debug.js | 27831 ++++++++++---------
apps/documents/js/3rdparty/webodf/webodf.js | 1849 +-
apps/documents/js/documents.js | 21 +-
apps/documents/js/viewer/viewer.js | 49 +-
apps/documents/lib/file.php | 30 +
apps/documents/lib/genesis.php | 19 +-
apps/files_encryption/lib/helper.php | 9 +-
apps/files_external/lib/amazons3.php | 12 +-
apps/files_external/lib/config.php | 7 +-
apps/files_external/templates/settings.php | 2 +-
apps/files_sharing/css/public.css | 29 +-
apps/files_trashbin/ajax/delete.php | 32 +-
apps/files_trashbin/ajax/undelete.php | 1 +
apps/files_trashbin/css/trash.css | 3 +
apps/files_trashbin/index.php | 1 +
apps/files_trashbin/js/trash.js | 50 +-
apps/files_trashbin/lib/helper.php | 2 +
apps/files_trashbin/lib/trashbin.php | 22 +-
apps/files_trashbin/templates/part.list.php | 13 +-
apps/search_lucene/ajax/lucene.php | 19 +-
apps/search_lucene/appinfo/update.php | 17 +
apps/search_lucene/appinfo/version | 2 +-
apps/search_lucene/lib/status.php | 85 +
apps/user_ldap/ajax/setConfiguration.php | 12 +
apps/user_ldap/ajax/testConfiguration.php | 2 +
apps/user_ldap/js/settings.js | 72 +-
apps/user_ldap/lib/configuration.php | 2 +-
apps/user_ldap/lib/wizard.php | 3 +-
config/config.sample.php | 7 +-
core/css/styles.css | 13 +-
core/skeleton/ownCloudUserManual.pdf | Bin 1393380 -> 1393379 bytes
lib/private/files/storage/wrapper/wrapper.php | 8 +
lib/private/files/view.php | 8 +-
lib/private/setup/abstractdatabase.php | 4 +
lib/private/setup/oci.php | 63 +-
lib/private/util.php | 12 +-
settings/admin.php | 1 +
settings/templates/admin.php | 14 +
version.php | 6 +-
121 files changed, 15897 insertions(+), 15160 deletions(-)
diff --cc apps/bookmarks/l10n/ar/bookmarks.po
index 2e8d11d,0000000..f10c1bb
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/ar/bookmarks.po
+++ b/apps/bookmarks/l10n/ar/bookmarks.po
@@@ -1,153 -1,0 +1,153 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# blackcoder <tarek.taha at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Arabic (http://www.transifex.com/projects/p/owncloud/language/ar/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ar\n"
+"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "لم يتم اضافة ملف للتدخيل"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "نوعية الملف غير صالحه للاستيراد"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "اشارات المرجعية"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "فئاة"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "تصفيه حسب الفئه"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "عدل المرجعيه"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "هل أنت متاكد أنك تريد حذف هذه الفئه من جميع المدخولات؟"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "تحذير"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "لقد فشل الإستيراد"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "تم الاستيراد بنجاح"
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "ترفيع..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "مرجعيه."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "أضف إشارة مرجعية"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "إغلق"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "أسم هذه الصفحه"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "عنوان هذه الصفحه"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "وصف هذه الصفحه"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "حفظ"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "حذف"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "تعديل"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "الغاء"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "اسحب هذه الى قائمة المرجعيه في متصفحك, و اضغط عليه عندما تريد اضافة صفحه :"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "عنوان"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "أدخل"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "فئات متشابهه"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "تعديلات"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "لا يوجد عندك صفحات مرجعيه"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "يمكنك ايضا محاولة ادخال ملف فئة مرجعيه"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "المرجعيه"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "تصدير و استيراد"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "تصدير المعلومات"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "استيراد"
diff --cc apps/bookmarks/l10n/bg_BG/bookmarks.po
index 140895d,0000000..9895098
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/bg_BG/bookmarks.po
+++ b/apps/bookmarks/l10n/bg_BG/bookmarks.po
@@@ -1,155 -1,0 +1,155 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Димитър Кръстев <dimitar.t.krastev at gmail.com>, 2013
+# Stefan Ilivanov <ilivanov at gmail.com>, 2013
+# Yasen Pramatarov <yasen at lindeas.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:40+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Bulgarian (Bulgaria) (http://www.transifex.com/projects/p/owncloud/language/bg_BG/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: bg_BG\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Не беше предоставен файл за зареждане"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Неподдържан файл за импорт"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Отметки"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Етикети"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Филтриране по етикет"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Промяна на предпочитание"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Сигурни ли сте, че желаете да премахнете този етикет от всеки запис?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Внимание"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Грешка при зареждане"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Импортирането завърши успешно."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Качване..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Предп."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Добави в предпочитани"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Затвори"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Заглавие на страницата"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Адрес на страницата"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Описание на страницата"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Запис"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Изтриване"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Промяна"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Отказ"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Довлачете това в лентата с отметки на браузъра си и го натискайте, когато искате да отметнете бързо някоя страница:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Адрес"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Добавяне"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Етикети"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Настройки"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Нямате предпочитания"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Може също да опитате да заредите файл с отметки"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Отметка"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Експорт и Импорт"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Експорт"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Внасяне"
diff --cc apps/bookmarks/l10n/bn_BD/bookmarks.po
index 723fdf1,0000000..7fda476
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/bn_BD/bookmarks.po
+++ b/apps/bookmarks/l10n/bn_BD/bookmarks.po
@@@ -1,153 -1,0 +1,153 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Shubhra Paul <paul_shubhra at yahoo.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Bengali (Bangladesh) (http://www.transifex.com/projects/p/owncloud/language/bn_BD/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: bn_BD\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr ""
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "আমদানি করার জন্য ফাইলের ফর্ম্যাটটি সঠিক নয়"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "ঠিকাসমূহ"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "ট্যাগ"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "ট্যাগ অনুসারে ছাঁক"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "ঠিকা সম্পাদনা"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "প্রত্যেক ভুক্তি থেকে এই ট্যাগটি অপসারণ করতে আপনি কি বদ্ধপরিকর?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "সতর্কবাণী"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr ""
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "আমদানি সুসম্পন্ন হয়েছে।"
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "আপলোড করা হচ্ছে.........."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "ঠিকা"
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "ঠিকা যোগ করুন"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "বন্ধ"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "পৃষ্ঠার শিরোনাম"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "পৃষ্ঠার ঠিকানা"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "পৃষ্ঠার বিবরণ"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "সংরক্ষণ কর"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "মুছে ফেল"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "সম্পাদনা"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "বাতিল"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "দ্রুত কোন ওয়েবপেজ ঠিকাতে সংরক্ষণ করতে চাইলে এটিকে টেনে ব্রাউজারের ঠিকাতে নিয়ে যান এবং তাতে ক্লিক করুনঃ"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "ঠিকানা"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "যোগ কর"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "সম্পর্কযুক্ত ট্যাগ"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "নিয়ামকসমূহ"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "আপনার কোন ঠিক নেই"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "আপনি একটি ঠিকা ফাইল আমদানি করার চেষ্টা করে দেখতে পারেন"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "অনুঠিকা"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "আমদানি এবং রপ্তানি"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "রপ্তানি"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "আমদানি"
diff --cc apps/bookmarks/l10n/ca.php
index b15eb71,0000000..03cd007
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/ca.php
+++ b/apps/bookmarks/l10n/ca.php
@@@ -1,34 -1,0 +1,35 @@@
+<?php $TRANSLATIONS = array(
+"No file provided for import" => "No heu proporcionat cap fitxer a importar",
+"Unsupported file type for import" => "Importació d'un tipus de fitxer no implementat",
+"Bookmarks" => "Adreces d'interès",
+"Tags" => "Etiquetes",
+"Filter by tag" => "Filtrat per etiqueta",
+"Edit bookmark" => "Edita l'adreça d'interès",
+"Are you sure you want to remove this tag from every entry?" => "Segur que voleu eliminar aquesta etiqueta de cada entrada?",
+"Warning" => "Avís",
+"Import error" => "Error en importar",
+"Import completed successfully." => "La importació ha acabat amb èxit",
+"Uploading..." => "Pujant...",
+"Bookm." => "Marcador",
+"Add a bookmark" => "Afegeix una adreça d'interès",
+"Close" => "Tanca",
+"The title of the page" => "El títol de la pàgina",
+"The address of the page" => "L'adreça de la pàgina",
+"Description of the page" => "Descripció de la pàgina",
+"Save" => "Desa",
+"Delete" => "Esborra",
+"Edit" => "Edita",
+"Cancel" => "Cancel·la",
+"Drag this to your browser bookmarks and click it, when you want to bookmark a webpage quickly:" => "Arrossegueu-ho al navegador i feu-hi un clic quan volgueu marcar ràpidament una adreça d'interès:",
++"Add to ownCloud" => "Afegeix a ownCloud",
+"Address" => "Adreça",
+"Add" => "Afegeix",
+"Related Tags" => "Etiquetes relacionades",
+"Settings" => "Configuració",
+"You have no bookmarks" => "No teniu adreces d'interès",
+"You can also try to import a bookmark file" => "També podeu intentar importar un fitxer d'adreces d'interès",
+"Bookmarklet" => "Bookmarklet",
+"Export & Import" => "Exporta i importa",
+"Export" => "Exporta",
+"Import" => "Importa"
+);
diff --cc apps/bookmarks/l10n/ca/bookmarks.po
index d1c929b,0000000..d53ca9f
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/ca/bookmarks.po
+++ b/apps/bookmarks/l10n/ca/bookmarks.po
@@@ -1,155 -1,0 +1,156 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# bury1000 <bury1000 at gmail.com>, 2012
+# rogerc, 2013
++# rogerc, 2013
+# rogerc, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
- "Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
++"Last-Translator: rogerc\n"
+"Language-Team: Catalan (http://www.transifex.com/projects/p/owncloud/language/ca/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ca\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "No heu proporcionat cap fitxer a importar"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Importació d'un tipus de fitxer no implementat"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Adreces d'interès"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Etiquetes"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtrat per etiqueta"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Edita l'adreça d'interès"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Segur que voleu eliminar aquesta etiqueta de cada entrada?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Avís"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Error en importar"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "La importació ha acabat amb èxit"
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Pujant..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Marcador"
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Afegeix una adreça d'interès"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Tanca"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "El títol de la pàgina"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "L'adreça de la pàgina"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Descripció de la pàgina"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Desa"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Esborra"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Edita"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Cancel·la"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Arrossegueu-ho al navegador i feu-hi un clic quan volgueu marcar ràpidament una adreça d'interès:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
- msgstr ""
++msgstr "Afegeix a ownCloud"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adreça"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Afegeix"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Etiquetes relacionades"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Configuració"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "No teniu adreces d'interès"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "També podeu intentar importar un fitxer d'adreces d'interès"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Bookmarklet"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Exporta i importa"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Exporta"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importa"
diff --cc apps/bookmarks/l10n/cs_CZ/bookmarks.po
index b313077,0000000..3d1d623
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/cs_CZ/bookmarks.po
+++ b/apps/bookmarks/l10n/cs_CZ/bookmarks.po
@@@ -1,156 -1,0 +1,156 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# liska_, 2013
+# Martin <fireball at atlas.cz>, 2012
+# pstast <petr at stastny.eu>, 2013
+# Tomáš Chvátal <tomas.chvatal at gmail.com>, 2012-2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-29 14:17-0500\n"
- "PO-Revision-Date: 2013-11-27 18:03+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:40+0000\n"
+"Last-Translator: pstast <petr at stastny.eu>\n"
+"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/owncloud/language/cs_CZ/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: cs_CZ\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Nebyl vybrán soubor k importu"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Nepodporovaný typ souboru pro import"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Záložky"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Značky"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtrovat podle značky"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Upravit záložku"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Opravdu jste si jisti, že si přejete odstranit tuto značku z každého záznamu?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Varování"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Chyba při importu"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Import úspěšně dokončen."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Odesílám..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Zál."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Přidat záložku"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Zavřít"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Název stránky"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Adresa stránky"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Popis stránky"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Uložit"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Smazat"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Upravit"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Zrušit"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Přetáhněte do Vašeho prohlížeče a klikněte, pokud si přejete rychle uložit stránku do záložek:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr "Přidat do ownCloudu"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adresa"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Přidat"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Podobné značky"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Nastavení"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Nemáte žádné záložky"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Můžete také zkusit importovat soubor záložek"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Rutina pro záložky"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Export a import"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Exportovat"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importovat"
diff --cc apps/bookmarks/l10n/cy_GB/bookmarks.po
index b4b8ec0,0000000..b6800e9
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/cy_GB/bookmarks.po
+++ b/apps/bookmarks/l10n/cy_GB/bookmarks.po
@@@ -1,153 -1,0 +1,153 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# ubuntucymraeg <owen.llywelyn at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Welsh (United Kingdom) (http://www.transifex.com/projects/p/owncloud/language/cy_GB/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: cy_GB\n"
+"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Dim ffeil i'w fewnforio"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Dim cefnogaeth i fewnforio'r math hwn o ffeil"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Nodau tudalen"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Tagiau"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Hidlo yn ôl tag"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Golygu nod tudalen"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Ydych chi'n siwr eich bod am waredu'r tag hwn o bob cofnod?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Rhybudd"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Gwall mewnforio"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Mewnforiwyd yn llwyddiannus."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Yn llwytho i fyny..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Nodtud."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Ychwanegu nod tudalen"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Cau"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Teitl y dudalen"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Cyfeiriad y dudalen"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Disgrifiad o'r dudalen"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Cadw"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Dileu"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Golygu"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Diddymu"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Llusgwch hwn i nodau tudalen eich porwr a'i glicio pan fyddwch eisiau gosod nod tudalen gwe'n gyflym."
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Cyfeiriad"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Ychwanegu"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Tagiau perthynol"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Gosodiadau"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Nid oes nodau tudalen gennych"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Gallwch hefyd geisio mewnforio ffeil nod tudalen"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Nod tudalen gweithredol"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Allforio & Mewnforio"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Allforio"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Mewnforio"
diff --cc apps/bookmarks/l10n/da/bookmarks.po
index b8ee763,0000000..b8d288f
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/da/bookmarks.po
+++ b/apps/bookmarks/l10n/da/bookmarks.po
@@@ -1,157 -1,0 +1,157 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Sappe, 2013
+# cronner <cronner at gmail.com>, 2012
+# Morten Juhl-Johansen Zölde-Fejér <morten at writtenandread.net>, 2012-2013
+# Ole Holm Frandsen <froksen at gmail.com>, 2012
+# osos <osos at openeyes.dk>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Danish (http://www.transifex.com/projects/p/owncloud/language/da/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: da\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Ingen fil opgivet til import"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Ikke understøttet filtype til import"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Bogmærker"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Mærker"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtrer efter tag"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Rediger bogmærker"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Er du sikker på at du vil fjerne dette flag fra alle poster?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Advarsel"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Fejl ved import"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Importer fuldført."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Uploader..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Bogm."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Tilføj bogmærke"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Luk"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Sidens titel"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Sidens adresse"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Sidens beskrivelse"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Gem"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Slet"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Rediger"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Annuller"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Træk denne til dine browserbogmærker og klik på den, når du ønsker at lynoprette et bogmærke til hjemmesiden:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adresser"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Tilføj"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Relaterede Tags"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Indstillinger"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Du har ingen bogmærker"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Du kan også prøve at importere en bogmærke-fil"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Bookmarklet"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Eksport & import"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Exporter"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importer"
diff --cc apps/bookmarks/l10n/de/bookmarks.po
index 7547406,0000000..52deb47
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/de/bookmarks.po
+++ b/apps/bookmarks/l10n/de/bookmarks.po
@@@ -1,162 -1,0 +1,162 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Mirodin <blobbyjj at ymail.com>, 2012
+# I Robot <owncloud-bot at tmit.eu>, 2012
+# I Robot <owncloud-bot at tmit.eu>, 2012
+# Mario Siegmann <mario_siegmann at web.de>, 2013
+# JamFX <niko at nik-o-mat.de>, 2012
+# Phi Lieb <>, 2012
+# robN <robert.neumann01 at gmail.com>, 2013
+# I Robot <owncloud-bot at tmit.eu>, 2012
- # traductor <transifex-2.7.mensaje at spamgourmet.com>, 2012
++# traductor <transifex-3.7.mensaje at spamgourmet.com>, 2012
+# Mirodin <blobbyjj at ymail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-24 01:08-0500\n"
- "PO-Revision-Date: 2013-11-23 16:10+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:40+0000\n"
+"Last-Translator: Mario Siegmann <mario_siegmann at web.de>\n"
+"Language-Team: German (http://www.transifex.com/projects/p/owncloud/language/de/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: de\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Es wurde keine Datei zum Import zur Verfügung gestellt"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Dateityp wird für den Import nicht unterstützt"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Lesezeichen"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Tags"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtern nach Schlagwort"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Lesezeichen bearbeiten"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Soll dieses Schlagwort wirklich von allen Einträgen entfernt werden?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Warnung"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Import Fehler"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Der Import wurde erfolgreich abgeschlossen."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Lade hoch ..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Lesez."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Ein Lesezeichen hinzufügen"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Schließen"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Der Titel der Seite"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Die Adresse der Seite"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Die Beschreibung der Seite"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Speichern"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Löschen"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Bearbeiten"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Abbrechen"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Ziehe dies zu Deinen Browser-Lesezeichen und klicke darauf, wenn Du eine Website schnell den Lesezeichen hinzufügen willst."
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr "Zu ownCloud hinzufügen"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adresse"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Hinzufügen"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Verwandte Schlagworte"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Einstellungen"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Du hast keine Lesezeichen"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Du kannst auch versuchen eine Lesezeichendatei zu importieren."
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Bookmarklet"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Export & Import"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Exportieren"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importieren"
diff --cc apps/bookmarks/l10n/de_CH/bookmarks.po
index bb65a26,0000000..0fdbb7d
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/de_CH/bookmarks.po
+++ b/apps/bookmarks/l10n/de_CH/bookmarks.po
@@@ -1,160 -1,0 +1,160 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# a.tangemann <a.tangemann at web.de>, 2012
+# FlorianScholz <work at bgstyle.de>, 2013
+# I Robot <owncloud-bot at tmit.eu>, 2012
+# JamFX <niko at nik-o-mat.de>, 2012
+# Mirodin <blobbyjj at ymail.com>, 2012-2013
+# Phi Lieb <>, 2012
+# robN <robert.neumann01 at gmail.com>, 2013
- # traductor <transifex-2.7.mensaje at spamgourmet.com>, 2012
++# traductor <transifex-3.7.mensaje at spamgourmet.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: German (Switzerland) (http://www.transifex.com/projects/p/owncloud/language/de_CH/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: de_CH\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Es wurde keine Datei zum Import zur Verfügung gestellt"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Dateityp wird für den Import nicht unterstützt"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Lesezeichen"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Tags"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtern nach Schlagwort"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Lesezeichen bearbeiten"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Soll dieses Schlagwort wirklich von allen Einträgen entfernt werden?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Warnung"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Import Fehler"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Import erfolgreich beendet."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Lade hoch ..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Lesez."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Ein Lesezeichen hinzufügen"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Schliessen"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Der Titel der Seite"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Die Adresse der Seite"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Die Beschreibung der Seite"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Speichern"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Löschen"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Bearbeiten"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Abbrechen"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Ziehen Sie dies zu Ihren Browser-Lesezeichen und klicken Sie darauf, wenn Sie eine Website schnell den Lesezeichen hinzufügen wollen."
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adresse"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Hinzufügen"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Verwandte Schlagworte"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Einstellungen"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Sie haben keine Lesezeichen"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Sie können auch versuchen, eine Lesezeichen Datei zu importieren."
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Bookmarklet"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Export & Import"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Exportieren"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importieren"
diff --cc apps/bookmarks/l10n/de_DE/bookmarks.po
index 1b36b7c,0000000..158d105
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/de_DE/bookmarks.po
+++ b/apps/bookmarks/l10n/de_DE/bookmarks.po
@@@ -1,162 -1,0 +1,162 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# a.tangemann <a.tangemann at web.de>, 2012
+# Mirodin <blobbyjj at ymail.com>, 2012
+# I Robot <owncloud-bot at tmit.eu>, 2012
+# Mario Siegmann <mario_siegmann at web.de>, 2013
+# JamFX <niko at nik-o-mat.de>, 2012
+# Phi Lieb <>, 2012
+# robN <robert.neumann01 at gmail.com>, 2013
+# I Robot <owncloud-bot at tmit.eu>, 2012
- # traductor <transifex-2.7.mensaje at spamgourmet.com>, 2012
++# traductor <transifex-3.7.mensaje at spamgourmet.com>, 2012
+# Mirodin <blobbyjj at ymail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-24 01:08-0500\n"
- "PO-Revision-Date: 2013-11-23 16:10+0000\n"
- "Last-Translator: Mario Siegmann <mario_siegmann at web.de>\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:40+0000\n"
++"Last-Translator: traductor <transifex-3.7.mensaje at spamgourmet.com>\n"
+"Language-Team: German (Germany) (http://www.transifex.com/projects/p/owncloud/language/de_DE/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: de_DE\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Es wurde keine Datei zum Import zur Verfügung gestellt"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Dateityp wird für den Import nicht unterstützt"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Lesezeichen"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Tags"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtern nach Schlagwort"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Lesezeichen bearbeiten"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Soll dieses Schlagwort wirklich von allen Einträgen entfernt werden?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Warnung"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Import Fehler"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Import erfolgreich beendet."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Lade hoch ..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Lesez."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Ein Lesezeichen hinzufügen"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Schließen"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Der Titel der Seite"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Die Adresse der Seite"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Die Beschreibung der Seite"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Speichern"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Löschen"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Bearbeiten"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Abbrechen"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Ziehen Sie dies zu Ihren Browser-Lesezeichen und klicken Sie darauf, wenn Sie eine Website schnell den Lesezeichen hinzufügen wollen."
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr "Zu ownCloud hinzufügen"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adresse"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Hinzufügen"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Verwandte Schlagworte"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Einstellungen"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Sie haben keine Lesezeichen"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Sie können auch versuchen, eine Lesezeichen Datei zu importieren."
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Bookmarklet"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Export & Import"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Exportieren"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importieren"
diff --cc apps/bookmarks/l10n/el/bookmarks.po
index 5507bb5,0000000..6225be0
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/el/bookmarks.po
+++ b/apps/bookmarks/l10n/el/bookmarks.po
@@@ -1,157 -1,0 +1,157 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Dimitris M. <monopatis at gmail.com>, 2012
+# Efstathios Iosifidis <iefstathios at gmail.com>, 2012
+# Efstathios Iosifidis <iefstathios at gmail.com>, 2013
+# Efstathios Iosifidis <iosifidis at opensuse.org>, 2012
+# vkehayas <vkehayas at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-24 01:08-0500\n"
- "PO-Revision-Date: 2013-11-23 01:20+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: vkehayas <vkehayas at gmail.com>\n"
+"Language-Team: Greek (http://www.transifex.com/projects/p/owncloud/language/el/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: el\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Δεν δόθηκε αρχείο για εισαγωγή"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Δεν υποστηρίζεται o τύπος αρχείου για εισαγωγή"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Σελιδοδείκτες"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Ετικέτες"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Φιλτράρισμα βάσει ετικέτας"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Επεξεργασία σελιδοδείκτη"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Είστε σίγουρος για την αφαίρεση αυτής της ετικέτας από κάθε καταχώρηση;"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Προειδοποίηση"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Σφάλμα εισαγωγής"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Η εισαγωγή ολοκληρώθηκε επιτυχώς."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Μεταφόρτωση..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Σελιδοδεικτ."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Προσθήκη σελιδοδείκτη"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Κλείσιμο"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Τίτλος της σελίδας"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Διεύθυνση της σελίδας"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Περιγραφή της σελίδας"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Αποθήκευση"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Διαγραφή"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Επεξεργασία"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Ακύρωση"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Σύρετε αυτό στους σελιδοδείκτες του περιηγητή σας και κάντε κλικ επάνω του, όταν θέλετε να προσθέσετε σύντομα μια ιστοσελίδα ως σελιδοδείκτη:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr "Προσθήκη στο ownCloud"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Διεύθυνση"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Προσθήκη"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Σχετικές ετικέτες"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Ρυθμίσεις"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Δεν έχετε σελιδοδείκτες"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Μπορείτε να δοκιμάσετε να εισάγεται ένα αρχείο σελιδοδεικτών"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Εφαρμογίδιο Σελιδοδεικτών"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Εξαγωγή & Εισαγωγή"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Εξαγωγή"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Εισαγωγή"
diff --cc apps/bookmarks/l10n/en_GB/bookmarks.po
index b4e5698,0000000..68754b3
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/en_GB/bookmarks.po
+++ b/apps/bookmarks/l10n/en_GB/bookmarks.po
@@@ -1,153 -1,0 +1,153 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# mnestis <transifex at mnestis.net>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-29 14:17-0500\n"
- "PO-Revision-Date: 2013-11-28 14:20+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: mnestis <transifex at mnestis.net>\n"
+"Language-Team: English (United Kingdom) (http://www.transifex.com/projects/p/owncloud/language/en_GB/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: en_GB\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "No file provided for import"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Unsupported file type for import"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Bookmarks"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Tags"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filter by tag"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Edit bookmark"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Are you sure you want to remove this tag from every entry?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Warning"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Import error"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Import completed successfully."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Uploading..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Bookm."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Add a bookmark"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Close"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "The title of the page"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "The address of the page"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Description of the page"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Save"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Delete"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Edit"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Cancel"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Drag this to your browser bookmarks and click it, when you want to bookmark a webpage quickly:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr "Add to ownCloud"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Address"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Add"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Related Tags"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Settings"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "You have no bookmarks"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "You can also try to import a bookmark file"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Bookmarklet"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Export & Import"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Export"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Import"
diff --cc apps/bookmarks/l10n/eo/bookmarks.po
index 1a6fa95,0000000..409ee43
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/eo/bookmarks.po
+++ b/apps/bookmarks/l10n/eo/bookmarks.po
@@@ -1,154 -1,0 +1,154 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Baptiste <baptiste+transifex at darthenay.fr>, 2013
+# Mariano <mstreet at kde.org.ar>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:40+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Esperanto (http://www.transifex.com/projects/p/owncloud/language/eo/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: eo\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Neniu dosiero aldonita por enporti"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Dosiertipo nekongrua kun enporto"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Legosignoj"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Etikedoj"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtri laŭ etikedo"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Redakti legosignon"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Ĉu vi vere volas forigi ĉi tiun etikedon el ĉiu ero?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Averto"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Enporta eraro"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Enporto plenumiĝis sukcese."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Alŝutante..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Legos."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Aldoni legosignon"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Fermi"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Titolo de la paĝo"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Adreso de la paĝo"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Priskribo de la paĝo"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Konservi"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Forigi"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Redakti"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Nuligi"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Ŝovu tion ĉi al la legosignoj de via TTT-legilo kaj klaku ĝin, se vi volas rapide legosignigi TTT-paĝon:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adreso"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Aldoni"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Rilataj etikedoj"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Agordo"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Vi havas neniun legosignon"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Vi povas ankaŭ provi enporti legosignan dosieron"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Kodosigno"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Malenporti kaj enporti"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Elporti"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Enporti"
diff --cc apps/bookmarks/l10n/es/bookmarks.po
index 717ceb5,0000000..ef40dcf
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/es/bookmarks.po
+++ b/apps/bookmarks/l10n/es/bookmarks.po
@@@ -1,162 -1,0 +1,162 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# aleza84 <aleja4984 at hotmail.com>, 2012
+# Art O. Pal <artopal at fastmail.fm>, 2012-2013
+# Luis Medina <devianpctek at gmail.com>, 2012
+# ggam <ggam at brainleakage.com>, 2013
+# juanman <juanma at kde.org.ar>, 2012
+# ranmaruhibikiya <ranmaru.hibikiya at gmail.com>, 2013
+# Ricardo Hermosilla <ra.hermosillac at gmail.com>, 2013
+# Rubén Trujillo <rubentrf at gmail.com>, 2012
+# scambra <sergio at programatica.es>, 2013
+# scambra <sergio at programatica.es>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-24 01:08-0500\n"
- "PO-Revision-Date: 2013-11-22 16:20+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: Art O. Pal <artopal at fastmail.fm>\n"
+"Language-Team: Spanish (http://www.transifex.com/projects/p/owncloud/language/es/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: es\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "No se especificó un archivo para importar"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Tipo de archivo no soportado para importar"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Marcadores"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Etiquetas"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtrar por etiquetas"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Editar marcador"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "¿Está seguro de que desea eliminar esta etiqueta de todas las entradas?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Precaución"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Error de importación"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Importación completada con éxito."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Subiendo..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Marc."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Agregar a marcadores"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Cerrar"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Título de la página"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Dirección de la página"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Descripción de la página"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Guardar"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Eliminar"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Editar"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Arrastre desde aquí a los marcadores de su navegador, y haga clic cuando quiera marcar una página web rápidamente:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr "Agregar a ownCloud"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Dirección"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Añadir"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Etiquetas relacionadas"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Ajustes"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "No tiene marcadores"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "También puede intentar importar un archivo de marcadores"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Marcador de JavaScript"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Exportar e Importar"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Exportar"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importar"
diff --cc apps/bookmarks/l10n/es_AR/bookmarks.po
index 9479805,0000000..777f4fd
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/es_AR/bookmarks.po
+++ b/apps/bookmarks/l10n/es_AR/bookmarks.po
@@@ -1,154 -1,0 +1,154 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# cjtess <claudio.tessone at gmail.com>, 2013
+# cjtess <claudio.tessone at gmail.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Spanish (Argentina) (http://www.transifex.com/projects/p/owncloud/language/es_AR/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: es_AR\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "No se proveyeron archivos para importar"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Tipo de archivo no soportado para importar"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Marcadores"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Etiquetas"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtrar por etiquetas"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Editar marcadores"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "¿Estás seguro de que querés borrar esta etiqueta de todos los elementos?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Atención"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Error al importar"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Importación completada con éxito."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Subiendo..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Marc."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Agregar un marcador"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Cerrar"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "El título de la página"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "La dirección de la página"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Descripción de la página"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Guardar"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Borrar"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Editar"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Arrastrá desde aquí a los marcadores de tu navegador, y hacé click cuando quieras marcar una página web:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Dirección"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Agregar"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Etiquetas relacionadas"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Configuración"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "No tenés marcadores"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "También podés intentar importar un archivo de marcadores"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Marcadores"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Exportar e importar"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Exportar"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importar"
diff --cc apps/bookmarks/l10n/et_EE/bookmarks.po
index 087e0bc,0000000..589fe12
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/et_EE/bookmarks.po
+++ b/apps/bookmarks/l10n/et_EE/bookmarks.po
@@@ -1,155 -1,0 +1,155 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# dagor <dagor.vint at hotmail.com>, 2012
+# pisike.sipelgas <pisike.sipelgas at gmail.com>, 2013
+# Rivo Zängov <eraser at eraser.ee>, 2012-2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-24 01:08-0500\n"
- "PO-Revision-Date: 2013-11-22 09:40+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: pisike.sipelgas <pisike.sipelgas at gmail.com>\n"
+"Language-Team: Estonian (Estonia) (http://www.transifex.com/projects/p/owncloud/language/et_EE/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: et_EE\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Imporditav fail puudub"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Toetuseta failitüübi import"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Järjehoidjad"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Sildid"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtreeri siltide järgi"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Muuda järjehoidjat"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Oled sa kindel, et sa soovid kõigilt sissekannetelt seda silti eemaldada?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Hoiatus"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Viga importimisel"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Import on edukalt lõpetatud."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Üleslaadimine..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Järjeh."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Lisa järjehoidja"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Sulge"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Lehe pealkiri"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Lehe aadress"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Lehe kirjeldus"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Salvesta"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Kustuta"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Muuda"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Loobu"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Lohista see oma veebilehitseja järjehoidjatesse ja kliki sellele, kui sa soovid veebilehte kiirelt lisada:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr "Lisa ownCloudi"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Aadress"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Lisa"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Seotud sildid"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Seaded"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Sul pole järjehoidjaid"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Sa võid ka proovida järjehoidjate faili importimist"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Järjehoidja vidin"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Eksport ja import"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Ekspordi"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Impordi"
diff --cc apps/bookmarks/l10n/eu/bookmarks.po
index 7a0245b,0000000..4947e44
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/eu/bookmarks.po
+++ b/apps/bookmarks/l10n/eu/bookmarks.po
@@@ -1,155 -1,0 +1,155 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# asieriko <asieriko at gmail.com>, 2013
+# asieriko <asieriko at gmail.com>, 2012
+# Piarres Beobide <pi at beobide.net>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Basque (http://www.transifex.com/projects/p/owncloud/language/eu/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: eu\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Ez da inportatzeko fitxategirik zehaztu"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Fitxategi mota hau ez da onartzen inportatzeko."
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Laster-markak"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Etiketak"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Iragazi etiketaren arabera"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Editatu laster-marka"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Ziur zaude etiketa hau sarrera guztietatik ezabatu nahi duzula?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Abisua"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Inportazio errorea"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Inportazioa ongi egin da."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Igotzen..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Lasterm."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Gehitu laster-marka"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Itxi"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Orriaren izenburua"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Orriaren helbidea"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Orriaren deskribapena"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Gorde"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Ezabatu"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Editatu"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Ezeztatu"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Web orri bat laster-marketara azkar gehitzeko, arrastratu hau zure arakatzailearen laster-marketara eta klikatu bertan:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Helbidea"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Gehitu"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Erlazionatutako etiketak"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Ezarpenak"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Ez duzu laster-markarik"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Laster-marka fitxategi bat inportatzen saia zaitezke"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Bookmarklet"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Exportatu eta inportatu"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Exportatu"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Inportatu"
diff --cc apps/bookmarks/l10n/fa/bookmarks.po
index 3144dd9,0000000..c9dbff7
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/fa/bookmarks.po
+++ b/apps/bookmarks/l10n/fa/bookmarks.po
@@@ -1,154 -1,0 +1,154 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# miki_mika1362 <miki_mika1362 at yahoo.com>, 2013
+# Mohammad Dashtizadeh <mohammad at dashtizadeh.net>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Persian (http://www.transifex.com/projects/p/owncloud/language/fa/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: fa\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "هیچ فایلی وارد نشده است."
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr ""
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "نشانکها"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "برچسبها"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "فیلتر بر اساس برچسب"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "ویرایش نشانک ها"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "آیا مطمئن هستید که میخواهید این برچسب را از هر مطلب حذف کنید؟"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "اخطار"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "وارد کردن خطا"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr ""
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "درحال بارگذاری..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr ""
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "اضافه کردن یک نشانک"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "بستن"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "عنوان صفحه"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "آدرس صحفه"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "توضیحات صفحه"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "ذخیره"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "حذف"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "ویرایش"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "منصرف شدن"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "هنگامی که میخواهید کی صفحهی اینترنتی را بسرعت نشان کنید، این را به نشانههای مرورگر خود بکشید و روی آن کلیک کنید."
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "آدرس"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "افزودن"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "برچسب های مرتبط"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "تنظیمات"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "شما هیچ نشانکی ندارید"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "شما میتوانید یک فایل نشانه دار را وارد نمایید."
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr ""
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "وارد کردن و خروجی گرفتن"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "خروجی گرفتن"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "وارد کردن"
diff --cc apps/bookmarks/l10n/fi_FI/bookmarks.po
index 57d6e94,0000000..b9c54e6
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/fi_FI/bookmarks.po
+++ b/apps/bookmarks/l10n/fi_FI/bookmarks.po
@@@ -1,154 -1,0 +1,154 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# variaatiox <ari.takalo at iki.fi>, 2012
+# Jiri Grönroos <jiri.gronroos at iki.fi>, 2012-2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-24 01:08-0500\n"
- "PO-Revision-Date: 2013-11-22 08:00+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: Jiri Grönroos <jiri.gronroos at iki.fi>\n"
+"Language-Team: Finnish (Finland) (http://www.transifex.com/projects/p/owncloud/language/fi_FI/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: fi_FI\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Yhtäkään tiedostoa ei määritetty tuotavaksi"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Tuonti ei tue kyseistä tiedostotyyppiä"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Kirjanmerkit"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Tunnisteet"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Suodata tunnisteen perusteella"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Muokkaa kirjanmerkkiä"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Haluatko varmasti poistaa tämän tunnisteen jokaiselta kohteelta?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Varoitus"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Tuontivirhe"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Tuonti valmistui onnistuneesti."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Lähetetään..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Kirjanm."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Lisää kirjanmerkki"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Sulje"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Sivun otsikko"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Sivun osoite"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Sivun kuvaus"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Tallenna"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Poista"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Muokkaa"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Peru"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Vedä tämä selaimesi kirjanmerkkipalkkiin ja napsauta sitä, kun haluat lisätä kirjanmerkin nopeasti:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr "Lisää ownCloudiin"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Osoite"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Lisää"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Vastaavanlaiset tunnisteet"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Asetukset"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Sinulla ei ole kirjanmerkkejä"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Voit myös yrittää tuoda kirjanmerkkitiedoston"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Kirjanmerkitsin"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Vienti ja tuonti"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Vie"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Tuo"
diff --cc apps/bookmarks/l10n/fr/bookmarks.po
index 92aa8bb,0000000..2a17f0c
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/fr/bookmarks.po
+++ b/apps/bookmarks/l10n/fr/bookmarks.po
@@@ -1,158 -1,0 +1,158 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Christophe Lherieau <skimpax at gmail.com>, 2012-2013
+# etiess <etiess at gmail.com>, 2013
+# fkhannouf <fkhannouf at me.com>, 2012
+# Geoffrey Guerrier <geoffrey.guerrier at gmail.com>, 2012
+# plachance <patlachance at gmail.com>, 2013
+# Romain DEP. <rom1dep at gmail.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-27 12:21-0500\n"
- "PO-Revision-Date: 2013-11-26 14:20+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: etiess <etiess at gmail.com>\n"
+"Language-Team: French (http://www.transifex.com/projects/p/owncloud/language/fr/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: fr\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Aucun fichier fourni pour l'importation"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Type de fichier non supporté pour l'importation"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Favoris"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Étiquettes"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtrer par étiquette"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Modifier le favori"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Êtes-vous certain de vouloir retirer cette étiquette de chaque entrée ?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Attention"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Erreur d'importation"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "L'importation s'est achevée avec succès."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Téléversement en cours…"
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Fav."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Ajouter un favori"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Fermer"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Le titre de la page"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "L'adresse de la page"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Description de la page"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Sauvegarder"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Supprimer"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Modifier"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Annuler"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Glissez ceci dans les favoris de votre navigateur et cliquer dessus lorsque vous souhaitez ajouter la page courante à vos marques-pages :"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr "Ajouter à ownCloud"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adresse"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Ajouter"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Étiquettes similaires"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Paramètres"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Vous n'avez aucun favori"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Vous pouvez également essayer l'import d'un fichier de favoris"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Applisignet"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Importer et exporter"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Exporter"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importer"
diff --cc apps/bookmarks/l10n/gl/bookmarks.po
index 071a5d1,0000000..203ad7d
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/gl/bookmarks.po
+++ b/apps/bookmarks/l10n/gl/bookmarks.po
@@@ -1,156 -1,0 +1,156 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# mbouzada <mbouzada at gmail.com>, 2013
+# mbouzada <mbouzada at gmail.com>, 2012
+# Miguel Branco <mgl.branco at gmail.com>, 2012
+# Xosé M. Lamas <correo.xmgz at gmail.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-24 01:08-0500\n"
- "PO-Revision-Date: 2013-11-22 07:30+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:40+0000\n"
+"Last-Translator: mbouzada <mbouzada at gmail.com>\n"
+"Language-Team: Galician (http://www.transifex.com/projects/p/owncloud/language/gl/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: gl\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Non foi fornecido un ficheiro para importar"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Tipo de ficheiro non admitido para a importación"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Marcadores"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Etiquetas"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtrar segundo a etiqueta"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Editar o marcador"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Confirma que quere eliminar esta etiqueta de todas as entradas?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Aviso"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Produciuse un erro na importación"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "A importación completouse correctamente."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Enviando..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Marc."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Engadir un marcador"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Pechar"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "O título da páxina"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "O enderezo desta páxina"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Descrición da páxina"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Gardar"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Eliminar"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Editar"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Arrastre isto aos marcadores do seu navegador e prema nel cando queira marcar unha páxina con rapidez:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr "Engadir no ownCloud"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Enderezo"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Engadir"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Etiquetas relacionadas"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Preferencias"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Non ten marcadores"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Tamén pode intentar importar un ficheiro de marcadores"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Marcador"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Exportar e importar"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Exportar"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importar"
diff --cc apps/bookmarks/l10n/he/bookmarks.po
index af6d15c,0000000..991c4c5
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/he/bookmarks.po
+++ b/apps/bookmarks/l10n/he/bookmarks.po
@@@ -1,155 -1,0 +1,155 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Gilad Naaman <gilad.doom at gmail.com>, 2012
+# Tomer Cohen <tomerc+transifex.net at gmail.com>, 2012
+# Yaron Shahrabani <sh.yaron at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:40+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Hebrew (http://www.transifex.com/projects/p/owncloud/language/he/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: he\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "לא סופק קובץ לייבוא"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "סוג הקובץ אינו ניתן לייבוא"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "סימניות"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "תגיות"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "סנן לפי תגית"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "ערוך סימניה"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "האם אתה בטוח שברצונך להסיר את התגית מכל הרשומות?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "אזהרה"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "שגיאת יבוא"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "ייבוא הושלם בהצלחה."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "העלאה..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "סימניה."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "הוסף סימניה"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "סגירה"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "כותרת הדף"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "כתובת הדף"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "תיאור הדף"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "שמירה"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "מחיקה"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "עריכה"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "ביטול"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "ניתן לגרור את הקישור הזה אל סרגל הסימניות בדפדפן שלך וללחוץ עליו כאשר מעוניינים ליצור סימניה לאתר במהירות."
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "כתובת"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "הוספה"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "תגיות קשורות"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "הגדרות"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "אין ברשותך סימניות"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "יש ביכולתך לייבא גם קובץ סימניות"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "יישומון סימנייה"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "ייבוא וייצוא"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "יצוא"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "יבא"
diff --cc apps/bookmarks/l10n/hr/bookmarks.po
index 9117579,0000000..a9dbd47
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/hr/bookmarks.po
+++ b/apps/bookmarks/l10n/hr/bookmarks.po
@@@ -1,152 -1,0 +1,152 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Croatian (http://www.transifex.com/projects/p/owncloud/language/hr/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: hr\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr ""
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr ""
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Zabilješke"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr ""
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr ""
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr ""
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr ""
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr ""
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr ""
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr ""
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr ""
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr ""
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr ""
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Zatvori"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr ""
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr ""
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr ""
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Snimi"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Obriši"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Uredi"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Odustani"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr ""
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adresa"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Dodaj"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr ""
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Postavke"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr ""
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr ""
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr ""
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr ""
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Izvoz"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Uvezi"
diff --cc apps/bookmarks/l10n/hu_HU/bookmarks.po
index 5644954,0000000..758d4db
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/hu_HU/bookmarks.po
+++ b/apps/bookmarks/l10n/hu_HU/bookmarks.po
@@@ -1,155 -1,0 +1,155 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Adam Toth <adazlord at gmail.com>, 2012
+# gyeben <gyonkibendeguz at gmail.com>, 2013
+# Laszlo Tornoci <torlasz at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:40+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Hungarian (Hungary) (http://www.transifex.com/projects/p/owncloud/language/hu_HU/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: hu_HU\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Nincs megadva az importálandó fájl"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Az importálandó fájltípus nem támogatott"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Könyvjelzők"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Címkék"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Szűrés címkék szerint"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Könyvjelző szerkesztése"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Biztos benne, hogy ezt a címkét el szeretné távolítani az összes bejegyzésből?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Figyelmeztetés"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Hiba történt az importáláskor"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Az importálás sikeresen befejeződött."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Feltöltés..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Könyvj."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Könyvjelző hozzáadása"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Bezár"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Az oldal neve"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Az oldal webcíme"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Az oldal leírása"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Mentés"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Törlés"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Szerkesztés"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Mégsem"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Húzza át ezt a gombot a böngészőprogram \"Könyvjelzők\" sávjába! Ha ezután rákattint, akkor az aktuális weboldal címét ide fogja menteni."
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Cím"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Hozzáad"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Kapcsolódó címkék"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Beállítások"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Nincsenek könyvjelzői"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Könyvjelzőket tartalmazó állomány is importálható"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Könyvjelző"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Export és import"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Exportálás"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importálás"
diff --cc apps/bookmarks/l10n/ia/bookmarks.po
index 9b29185,0000000..700af19
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/ia/bookmarks.po
+++ b/apps/bookmarks/l10n/ia/bookmarks.po
@@@ -1,152 -1,0 +1,152 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Interlingua (http://www.transifex.com/projects/p/owncloud/language/ia/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ia\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr ""
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr ""
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr ""
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr ""
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr ""
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr ""
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr ""
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr ""
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr ""
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr ""
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr ""
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr ""
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr ""
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Clauder"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr ""
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr ""
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr ""
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Salveguardar"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Deler"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Modificar"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Cancellar"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr ""
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adresse"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Adder"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr ""
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Configurationes"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr ""
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr ""
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr ""
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr ""
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Exportar"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importar"
diff --cc apps/bookmarks/l10n/id/bookmarks.po
index e94e7ab,0000000..86d52c8
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/id/bookmarks.po
+++ b/apps/bookmarks/l10n/id/bookmarks.po
@@@ -1,154 -1,0 +1,154 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# elmakong <mr.pige_ina at yahoo.co.id>, 2012
+# rodin <romihardiyanto at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Indonesian (http://www.transifex.com/projects/p/owncloud/language/id/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: id\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Tidak ada berkas untuk diimpor"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Tipe berkas tidak didukung untuk diimpor"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Markah"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Tag"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filter berdasar tag"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Edit markah"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Yakin ingin menghapus tag ini dari semua entri?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Peringatan"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Galat ketika mengimpor"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Proses impor selesai dengan sukses."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Mengunggah..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Markah"
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Tambah markah"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Tutup"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Judul halaman"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Alamat halaman"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Deskripsi halaman"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Simpan"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Hapus"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Edit"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Batal"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Seret ke bilah alat markah peramban Anda untuk diklik, jika Anda ingin membuat markah halaman web dengan cepat:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Alamat"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Tambah"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Tag terkait"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Setelan"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Anda tidak punya markah"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Anda juga dapat mengimpor berkas markah"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Bookmarklet"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Ekspor & Impor"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Ekspor"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Impor"
diff --cc apps/bookmarks/l10n/is/bookmarks.po
index cb10545,0000000..4c04916
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/is/bookmarks.po
+++ b/apps/bookmarks/l10n/is/bookmarks.po
@@@ -1,154 -1,0 +1,154 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Magnus Magnusson <maggiymir at gmail.com>, 2013
+# sveinn <sveinng at gmail.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:40+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Icelandic (http://www.transifex.com/projects/p/owncloud/language/is/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: is\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr ""
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Ekki er hægt að flytja inn þessa tegund af bókamerki"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Bókamerki"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Tagg"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Sía eftir töggum"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Breyta bókamerki"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Ertu viss um að þú viljir fjarlægja þetta tagg úr öllum færslum?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Aðvörun"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Innflutnings villa"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Tókst að flytja inn"
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Sendi inn ..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Bókam."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Bæta við bókamerki"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Loka"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Titill á síðunni"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Slóð á síðuna"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Lýsing á síðunni"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Vista"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Eyða"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Breyta"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Hætta við"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Dragðu þetta yfir í bókamerki í vafranum þínu og smelltu, ef þú vilt bæta við bókamerki fyrir þessa vefsíðu á fljótlegan hátt."
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Slóð"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Bæta við"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Skyld tögg"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Stillingar"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Þú hefur engin bókamerki"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Þú getur inni prófa að flytja inn bókamerkja skrá"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Bookmarklet"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Inn- og útflutningur"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Flytja út"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Flytja inn"
diff --cc apps/bookmarks/l10n/it/bookmarks.po
index 4ded23b,0000000..89c07ec
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/it/bookmarks.po
+++ b/apps/bookmarks/l10n/it/bookmarks.po
@@@ -1,153 -1,0 +1,153 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Vincenzo Reale <vinx.reale at gmail.com>, 2012-2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-24 01:08-0500\n"
- "PO-Revision-Date: 2013-11-22 21:10+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: Vincenzo Reale <vinx.reale at gmail.com>\n"
+"Language-Team: Italian (http://www.transifex.com/projects/p/owncloud/language/it/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: it\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Non è stato fornito alcun file da importare"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Tipo di file non supportato per l'importazione"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Segnalibri"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Tag"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtro per etichetta"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Modifica segnalibro"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Sei sicuro di voler rimuovere questo tag da ogni voce?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Avviso"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Errore di importazione"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Importazione completata correttamente."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Caricamento in corso..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Segnal."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Aggiungi un segnalibro"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Chiudi"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Il titolo della pagina"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "L'indirizzo della pagina"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Descrizione della pagina"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Salva"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Elimina"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Modifica"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Annulla"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Quando vuoi creare rapidamente un segnalibro, trascinalo sui segnalibri del browser e fai clic su di esso:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr "Aggiungi a ownCloud"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Indirizzo"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Aggiungi"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Tag correlati"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Impostazioni"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Non hai segnalibri"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Puoi anche provare a importare un file di segnalibri"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Bookmarklet"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Esporta e importa"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Esporta"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importa"
diff --cc apps/bookmarks/l10n/ja_JP/bookmarks.po
index 1182765,0000000..5ab7602
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/ja_JP/bookmarks.po
+++ b/apps/bookmarks/l10n/ja_JP/bookmarks.po
@@@ -1,154 -1,0 +1,154 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Daisuke Deguchi <ddeguchi at nagoya-u.jp>, 2012
+# Daisuke Deguchi <ddeguchi at nagoya-u.jp>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-29 14:17-0500\n"
- "PO-Revision-Date: 2013-11-29 11:40+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: Daisuke Deguchi <ddeguchi at nagoya-u.jp>\n"
+"Language-Team: Japanese (Japan) (http://www.transifex.com/projects/p/owncloud/language/ja_JP/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ja_JP\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "インポートするファイルが指定されていません"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "インポートでは未サポートのファイルタイプ"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "ブックマーク"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "タグ"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "タグによるフィルタ"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "ブックマークを編集"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "すべてのエントリからこのタグを削除してもよろしいですか?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "警告"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "インポートエラー"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "インポートは正常に完了しました。"
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "アップロード中..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "ブックマーク"
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "ブックマークを追加"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "閉じる"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "ページのタイトル"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "ページのアドレス"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "ページの説明"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "保存"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "削除"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "編集"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "キャンセル"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Webページをすぐにブックマークしたい場合は、これをブラウザのブックマークにドラッグし、クリックしてください:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr "ownCloud に追加"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "アドレス"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "追加"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "関連タグ"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "設定"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "ブックマークがありません"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "ブックマークファイルのインポートも可能です"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "ブックマークレット"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "エクスポート&インポート"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "エクスポート"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "インポート"
diff --cc apps/bookmarks/l10n/ka_GE/bookmarks.po
index 34e6d0c,0000000..223fb50
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/ka_GE/bookmarks.po
+++ b/apps/bookmarks/l10n/ka_GE/bookmarks.po
@@@ -1,154 -1,0 +1,154 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# drlinux64 <romeo at energo-pro.ge>, 2012
+# drlinux64 <romeo at energo-pro.ge>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Georgian (Georgia) (http://www.transifex.com/projects/p/owncloud/language/ka_GE/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ka_GE\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "არ არის ფაილი იმპორტისთვის"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "დაუშვებელი ფაილის ტიპი იმპორტისთვის"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "ბუქმარკები"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "ტაგები"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "ტეგების მიხედვით ფილტრაცია"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "ბუქმარკების რედაქტირება"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "დარწმუნებული ხართ რომ აღნიშნული ტაგის წაშლა გინდათ ყველა ჩანაწერიდა?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "გაფრთხილება"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "შეცდომა იმპორტის დროს"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "იმპორტირება დასრულებულია."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "მიმდინარეობს ატვირთვა..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Bookm."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "ბუქმარქში დამატება"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "დახურვა"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "გვერდის სათაური"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "გვერდის მისამართი"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "გვერდის დახასიათება"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "შენახვა"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "წაშლა"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "რედაქტირება"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "უარყოფა"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "გადაათრიეთ ეს თქვენს ბუქმარკებში თუ გინდათ რომ საითი სწრაფად დაბუქმარკდეს"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "მისამართი"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "დამატება"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Related Tags"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "პარამეტრები"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "თქვენ არ გაქვთ ბუქმარკები"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "თქვენ შეგიძლიათ აგრეთვე დააიმპორტოთ ბუქმარქ ფაილი"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "ბუქმარქლეტი"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "ექსპორტ & იმპორტი"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "ექსპორტი"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "იმპორტი"
diff --cc apps/bookmarks/l10n/ko/bookmarks.po
index 0fe4dbc,0000000..ce6533a
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/ko/bookmarks.po
+++ b/apps/bookmarks/l10n/ko/bookmarks.po
@@@ -1,155 -1,0 +1,155 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# 남자사람 <cessnagi at gmail.com>, 2012
+# 남자사람 <cessnagi at gmail.com>, 2012
+# Shinjo Park <kde at peremen.name>, 2012-2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:40+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Korean (http://www.transifex.com/projects/p/owncloud/language/ko/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ko\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "가져올 파일을 지정하지 않았음"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "가져올 수 없는 파일 형식임"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "책갈피"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "태그"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "태그로 필터링"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "책갈피 편집"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "모든 항목에서 이 태그를 삭제하시겠습니까?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "경고"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "가져오기 오류"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "성공적으로 가져왔습니다."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "업로드 중..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "책갈피"
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "책갈피 추가"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "닫기"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "페이지 제목"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "페이지 주소"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "페이지 설명"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "저장"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "삭제"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "편집"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "취소"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "웹 브라우저 책갈피 항목에 다음 링크를 끌어다 놓으면 나중에 볼 웹 페이지를 빠르게 구독할 때 사용할 수 있습니다:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "주소"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "추가"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "관련된 태그"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "설정"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "책갈피가 없습니다"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "책갈피 파일을 가져올 수 있습니다"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "북마크릿"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "내보내기 & 가져오기"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "내보내기"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "가져오기"
diff --cc apps/bookmarks/l10n/ku_IQ/bookmarks.po
index 4f7ff17,0000000..b166ee7
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/ku_IQ/bookmarks.po
+++ b/apps/bookmarks/l10n/ku_IQ/bookmarks.po
@@@ -1,153 -1,0 +1,153 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Hozha Koyi <hozhan at gmail.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Kurdish (Iraq) (http://www.transifex.com/projects/p/owncloud/language/ku_IQ/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ku_IQ\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr ""
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr ""
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "دڵخوازهکان"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "تاگهکان"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr ""
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr ""
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr ""
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "ئاگاداری"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr ""
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr ""
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr ""
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "نیشانکردن"
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr ""
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "داخستن"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr ""
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr ""
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr ""
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "پاشکهوتکردن"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr ""
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "دەسکاریکردن"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr ""
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "رابکێشه ئهمه بۆ دڵخوازهکان له وێبگهڕهکهت وه کرته بکه لێی، کاتێك دهتهوێت ماڵپهڕێك دڵخواز بکهی بهخێرای:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "ناونیشان"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "زیادکردن"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr ""
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "دهستكاری"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "تۆ دڵخوازت نیه"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr ""
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr ""
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr ""
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "ههناردن"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "هێنان"
diff --cc apps/bookmarks/l10n/lb/bookmarks.po
index 227e85f,0000000..e02ba8d
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/lb/bookmarks.po
+++ b/apps/bookmarks/l10n/lb/bookmarks.po
@@@ -1,153 -1,0 +1,153 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# llaera <llaera at outlook.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Luxembourgish (http://www.transifex.com/projects/p/owncloud/language/lb/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: lb\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Keen Type un fichier fir ze importeieren"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Onenerstetzen Format fir den Import"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Bookmarks"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Tags"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtreieren vun Tags"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Favoriten bearbeschten."
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Sidd dir secher all Tags vum erem Projet ze entfernen?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Warnung"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Import Fehler"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Import war erfolgraich"
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Upload..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Bookm."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Favorit beifügen"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Zoumaachen"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Den Titel vun der Sait"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "D'address vun der Sait."
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Beswchreiwung vun der Sait"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Späicheren"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Läschen"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Editéieren"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Ofbriechen"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Zitt eren Favorit an op den Browser vir een Short-Link ze kreien:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adress"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Dobäisetzen"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Bekannten Tags"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Astellungen"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Dir hud keng Favoriten"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Du kanns och een Favorite importeieren"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Favoriten Buch"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Exporteieren & Importeieren"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Exporteieren"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importeieren"
diff --cc apps/bookmarks/l10n/lt_LT/bookmarks.po
index 4ac4672,0000000..259a45d
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/lt_LT/bookmarks.po
+++ b/apps/bookmarks/l10n/lt_LT/bookmarks.po
@@@ -1,155 -1,0 +1,155 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Dr. ROX <to.dr.rox at gmail.com>, 2013
+# Dr. ROX <to.dr.rox at gmail.com>, 2012
+# Liudas Ališauskas <liudas.alisauskas at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-27 12:21-0500\n"
- "PO-Revision-Date: 2013-11-27 11:20+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: Liudas Ališauskas <liudas.alisauskas at gmail.com>\n"
+"Language-Team: Lithuanian (Lithuania) (http://www.transifex.com/projects/p/owncloud/language/lt_LT/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: lt_LT\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Nepateiktas failas importavimui"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Netinkamas failo tipas importavimui"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Žymekliai"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Žymės"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtruoti pagal žymę"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Redaguoti žymeles"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr ""
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Įspėjimas"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Importavimo klaida"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Importavimas baigtas sėkmingai."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Įkeliama..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Žym."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Pridėti žymelę"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Užverti"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Puslapio antraštė"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Puslapio adresas"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Puslapio aprašymas"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Išsaugoti"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Ištrinti"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Redaguoti"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Atšaukti"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr ""
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr "Pridėti į ownCloud"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adresas"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Pridėti"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Susijusios žymelės"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Nustatymai"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Jūs neturite žymelių"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Tai pat galite bandyti importuoti žymelių failą"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr ""
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Eksportavimas / Importavimas"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Eksportuoti"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importuoti"
diff --cc apps/bookmarks/l10n/lv/bookmarks.po
index cab7614,0000000..db429e2
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/lv/bookmarks.po
+++ b/apps/bookmarks/l10n/lv/bookmarks.po
@@@ -1,153 -1,0 +1,153 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Rūdolfs Mazurs <rudolfs.mazurs at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Latvian (http://www.transifex.com/projects/p/owncloud/language/lv/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: lv\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Neviena datne nav dota importēšanai"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Importēšanai neatbalstītie datņu tipi"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Grāmatzīmes"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Birkas"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Atlasīt pēc birkas"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Rediģēt grāmatzīmi"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Vai tiešām vēlaties izņemt šo birku no katra ieraksta?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Brīdinājums"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Importēšanas kļūda"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Importēšana ir veiksmīgi pabeigta."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Augšupielādē..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Grāmatz."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Pievienot grāmatzīmi"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Aizvērt"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Lapas virsraksts"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Lapas adrese"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Lapas apraksts"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Saglabāt"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Izdzēst"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Rediģēt"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Atcelt"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Ievelc šo savās pārlūka grāmatzīmēs un spied uz tā, kad vēlies ātri pievienot tīmekļa lapu grāmatzīmēm:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adrese"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Pievienot"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Saistītās birkas"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Iestatījumi"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Jums nav grāmatzīmju"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Jūs varat arī mēģināt importēt grāmatzīmes datni"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Sīkgrāmatzīme"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Eksportēt un importēt"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Eksportēt"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importēt"
diff --cc apps/bookmarks/l10n/mk/bookmarks.po
index 7bed1bf,0000000..9a388ef
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/mk/bookmarks.po
+++ b/apps/bookmarks/l10n/mk/bookmarks.po
@@@ -1,153 -1,0 +1,153 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Georgi Stanojevski <glisha at gmail.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:40+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Macedonian (http://www.transifex.com/projects/p/owncloud/language/mk/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: mk\n"
+"Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr ""
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Неподржнан тип на датотека за внес"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Обележувачи"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr ""
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr ""
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Уреди обележувач"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr ""
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Предупредување"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr ""
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Увозот заврши успешно"
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Подигнувам..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Обел."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Додади обележувач"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Затвои"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Насловот на страницата"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Адресата на страницата"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Опис на страницата"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Сними"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Избриши"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Уреди"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Откажи"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Повлечете го ова во папката со обележувачи во Вашиот прелистувач и кликнете го кога сакате брзо да направите обележувач:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Адреса"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Додади"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr ""
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Параметри"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Немате обележувачи"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Можете да се обидете да внесете датотека со обележувачи"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Обележувач"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Извези и увези"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Извези"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Внеси"
diff --cc apps/bookmarks/l10n/ms_MY/bookmarks.po
index d0d3ca9,0000000..039df78
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/ms_MY/bookmarks.po
+++ b/apps/bookmarks/l10n/ms_MY/bookmarks.po
@@@ -1,152 -1,0 +1,152 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Malay (Malaysia) (http://www.transifex.com/projects/p/owncloud/language/ms_MY/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ms_MY\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr ""
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr ""
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Tanda"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr ""
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr ""
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr ""
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr ""
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Amaran"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr ""
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr ""
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr ""
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr ""
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr ""
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Tutup"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr ""
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr ""
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr ""
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Simpan"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Padam"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Sunting"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Batal"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr ""
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Alamat"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Tambah"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr ""
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Tetapan"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr ""
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr ""
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr ""
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr ""
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Export"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Import"
diff --cc apps/bookmarks/l10n/nb_NO/bookmarks.po
index 1869ff9,0000000..eabe739
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/nb_NO/bookmarks.po
+++ b/apps/bookmarks/l10n/nb_NO/bookmarks.po
@@@ -1,157 -1,0 +1,157 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Arvid Nornes <arvid.nornes at gmail.com>, 2012
+# Hans Nesse <>, 2013
+# hdalgrav <hdalgrav at gmail.com>, 2012
+# troll <oyvind.hojem at gmail.com>, 2013
+# runesudden <runesudden at gmail.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Norwegian Bokmål (Norway) (http://www.transifex.com/projects/p/owncloud/language/nb_NO/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: nb_NO\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Ingen fil valgt for importering"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Ikke støttet filtype for importering"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Bokmerker"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Tagger"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtrer ut fra tag"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Endre bokmerke"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Er du sikker på at du vil slette denne taggen fra alle oppføringene?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Advarsel"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Importerings-feil"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Importering fullførte vellykket."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Laster opp..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Bokmrk."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Legg til et bokmerke"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Lukk"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Sidens tittel"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Sidens adresse"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Beskrivelse av siden"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Lagre"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Slett"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Endre"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Avbryt"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Dra denne til din nettlesers bokmerker, og klikk den når du ønsker å hurtig legge til en nettside som bokmerke:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adresse"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Legg til"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Relaterte tagger"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Innstillinger"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Du har ingen bokmerker"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Du kan også prøve å importere en bokmerke-fil"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Bokmerket"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Eksport og import"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Eksporter"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importer"
diff --cc apps/bookmarks/l10n/nl.php
index 683fb03,0000000..2cd0cb6
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/nl.php
+++ b/apps/bookmarks/l10n/nl.php
@@@ -1,34 -1,0 +1,35 @@@
+<?php $TRANSLATIONS = array(
+"No file provided for import" => "Geen bestand voor import opgegeven",
+"Unsupported file type for import" => "Niet ondersteund bestandstype voor import",
+"Bookmarks" => "Bladwijzers",
+"Tags" => "Tags",
+"Filter by tag" => "Filter op tag",
+"Edit bookmark" => "Bewerk bladwijzer",
+"Are you sure you want to remove this tag from every entry?" => "Bent u zeker dat u deze tag van elk item wilt verwijderen.",
+"Warning" => "Waarschuwing",
+"Import error" => "Import fout",
+"Import completed successfully." => "Het importeren is helemaal geslaagd",
+"Uploading..." => "Uploading...",
+"Bookm." => "Bladw.",
+"Add a bookmark" => "Voeg een bladwijzer toe",
+"Close" => "Sluit",
+"The title of the page" => "De pagina titel",
+"The address of the page" => "Het pagina adres",
+"Description of the page" => "Pagina beschrijving",
+"Save" => "Bewaar",
+"Delete" => "Verwijder",
+"Edit" => "Bewerk",
+"Cancel" => "Annuleer",
+"Drag this to your browser bookmarks and click it, when you want to bookmark a webpage quickly:" => "Sleep dit naar uw browser bladwijzer menu en klik erop, wanneer u een webpagina snel wilt voorzien van een bladwijzer:",
++"Add to ownCloud" => "Toevoegen aan ownCloud",
+"Address" => "Adres",
+"Add" => "Toevoegen",
+"Related Tags" => "Aanverwante tags",
+"Settings" => "Instellingen",
+"You have no bookmarks" => "U heeft geen bladwijzers",
+"You can also try to import a bookmark file" => "U kan ook een bladwijzer bestand proberen te importen",
+"Bookmarklet" => "Bookmarklet",
+"Export & Import" => "Export & Import",
+"Export" => "Exporteer",
+"Import" => "Importeer"
+);
diff --cc apps/bookmarks/l10n/nl/bookmarks.po
index 1269eab,0000000..f29def5
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/nl/bookmarks.po
+++ b/apps/bookmarks/l10n/nl/bookmarks.po
@@@ -1,155 -1,0 +1,155 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# André Koot <meneer at tken.net>, 2013
+# diederikdehaas <didi.debian at cknow.org>, 2012
+# Richard Bos <radoeka at gmail.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
- "Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
++"Last-Translator: André Koot <meneer at tken.net>\n"
+"Language-Team: Dutch (http://www.transifex.com/projects/p/owncloud/language/nl/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: nl\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Geen bestand voor import opgegeven"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Niet ondersteund bestandstype voor import"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Bladwijzers"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Tags"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filter op tag"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Bewerk bladwijzer"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Bent u zeker dat u deze tag van elk item wilt verwijderen."
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Waarschuwing"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Import fout"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Het importeren is helemaal geslaagd"
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Uploading..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Bladw."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Voeg een bladwijzer toe"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Sluit"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "De pagina titel"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Het pagina adres"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Pagina beschrijving"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Bewaar"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Verwijder"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Bewerk"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Annuleer"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Sleep dit naar uw browser bladwijzer menu en klik erop, wanneer u een webpagina snel wilt voorzien van een bladwijzer:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
- msgstr ""
++msgstr "Toevoegen aan ownCloud"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adres"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Toevoegen"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Aanverwante tags"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Instellingen"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "U heeft geen bladwijzers"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "U kan ook een bladwijzer bestand proberen te importen"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Bookmarklet"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Export & Import"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Exporteer"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importeer"
diff --cc apps/bookmarks/l10n/nn_NO/bookmarks.po
index 7b8fed5,0000000..007a697
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/nn_NO/bookmarks.po
+++ b/apps/bookmarks/l10n/nn_NO/bookmarks.po
@@@ -1,153 -1,0 +1,153 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# unhammer <unhammer+dill at mm.st>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Norwegian Nynorsk (Norway) (http://www.transifex.com/projects/p/owncloud/language/nn_NO/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: nn_NO\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Inga fil gjeve for importering"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Ustøtta filtype for importering"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Bokmerkje"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Emneord"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtrer etter emneord"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Endra bokmerkje"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Er du sikker på at du vil fjerna dette emneordet frå alle oppføringane?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Åtvaring"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Feil ved importering"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Importering fullførte utan feil."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Lastar opp …"
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Bokm."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Legg til eit bokmerkje"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Lukk"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Tittelen på sida"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Adressa til sida"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Skildring av sida"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Lagra"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Slett"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Endra"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Avbryt"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Dra denne knappen til bokmerkjelinja i nettlesaren din og klikk han når du vil laga eit bokmerkje raskt:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adresse"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Legg til"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Liknande emneord"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Innstillingar"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Du har inga bokmerkje"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Du kan òg prøva å importera ei bokmerkjefil"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Bokmerkjeknapp"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Eksporter/importer"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Eksporter"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importer"
diff --cc apps/bookmarks/l10n/oc/bookmarks.po
index 2f0e2f6,0000000..61d1066
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/oc/bookmarks.po
+++ b/apps/bookmarks/l10n/oc/bookmarks.po
@@@ -1,152 -1,0 +1,152 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:40+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Occitan (post 1500) (http://www.transifex.com/projects/p/owncloud/language/oc/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: oc\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr ""
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr ""
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Marcapaginas"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr ""
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr ""
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr ""
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr ""
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr ""
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr ""
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr ""
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr ""
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr ""
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr ""
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr ""
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr ""
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr ""
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr ""
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Enregistra"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Escafa"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Editar"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Annula"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr ""
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr ""
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Ajusta"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr ""
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Configuracion"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr ""
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr ""
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr ""
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr ""
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Exporta"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importa"
diff --cc apps/bookmarks/l10n/pl/bookmarks.po
index 3300b35,0000000..01852fb
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/pl/bookmarks.po
+++ b/apps/bookmarks/l10n/pl/bookmarks.po
@@@ -1,154 -1,0 +1,154 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Cyryl Sochacki <cyrylsochacki at gmail.com>, 2012
+# Cyryl Sochacki <cyrylsochacki at gmail.com>, 2012-2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:40+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Polish (http://www.transifex.com/projects/p/owncloud/language/pl/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: pl\n"
+"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Nie wybrano plików do importu"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Nieobsługiwany typ pliku do importu"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Zakładki"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Tagi"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtruj po tagach"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Edytuj zakładkę"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Czy na pewno chcesz usunąć ten tag na każdym wejściu?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Ostrzeżenie"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Błąd importu"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Importowanie zostało pomyślnie ukończone."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Wgrywanie...."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Zakładka"
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Dodaj zakładkę"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Zamknij"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Tytuł strony"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Adres strony"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Opis strony"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Zapisz"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Usuń"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Edytuj"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Anuluj"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Przeciągnij to do ulubionych przeglądarki i kliknij go, gdy użytkownik chce szybko dodać zakładkę strony sieci Web:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adres"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Dodaj"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Powiązane Tagi"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Ustawienia"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Nie masz żadnych zakładek"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Można również spróbować zaimportować plik zakładki"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Zakładka"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Eksportuj i Importuj"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Export"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Import"
diff --cc apps/bookmarks/l10n/pt_BR/bookmarks.po
index 738bc22,0000000..28b41b3
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/pt_BR/bookmarks.po
+++ b/apps/bookmarks/l10n/pt_BR/bookmarks.po
@@@ -1,158 -1,0 +1,158 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# dudanogueira <dudanogueira at gmail.com>, 2013
+# dudanogueira <dudanogueira at gmail.com>, 2012
+# Flávio Veras <flaviove at gmail.com>, 2013
+# henriquemeira <henrique at meira.net>, 2012
+# sedir <philippi.sedir at gmail.com>, 2012
+# thoriumbr <thoriumbr at gmail.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-24 01:08-0500\n"
- "PO-Revision-Date: 2013-11-22 10:10+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: Flávio Veras <flaviove at gmail.com>\n"
+"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/owncloud/language/pt_BR/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: pt_BR\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Arquivo para importação não fornecido"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Arquivo para importação não suportado"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Marcadores"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Tags"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtrar por tag"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Editar marcador"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Tem certeza que deseja remover esta tag de todas as entradas?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Aviso"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Error ao Importar"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Importação completada com sucesso"
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Enviando..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Marc."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Adicionar um marcador"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Fechar"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "O título da página"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "O endereço da página"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Descrição da página"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Salvar"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Excluir"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Editar"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Arraste isso para os favoritos do seu navegador web e clique nele quando você quiser marcar/favoritar uma página rapidamente:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr "Adicionar ao ownCloud"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Endereço"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Adicionar"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Tags Relacionadas"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Ajustes"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Você não tem marcadores"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Você também pode tentar importar um arquivo de marcadores."
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Bookmarklet"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Exportar e Importar"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Exportar"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importar"
diff --cc apps/bookmarks/l10n/pt_PT.php
index eeac5cc,0000000..326b053
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/pt_PT.php
+++ b/apps/bookmarks/l10n/pt_PT.php
@@@ -1,34 -1,0 +1,35 @@@
+<?php $TRANSLATIONS = array(
+"No file provided for import" => "Não foi selecionado nenhum ficheiro para importar",
+"Unsupported file type for import" => "Tipo de ficheiro não suportado para importação",
+"Bookmarks" => "Marcadores",
+"Tags" => "Etiquetas",
+"Filter by tag" => "Filtrar por tag",
+"Edit bookmark" => "Editar marcador",
+"Are you sure you want to remove this tag from every entry?" => "Tem a certeza de que quer remover esta etiqueta de cada registo?",
+"Warning" => "Aviso",
+"Import error" => "Erro na importação",
+"Import completed successfully." => "Importação bem sucedida.",
+"Uploading..." => "A enviar...",
+"Bookm." => "Marc.",
+"Add a bookmark" => "Acrescentar um marcador",
+"Close" => "Fechar",
+"The title of the page" => "O titulo da página",
+"The address of the page" => "O endereço da página",
+"Description of the page" => "Descrição da página",
+"Save" => "Guardar",
+"Delete" => "Apagar",
+"Edit" => "Editar",
+"Cancel" => "Cancelar",
+"Drag this to your browser bookmarks and click it, when you want to bookmark a webpage quickly:" => "Arraste isto para o seu navegador, e clique nele quando quiser guardar a página rapidamente com um marcador.",
++"Add to ownCloud" => "Adicionar ao ownCloud",
+"Address" => "Endereço",
+"Add" => "Adicionar",
+"Related Tags" => "Etiquetas relacionadas",
+"Settings" => "Configurações",
+"You have no bookmarks" => "Não tem marcadores",
+"You can also try to import a bookmark file" => "Também pode tentar importar o ficheiro de favoritos",
+"Bookmarklet" => "Marcadorzinho",
+"Export & Import" => "Exportar & Importar",
+"Export" => "Exportar",
+"Import" => "Importar"
+);
diff --cc apps/bookmarks/l10n/pt_PT/bookmarks.po
index 2d0f3da,0000000..7df532f
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/pt_PT/bookmarks.po
+++ b/apps/bookmarks/l10n/pt_PT/bookmarks.po
@@@ -1,156 -1,0 +1,157 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# carlosamp <carlos.am.pereira at hotmail.com>, 2013
+# Mouxy <daniel at mouxy.net>, 2012
+# Mouxy <daniel at mouxy.net>, 2013
+# Duarte Velez Grilo <duartegrilo at gmail.com>, 2012
++# PapiMigas Migas <papimigas at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
- "Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
++"POT-Creation-Date: 2013-12-04 18:12-0500\n"
++"PO-Revision-Date: 2013-12-03 11:40+0000\n"
++"Last-Translator: PapiMigas Migas <papimigas at gmail.com>\n"
+"Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/owncloud/language/pt_PT/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: pt_PT\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Não foi selecionado nenhum ficheiro para importar"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Tipo de ficheiro não suportado para importação"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Marcadores"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Etiquetas"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtrar por tag"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Editar marcador"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Tem a certeza de que quer remover esta etiqueta de cada registo?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Aviso"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Erro na importação"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Importação bem sucedida."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "A enviar..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Marc."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Acrescentar um marcador"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Fechar"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "O titulo da página"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "O endereço da página"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Descrição da página"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Guardar"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Apagar"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Editar"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Arraste isto para o seu navegador, e clique nele quando quiser guardar a página rapidamente com um marcador."
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
- msgstr ""
++msgstr "Adicionar ao ownCloud"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Endereço"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Adicionar"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Etiquetas relacionadas"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Configurações"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Não tem marcadores"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Também pode tentar importar o ficheiro de favoritos"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Marcadorzinho"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Exportar & Importar"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Exportar"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importar"
diff --cc apps/bookmarks/l10n/ro/bookmarks.po
index b87a867,0000000..4601319
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/ro/bookmarks.po
+++ b/apps/bookmarks/l10n/ro/bookmarks.po
@@@ -1,156 -1,0 +1,156 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# corneliu.e <corneliueva at yahoo.com>, 2013
+# Dimon Pockemon <>, 2013
+# g.ciprian <g.ciprian at osn.ro>, 2012
+# ripkid666 <ripkid666 at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Romanian (http://www.transifex.com/projects/p/owncloud/language/ro/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ro\n"
+"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Niciun fișier furnizat pentru import"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Tipul de fișier nu este suportat pentru importări"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Semne de carte"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Cuvinte cheie"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtrare după marcaj"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Editează semn de carte"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Ești sigur că vrei să ștergi acest marcaj din fiecare înscriere?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Atenție"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Eroare de import"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Importarea a fost completată cu succes"
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Încărcare..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Bookm."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Adaugă un semn de carte"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Închide"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Titlul paginii"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Adresa paginii"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Descrierea paginii"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Salvează"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Șterge"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Editează"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Anulare"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Trage acest semn în semnele de carte din navigatorul tău web când dorești să salvezi rapid un semn către o pagină web:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adresă"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Adaugă"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Marcaje asemănătoare"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Setări"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Nu ai niciun semn de carte"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "De asemenea puteți să încercați importarea unui fișier cu semne de carte"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Marcator"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Exportă & Importă"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Exportă"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importă"
diff --cc apps/bookmarks/l10n/ru.php
index d84e028,0000000..28a06e4
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/ru.php
+++ b/apps/bookmarks/l10n/ru.php
@@@ -1,34 -1,0 +1,35 @@@
+<?php $TRANSLATIONS = array(
+"No file provided for import" => "Ни один файл не предоставлен для импорта",
+"Unsupported file type for import" => "Не подходящий тип файла для импорта",
+"Bookmarks" => "Закладки",
+"Tags" => "Метки",
+"Filter by tag" => "Фильтр по тегу",
+"Edit bookmark" => "Редактировать закладку",
+"Are you sure you want to remove this tag from every entry?" => "Вы уверены, что хотите удалить этот тег из каждой записи?",
+"Warning" => "Предупреждение",
+"Import error" => "Ошибка импорта",
+"Import completed successfully." => "Импортирование завершилось успешно.",
+"Uploading..." => "Загрузка...",
+"Bookm." => "Закл.",
+"Add a bookmark" => "Добавить закладку",
+"Close" => "Закрыть",
+"The title of the page" => "Заголовок страницы",
+"The address of the page" => "Адрес страницы",
+"Description of the page" => "Описание страницы",
+"Save" => "Сохранить",
+"Delete" => "Удалить",
+"Edit" => "Редактировать",
+"Cancel" => "Отменить",
+"Drag this to your browser bookmarks and click it, when you want to bookmark a webpage quickly:" => "Перетащите эту кнопку в закладки вашего браузера и нажимайте на неё для быстрого добавления страницы в закладки:",
++"Add to ownCloud" => "Добавить в ownCloud",
+"Address" => "Адрес",
+"Add" => "Добавить",
+"Related Tags" => "Связанные теги",
+"Settings" => "Конфигурация",
+"You have no bookmarks" => "У вас нет закладок",
+"You can also try to import a bookmark file" => "Вы также можете попробовать импортировать файл закладки",
+"Bookmarklet" => "Bookmarklet",
+"Export & Import" => "Экспорт & Импорт",
+"Export" => "Экспорт",
+"Import" => "Импорт"
+);
diff --cc apps/bookmarks/l10n/ru/bookmarks.po
index f1abd89,0000000..af3ad87
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/ru/bookmarks.po
+++ b/apps/bookmarks/l10n/ru/bookmarks.po
@@@ -1,156 -1,0 +1,157 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Denis <reg.transifex.net at demitel.ru>, 2012
+# skoptev <skoptev at ukr.net>, 2012
+# VicDeo <victor.dubiniuk at gmail.com>, 2012
++# vsapronov <vladimir.sapronov at gmail.com>, 2013
+# Langaru <langaru at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
- "Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:40+0000\n"
++"Last-Translator: vsapronov <vladimir.sapronov at gmail.com>\n"
+"Language-Team: Russian (http://www.transifex.com/projects/p/owncloud/language/ru/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ru\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Ни один файл не предоставлен для импорта"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Не подходящий тип файла для импорта"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Закладки"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Метки"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Фильтр по тегу"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Редактировать закладку"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Вы уверены, что хотите удалить этот тег из каждой записи?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Предупреждение"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Ошибка импорта"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Импортирование завершилось успешно."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Загрузка..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Закл."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Добавить закладку"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Закрыть"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Заголовок страницы"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Адрес страницы"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Описание страницы"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Сохранить"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Удалить"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Редактировать"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Отменить"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Перетащите эту кнопку в закладки вашего браузера и нажимайте на неё для быстрого добавления страницы в закладки:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
- msgstr ""
++msgstr "Добавить в ownCloud"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Адрес"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Добавить"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Связанные теги"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Конфигурация"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "У вас нет закладок"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Вы также можете попробовать импортировать файл закладки"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Bookmarklet"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Экспорт & Импорт"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Экспорт"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Импорт"
diff --cc apps/bookmarks/l10n/ru_RU.php
index e246608,0000000..ae63dd3
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/ru_RU.php
+++ b/apps/bookmarks/l10n/ru_RU.php
@@@ -1,8 -1,0 +1,9 @@@
+<?php $TRANSLATIONS = array(
+"Bookmarks" => "Закладки",
+"Warning" => "Предупреждение",
+"Save" => "Сохранить",
+"Delete" => "Удалить",
++"Edit" => "Редактировать",
+"Cancel" => "Отмена",
+"Settings" => "Настройки"
+);
diff --cc apps/bookmarks/l10n/ru_RU/bookmarks.po
index 236e32f,0000000..858df7b
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/ru_RU/bookmarks.po
+++ b/apps/bookmarks/l10n/ru_RU/bookmarks.po
@@@ -1,153 -1,0 +1,153 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# AnnaSch <cdewqazxsqwe at gmail.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:50+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Russian (Russia) (http://www.transifex.com/projects/p/owncloud/language/ru_RU/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ru_RU\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr ""
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr ""
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Закладки"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr ""
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr ""
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr ""
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr ""
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Предупреждение"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr ""
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr ""
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr ""
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr ""
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr ""
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr ""
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr ""
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr ""
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr ""
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Сохранить"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Удалить"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
- msgstr ""
++msgstr "Редактировать"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Отмена"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr ""
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr ""
+
+#: templates/list.php:23
+msgid "Add"
+msgstr ""
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr ""
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Настройки"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr ""
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr ""
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr ""
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr ""
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr ""
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr ""
diff --cc apps/bookmarks/l10n/si_LK/bookmarks.po
index f78b0af,0000000..b3868a8
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/si_LK/bookmarks.po
+++ b/apps/bookmarks/l10n/si_LK/bookmarks.po
@@@ -1,154 -1,0 +1,154 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Anushke Guneratne <anushke at gmail.com>, 2012
+# Chamara Disanayake <chamara at nic.lk>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:40+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Sinhala (Sri Lanka) (http://www.transifex.com/projects/p/owncloud/language/si_LK/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: si_LK\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr ""
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "ආයාත කරන ගොනුව රුචි නොවේ"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "පිටු සළකුනු"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "ටැග"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "ටැගය ආධාරයෙන් පෙරන්න"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "පිටු සළකුනු සකසන්න"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "මෙම ටැගය සියළු ඇතුලත් කිරීමකින් ඉවත් කරන බව ඔබට සහතිකද"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "අනතුරු ඇඟවිම"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr ""
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "ආයාත කිරීම සාර්ථකයි"
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "උඩුගත කෙරේ..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "පිටුසන"
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "පිටු සළකුනක් එක් කරන්න"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "වසන්න"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "පිටුවේ මාතෘකාව"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "පිටුවේ ලිපිනය"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "පිටුවේ විස්තර"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "සුරකින්න"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "මකන්න"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "සකසන්න"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "එපා"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "මෙම වෙබ් පිටුව ඉක්මනින් පිටු සළකුනක් ලෙස සටහන් කිරීමට, එය බ්රවුසරයේ පිටු සළකුනු මතට ඇද ක්ලික් කරන්න:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "ලිපිනය"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "එකතු කරන්න"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "අදාළ ටැගයන්"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "සිටුවම්"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "පිටු සළකුනු නොමැත"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "පිටුසන අඩංගු ගොනුවක් ආයාත කිරීමට උත්සහ කළ හැක"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr ""
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "ආයාත හා නිර්යාත"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "නිර්යාත කරන්න"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "ආයාත කරන්න"
diff --cc apps/bookmarks/l10n/sk_SK.php
index 2a6d473,0000000..b4a8229
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/sk_SK.php
+++ b/apps/bookmarks/l10n/sk_SK.php
@@@ -1,34 -1,0 +1,35 @@@
+<?php $TRANSLATIONS = array(
+"No file provided for import" => "Žiadny súbor na import",
+"Unsupported file type for import" => "Nepodporovaný typ súboru pre import",
+"Bookmarks" => "Záložky",
+"Tags" => "Značky",
+"Filter by tag" => "Filtrovať podľa značky",
+"Edit bookmark" => "Upraviť záložku",
+"Are you sure you want to remove this tag from every entry?" => "Naozaj ste si istý, že chcete odstrániť túto značku z každého záznamu?",
+"Warning" => "Upozornenie",
+"Import error" => "Chyba importu",
+"Import completed successfully." => "Import prebehol úspešne.",
+"Uploading..." => "Odosielanie...",
+"Bookm." => "Zál.",
+"Add a bookmark" => "Pridať záložku",
+"Close" => "Zavrieť",
+"The title of the page" => "Názov stránky",
+"The address of the page" => "Adresa stránky",
+"Description of the page" => "Popis stránky",
+"Save" => "Uložiť",
+"Delete" => "Zmazať",
+"Edit" => "Upraviť",
+"Cancel" => "Zrušiť",
+"Drag this to your browser bookmarks and click it, when you want to bookmark a webpage quickly:" => "Presuňte toto do vášho prehliadača a kliknite ak chcete aktuálnu stránku uložiť do záložiek.",
++"Add to ownCloud" => "Pridať do ownCloudu",
+"Address" => "Adresa",
+"Add" => "Pridať",
+"Related Tags" => "Podobné značky",
+"Settings" => "Nastavenia",
+"You have no bookmarks" => "Nemáte žiadne záložky",
+"You can also try to import a bookmark file" => "Môžte tiež skúsiť import súboru zo záložkami.",
+"Bookmarklet" => "Bookmarklet",
+"Export & Import" => "Export & Import",
+"Export" => "Export",
+"Import" => "Import"
+);
diff --cc apps/bookmarks/l10n/sk_SK/bookmarks.po
index a35beb3,0000000..5554490
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/sk_SK/bookmarks.po
+++ b/apps/bookmarks/l10n/sk_SK/bookmarks.po
@@@ -1,156 -1,0 +1,156 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# mhh <marian.hvolka at stuba.sk>, 2013
+# martinb <martin.babik at gmail.com>, 2012
+# Roman Priesol <roman at priesol.net>, 2012
+# martin, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
- "Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
++"Last-Translator: mhh <marian.hvolka at stuba.sk>\n"
+"Language-Team: Slovak (Slovakia) (http://www.transifex.com/projects/p/owncloud/language/sk_SK/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: sk_SK\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Žiadny súbor na import"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Nepodporovaný typ súboru pre import"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Záložky"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Značky"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtrovať podľa značky"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Upraviť záložku"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Naozaj ste si istý, že chcete odstrániť túto značku z každého záznamu?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Upozornenie"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Chyba importu"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Import prebehol úspešne."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Odosielanie..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Zál."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Pridať záložku"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Zavrieť"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Názov stránky"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Adresa stránky"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Popis stránky"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Uložiť"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Zmazať"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Upraviť"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Zrušiť"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Presuňte toto do vášho prehliadača a kliknite ak chcete aktuálnu stránku uložiť do záložiek."
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
- msgstr ""
++msgstr "Pridať do ownCloudu"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adresa"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Pridať"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Podobné značky"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Nastavenia"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Nemáte žiadne záložky"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Môžte tiež skúsiť import súboru zo záložkami."
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Bookmarklet"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Export & Import"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Export"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Import"
diff --cc apps/bookmarks/l10n/sl/bookmarks.po
index 5e3b5b4,0000000..322e4a6
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/sl/bookmarks.po
+++ b/apps/bookmarks/l10n/sl/bookmarks.po
@@@ -1,155 -1,0 +1,155 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# mateju <>, 2012
+# mateju <>, 2013
+# Peter Peroša <peter.perosa at gmail.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-24 01:08-0500\n"
- "PO-Revision-Date: 2013-11-22 21:50+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: mateju <>\n"
+"Language-Team: Slovenian (http://www.transifex.com/projects/p/owncloud/language/sl/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: sl\n"
+"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Ni navedene datoteke za uvoz"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Vrsta datoteke ni podprta za uvoz"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Zaznamki"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Oznake"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Razvrsti po oznakah"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Uredi zaznamke"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Ali res želite odstraniti te oznake iz vsakega vnosa?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Opozorilo"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Napaka med uvozom"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Uvoz je uspešno zaključen."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Poteka pošiljanje ..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Zaznam."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Dodaj zaznamek"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Zapri"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Naziv strani"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Naslov strani"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Opis strani"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Shrani"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Izbriši"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Uredi"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Prekliči"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Povlecite gumb med zaznamke in kliknite nanj, kadar želite obiskano spletno stran hitro dodati med svoje zaznamke:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr "Dodaj v oblak ownCloud"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Naslov"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Dodaj"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Sorodne oznake"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Nastavitve"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Ni shranjenih zaznamkov"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Prav tako je mogoče uvoziti datoteko z zaznamki"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Vstavek za zaznamke"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Izvoz in uvoz"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Izvozi"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Uvozi"
diff --cc apps/bookmarks/l10n/sq/bookmarks.po
index 9d54df3,0000000..a2ea419
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/sq/bookmarks.po
+++ b/apps/bookmarks/l10n/sq/bookmarks.po
@@@ -1,152 -1,0 +1,152 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:40+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Albanian (http://www.transifex.com/projects/p/owncloud/language/sq/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: sq\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr ""
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr ""
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr ""
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr ""
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr ""
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr ""
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr ""
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr ""
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr ""
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr ""
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr ""
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr ""
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr ""
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr ""
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr ""
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr ""
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr ""
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Ruaj"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Elimino"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Ndrysho"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Anulo"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr ""
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adresa"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Shto"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr ""
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Parametrat"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr ""
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr ""
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr ""
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr ""
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Eksporto"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importo"
diff --cc apps/bookmarks/l10n/sr/bookmarks.po
index 4569e3a,0000000..1f3aa72
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/sr/bookmarks.po
+++ b/apps/bookmarks/l10n/sr/bookmarks.po
@@@ -1,154 -1,0 +1,154 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Kostic <marko at evizo.com>, 2012
+# Rancher <djordje.vasiljevich at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:40+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Serbian (http://www.transifex.com/projects/p/owncloud/language/sr/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: sr\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr ""
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Неподржана врста датотеке за увоз"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Обележивачи"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Ознаке"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Филтрирај по ознаци"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Уреди обележивач"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Желите ли да уклоните ову ознаку из сваког уноса?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Упозорење"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr ""
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Увоз је успешно завршен."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Отпремам…"
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Обележ."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Додај обележивач"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Затвори"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Наслов странице"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Адреса странице"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Опис странице"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Сачувај"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Обриши"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Уреди"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Откажи"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Превуците ово у прегледач и кликните ако на брзину желите да обележите веб страницу:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Адреса"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Додај"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Сродне ознаке"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Поставке"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Немате обележиваче"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Можете да пробате да увезете и датотеку са обележивачима"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Активан обележивач"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Извоз и увоз"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Извези"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Увези"
diff --cc apps/bookmarks/l10n/sr at latin/bookmarks.po
index 4dcc055,0000000..c154a33
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/sr at latin/bookmarks.po
+++ b/apps/bookmarks/l10n/sr at latin/bookmarks.po
@@@ -1,152 -1,0 +1,152 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:40+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Serbian (Latin) (http://www.transifex.com/projects/p/owncloud/language/sr@latin/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: sr at latin\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr ""
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr ""
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr ""
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr ""
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr ""
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr ""
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr ""
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr ""
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr ""
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr ""
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr ""
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr ""
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr ""
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Zatvori"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr ""
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr ""
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr ""
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Snimi"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Obriši"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Uredi"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Otkaži"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr ""
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adresa"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Dodaj"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr ""
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Podešavanja"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr ""
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr ""
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr ""
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr ""
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr ""
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr ""
diff --cc apps/bookmarks/l10n/sv/bookmarks.po
index 9a2f784,0000000..11e9c3b
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/sv/bookmarks.po
+++ b/apps/bookmarks/l10n/sv/bookmarks.po
@@@ -1,156 -1,0 +1,156 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Lokal_Profil <lokal_profil at hotmail.com>, 2013
+# kallemooo <karl.h.thoren at gmail.com>, 2013
+# Magnus Höglund <magnus at linux.com>, 2012
+# Magnus Höglund <magnus at linux.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-26 04:11-0500\n"
- "PO-Revision-Date: 2013-11-24 19:30+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: kallemooo <karl.h.thoren at gmail.com>\n"
+"Language-Team: Swedish (http://www.transifex.com/projects/p/owncloud/language/sv/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: sv\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Ingen fil försedd för import"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Filtypen stöds ej för import"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Bokmärken"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Taggar"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Filtrera på etikett"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Redigera bokmärke"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Är du säker på att du vill ta bort denna tagg från varje post?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Varning"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Importfel"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Import slutförd."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Laddar upp..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Bokm."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Lägg till ett bokmärke"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Stäng"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Titel på sidan"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Adress till sidan"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Beskrivning av sidan"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Spara"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Radera"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Redigera"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Avbryt"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Dra till din webbläsares bokmärken och klicka på det när du vill bokmärka en webbsida snabbt:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr "Lägg till på ownCloud"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adress"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Lägg till"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Relaterade taggar"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Inställningar"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Du har inga bokmärken"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Du kan också försöka att importera en bokmärkesfil"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Bokmärke"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Export & Import"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Exportera"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Importera"
diff --cc apps/bookmarks/l10n/ta_LK/bookmarks.po
index 5ee43cb,0000000..b281c03
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/ta_LK/bookmarks.po
+++ b/apps/bookmarks/l10n/ta_LK/bookmarks.po
@@@ -1,153 -1,0 +1,153 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# suganthi <suganthi at nic.lk>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Tamil (Sri-Lanka) (http://www.transifex.com/projects/p/owncloud/language/ta_LK/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ta_LK\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr ""
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "இறக்குமதிக்கு ஆதரவளிக்காத கோப்பு வகை"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "பக்க அடையாளங்கள்"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "சீட்டுகள்"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "சீட்டுகளால் வடிகட்டுக"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "பக்க அடையாளத் தொகுக்க "
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "ஒவ்வொரு நுழைவின் போதும் இந்த சீட்டை கட்டாயம் அகற்ற வேண்டுமா?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "எச்சரிக்கை"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr ""
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "இறக்குமதி வெற்றிகரமாக நிறைவேற்றப்பட்டது."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "பதிவேற்றல்..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "பக்க அடையாளங்கள்"
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "பக்க அடையாளம் ஒன்றை சேர்க்க"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "மூடுக"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "பக்கத்தி்ன் தலைப்பு"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "பக்கத்தின் முகவரி"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "பக்கத்தின் விவரிப்பு"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "சேமிக்க"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "அழிக்க"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "தொகுக்க"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "இரத்து செய்க"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "உங்களுக்கு ஒரு வலைய பக்கத்தை விரைவாக பக்க அடையாளப்படுத்துவதற்கு அதை உங்களுடைய உலாவியின் பக்க அடையாளங்களில் இழுத்து விட்டு சொடக்குக"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "முகவரி"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "சேர்க்க"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "தொடர்புபட்ட சீட்டுகள்"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "அமைப்புகள்"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "உங்களிடம் பக்க அடையாளங்கள் இல்லை "
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "நீங்களும் ஒரு பக்க அடையாள கோப்பை இறக்குமதி செய்ய முயற்சிக்கலாம்"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "பக்க அடையாளங்கள்"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "ஏற்றுமதி மற்றும் இறக்குமதி"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "ஏற்றுமதி"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "இறக்குமதி"
diff --cc apps/bookmarks/l10n/templates/bookmarks.pot
index 3f4f855,0000000..376af33
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/templates/bookmarks.pot
+++ b/apps/bookmarks/l10n/templates/bookmarks.pot
@@@ -1,152 -1,0 +1,152 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud bookmarks 5.0.0\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-29 14:17-0500\n"
++"POT-Creation-Date: 2013-12-04 18:12-0500\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr ""
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr ""
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr ""
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr ""
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr ""
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr ""
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr ""
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr ""
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr ""
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr ""
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr ""
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr ""
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr ""
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr ""
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr ""
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr ""
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr ""
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr ""
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr ""
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr ""
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr ""
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr ""
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr ""
+
+#: templates/list.php:23
+msgid "Add"
+msgstr ""
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr ""
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr ""
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr ""
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr ""
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr ""
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr ""
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr ""
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr ""
diff --cc apps/bookmarks/l10n/th_TH/bookmarks.po
index 4b2f34b,0000000..353906a
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/th_TH/bookmarks.po
+++ b/apps/bookmarks/l10n/th_TH/bookmarks.po
@@@ -1,153 -1,0 +1,153 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# AriesAnywhere Anywhere <ariesanywhere at gmail.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Thai (Thailand) (http://www.transifex.com/projects/p/owncloud/language/th_TH/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: th_TH\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr ""
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "ประเภทของไฟล์ที่ต้องการนำเข้าไม่ได้รับการรองรับให้ใช้งาน"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "รายการโปรด"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "ป้ายกำกับ"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "แสดงข้อมูลตามป้ายกำกับ"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "แก้ไขรายการโปรด"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "คุณแน่ใจแล้วหรือว่าต้องการลบป้ายกำกับนี้ออกจากทุกๆรายการ"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "คำเตือน"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr ""
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "นำเข้าข้อมูลเสร็จเรียบร้อยแล้ว"
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "กำลังอัพโหลด..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "รายการโปรด"
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "เพิ่มรายการโปรด"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "ปิด"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "ชื่อของหน้า"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "ที่อยู่ของหน้า"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "คำอธิบายเกี่ยวกับหน้า"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "บันทึก"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "ลบ"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "แก้ไข"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "ยกเลิก"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "ลากสิ่งนี้ไปไว้ที่รายการโปรดในโปรแกรมบราวเซอร์ของคุณ แล้วคลิกที่นั่น, เมื่อคุณต้องการเก็บหน้าเว็บเพจเข้าไปไว้ในรายการโปรดอย่างรวดเร็ว"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "ที่อยู่"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "เพิ่ม"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "ป้ายกำกับอื่นๆที่เกี่ยวข้อง"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "ตั้งค่า"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "คุณยังไม่มีรายการโปรด"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "คุณสามารถที่จะลองนำเข้าไฟล์รายการโปรดได้ด้วยเช่นกัน"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Bookmarklet"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "ส่งออก & นำเข้า"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "ส่งออก"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "นำเข้า"
diff --cc apps/bookmarks/l10n/tr/bookmarks.po
index a2b009c,0000000..c25ab57
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/tr/bookmarks.po
+++ b/apps/bookmarks/l10n/tr/bookmarks.po
@@@ -1,156 -1,0 +1,156 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# otefenli <otefenli at gmail.com>, 2013
- # Murat Bişkin <mbiskin at gmail.com>, 2012
++# Murat Bişkin <murat at muratbiskin.com.tr>, 2012
+# Necdet Yücel <necdetyucel at gmail.com>, 2012
+# volkangezer <volkangezer at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-24 01:08-0500\n"
- "PO-Revision-Date: 2013-11-22 18:00+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: volkangezer <volkangezer at gmail.com>\n"
+"Language-Team: Turkish (http://www.transifex.com/projects/p/owncloud/language/tr/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: tr\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "İçe aktarılacak dosya yok"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "İçe aktarmak için desteklenmeyen dosya türü"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Yer İmleri"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Etiketler"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Etikete göre süz"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Yer imini düzenle"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Bu etiketi tüm girdilerden silmek istediğinizden emin misiniz?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Uyarı"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "İçeri aktarım hatası"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "İçe aktarım başarıyla tamamlandı."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Yükleniyor..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Yer imi"
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Yer imi ekle"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Kapat"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Sayfanın başlığı"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Sayfanın adresi"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Sayfanın tanımlaması"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Kaydet"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Sil"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Düzenle"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "İptal"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Bir web sayfasını hızlıca yer imlerine eklemek istediğinizde onu tarayıcınızın yer imlerine sürükleyin ve tıklayın."
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr "ownCloud'a Ekle"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Adres"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Ekle"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "İlgili etiketler"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Ayarlar"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Hiç yer iminiz yok"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Bir yer imi dosyasını içe aktarmayı deneyebilirsiniz"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Yer imleri"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Dışa Aktar & İçe Aktar"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Dışa aktar"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "İçe aktar"
diff --cc apps/bookmarks/l10n/ug/bookmarks.po
index aa70a2c,0000000..327a6cd
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/ug/bookmarks.po
+++ b/apps/bookmarks/l10n/ug/bookmarks.po
@@@ -1,153 -1,0 +1,153 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Abduqadir Abliz <sahran.ug at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Uighur (http://www.transifex.com/projects/p/owncloud/language/ug/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ug\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "ئەكىرىشكە ھېچقانداق ھۆججەت تەمىنلەنمىگەن"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "ئەكىرىشنى قوللىمايدىغان ھۆججەت تىپى"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "خەتكۈچلەر"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "بەلگەلەر"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "بەلگە بويىچە سۈز"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "خەتكۈچ تەھرىر"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "بۇ بەلگىنى ھەممە تۈرلەردىن راستىنلا چىقىرىۋېتەمسىز؟"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "ئاگاھلاندۇرۇش"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "ئەكىرىش خاتالىقى"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "ئەكىرىش مۇۋەپپەقىيەتلىك تاماملاندى."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "يۈكلەۋاتىدۇ…"
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "خەتكۈچ."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "خەتكۈچتىن بىرنى قوش"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "ياپ"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "بۇ بەتنىڭ ماۋزۇسى"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "بەتنىڭ ئادرېسى"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "بەتنىڭ چۈشەندۈرۈلۈشى"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "ساقلا"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "ئۆچۈر"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "تەھرىر"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "ۋاز كەچ"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "سىز تور بەتنى تېز سۈرئەتتە خەتكۈچكە قوشماقچى بولغاندا، بۇنى توركۆرگۈڭىزنىڭ خەتكۈچىگە سۆرەپ، ئۇنى چېكىڭ، "
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "ئادرېس"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "قوش"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "مۇناسىۋەتلىك بەلگىلەر"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "تەڭشەكلەر"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "ھېچقانداق خەتكۈچىڭىز يوق"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "خەتكۈچ ھۆججەتتىن ئەكىرىشنى سىنىيالايسىز"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "خەتكۈچ"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "ئەكىر ياكى چىقار"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "چىقار"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "ئەكىر"
diff --cc apps/bookmarks/l10n/uk/bookmarks.po
index d34adca,0000000..8ba79bb
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/uk/bookmarks.po
+++ b/apps/bookmarks/l10n/uk/bookmarks.po
@@@ -1,154 -1,0 +1,154 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Soul Kim <warlock.rf at gmail.com>, 2012
+# volodya327 <volodya327 at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-29 14:17-0500\n"
- "PO-Revision-Date: 2013-11-28 09:20+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: volodya327 <volodya327 at gmail.com>\n"
+"Language-Team: Ukrainian (http://www.transifex.com/projects/p/owncloud/language/uk/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: uk\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Немає файла для імпорту"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Імпорт файлу даного типу не підтримується"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Закладки"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Теги"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Фільтр по тегах"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Редагувати закладку"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Ви впевнені, що бажаєте видалити цей тег з кожного запису ?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Попередження"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Помилка імпорту"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Імпорт завершено успішно."
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "Вивантаження..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Заклд."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "Додати закладку"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Закрити"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Заголовок сторінки"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Адреса сторінки"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Опис сторінки"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Зберегти"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Видалити"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Редагувати"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Відмінити"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Перетягніть це в закладки вашого броузера і клікніть для того, щоб швидко закласти web-сторінку:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr "Додати до ownCloud"
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Адреса"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Додати"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Пов'язані теги"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Налаштування"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "У вас немає закладок"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Ви можете також спробувати імпортувати файл закладок"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Закладка-аплет"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Експорт та Імпорт"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Експорт"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Імпорт"
diff --cc apps/bookmarks/l10n/vi/bookmarks.po
index af43d2c,0000000..5aa1b0d
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/vi/bookmarks.po
+++ b/apps/bookmarks/l10n/vi/bookmarks.po
@@@ -1,155 -1,0 +1,155 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# mattheu_9x <mattheu.9x at gmail.com>, 2012
+# Sơn Nguyễn <sonnghit at gmail.com>, 2012
+# xtdv <truong.tx8 at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Vietnamese (http://www.transifex.com/projects/p/owncloud/language/vi/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: vi\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "Không có tập tin nào để nhập vào"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "Loại tập tin không được hỗ trợ để nhập vào"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "Bookmarks"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "Tags"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "Lọc theo tag"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "Sửa bookmark"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "Bạn có chắc chắn bạn muốn loại bỏ tags này ?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "Cảnh báo"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "Lỗi khi nhập"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "Nhập vào thành công"
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "tải lên..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "Bookm."
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr " Thêm bookmark"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "Đóng"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "Tiêu đề trang"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "Địa chỉ trang"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "Mô tả trang"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "Lưu"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "Xóa"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "Sửa"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "Hủy"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "Kéo vào bookmark trình duyệt của bạn và nhấp vào nó, khi bạn muốn đánh dấu một trang web một cách nhanh chóng:"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "Địa chỉ"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "Thêm"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "Những Tag có liên quan"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "Cài đặt"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "Bạn chưa có bookmark nào"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "Bạn cũng có thể thử nhập vào một tập tin bookmark"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Bookmarklet"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "Xuất ra & Nhập vào"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "Xuất ra"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "Nhập vào"
diff --cc apps/bookmarks/l10n/zh_CN/bookmarks.po
index 294c886,0000000..c819bc6
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/zh_CN/bookmarks.po
+++ b/apps/bookmarks/l10n/zh_CN/bookmarks.po
@@@ -1,154 -1,0 +1,154 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# hanfeng <appweb.cn at gmail.com>, 2012
+# Xuetian Weng <wengxt at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Chinese (China) (http://www.transifex.com/projects/p/owncloud/language/zh_CN/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: zh_CN\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "未提供导入文件"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "不支持导入的文件类型"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "书签"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "标签"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "按标签过滤"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "编辑书签"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "确定要从所有条目中移除此标签?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "警告"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "导入错误"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "导入成功完成。"
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "上传中……"
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "书签"
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "新增一个书签"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "关闭"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "页面名称"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "页面地址"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "页面描述"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "保存"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "删除"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "编辑"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "取消"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "拖曳此处到您的浏览器书签处,点击可以将网页快速添加到书签中。"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "地址"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "增加"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "相关标签"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "设置"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "您暂无书签"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "您也可以尝试导入一个书签文件"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "书签"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "导入导出"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "导出"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "导入"
diff --cc apps/bookmarks/l10n/zh_HK/bookmarks.po
index e32d80b,0000000..9f4b096
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/zh_HK/bookmarks.po
+++ b/apps/bookmarks/l10n/zh_HK/bookmarks.po
@@@ -1,152 -1,0 +1,152 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Chinese (Hong Kong) (http://www.transifex.com/projects/p/owncloud/language/zh_HK/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: zh_HK\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr ""
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr ""
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "收藏"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr ""
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr ""
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr ""
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr ""
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr ""
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr ""
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr ""
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr ""
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr ""
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr ""
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "關閉"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr ""
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr ""
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr ""
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "儲存"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "刪除"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "編輯"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "取消"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr ""
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "地址"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "加入"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr ""
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "設定"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr ""
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr ""
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr ""
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr ""
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr ""
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "導入"
diff --cc apps/bookmarks/l10n/zh_TW/bookmarks.po
index 4825f70,0000000..1f0825d
mode 100644,000000..100644
--- a/apps/bookmarks/l10n/zh_TW/bookmarks.po
+++ b/apps/bookmarks/l10n/zh_TW/bookmarks.po
@@@ -1,156 -1,0 +1,156 @@@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Hydriz <admin at alphacorp.tk>, 2013
+# dw4dev <dw4dev at gmail.com>, 2012
+# pellaeon <nfsmwlin at gmail.com>, 2013
+# ywang <ywang1007 at gmail.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: ownCloud\n"
+"Report-Msgid-Bugs-To: translations at owncloud.org\n"
- "POT-Creation-Date: 2013-11-21 21:15-0500\n"
- "PO-Revision-Date: 2013-11-22 02:15+0000\n"
++"POT-Creation-Date: 2013-12-02 18:22-0500\n"
++"PO-Revision-Date: 2013-12-02 20:41+0000\n"
+"Last-Translator: I Robot <owncloud-bot at tmit.eu>\n"
+"Language-Team: Chinese (Taiwan) (http://www.transifex.com/projects/p/owncloud/language/zh_TW/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: zh_TW\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ajax/import.php:9
+msgid "No file provided for import"
+msgstr "沒有提供匯入用的檔案"
+
+#: ajax/import.php:21
+msgid "Unsupported file type for import"
+msgstr "不支援這種檔案類型的匯入"
+
+#: appinfo/app.php:17
+msgid "Bookmarks"
+msgstr "書籤"
+
+#: js/addBm.js:42 js/bookmarks.js:235
+msgid "Tags"
+msgstr "標籤"
+
+#: js/bookmarks.js:22
+msgid "Filter by tag"
+msgstr "依標籤篩選"
+
+#: js/bookmarks.js:132
+msgid "Edit bookmark"
+msgstr "編輯書籤"
+
+#: js/bookmarks.js:369
+msgid "Are you sure you want to remove this tag from every entry?"
+msgstr "您確定要從每個項目中移除這個標籤嗎?"
+
+#: js/bookmarks.js:370
+msgid "Warning"
+msgstr "警告"
+
+#: js/settings.js:18
+msgid "Import error"
+msgstr "匯入錯誤"
+
+#: js/settings.js:29
+msgid "Import completed successfully."
+msgstr "匯入成功完成。"
+
+#: js/settings.js:61
+msgid "Uploading..."
+msgstr "上傳中..."
+
+#: lib/search.php:38
+msgid "Bookm."
+msgstr "書籤"
+
+#: templates/addBm.php:5
+msgid "Add a bookmark"
+msgstr "新增書籤"
+
+#: templates/addBm.php:8
+msgid "Close"
+msgstr "關閉"
+
+#: templates/addBm.php:16 templates/js_tpl.php:27
+msgid "The title of the page"
+msgstr "頁面標題"
+
+#: templates/addBm.php:21 templates/js_tpl.php:31
+msgid "The address of the page"
+msgstr "頁面的位址"
+
+#: templates/addBm.php:34 templates/js_tpl.php:40
+msgid "Description of the page"
+msgstr "頁面說明"
+
+#: templates/addBm.php:38 templates/js_tpl.php:45
+msgid "Save"
+msgstr "儲存"
+
+#: templates/js_tpl.php:6 templates/js_tpl.php:59
+msgid "Delete"
+msgstr "刪除"
+
+#: templates/js_tpl.php:14 templates/js_tpl.php:55
+msgid "Edit"
+msgstr "編輯"
+
+#: templates/js_tpl.php:44
+msgid "Cancel"
+msgstr "取消"
+
+#: templates/list.php:14
+msgid ""
+"Drag this to your browser bookmarks and click it, when you want to bookmark "
+"a webpage quickly:"
+msgstr "把這個拖曳至瀏覽器的書籤列,下次您想要將某個頁面加至書籤時,點一下書籤列上面的這個項目即可。"
+
+#: templates/list.php:15
+msgid "Add to ownCloud"
+msgstr ""
+
+#: templates/list.php:22
+msgid "Address"
+msgstr "網址"
+
+#: templates/list.php:23
+msgid "Add"
+msgstr "新增"
+
+#: templates/list.php:31
+msgid "Related Tags"
+msgstr "相關標籤"
+
+#: templates/list.php:38 templates/list.php:40
+msgid "Settings"
+msgstr "設定"
+
+#: templates/list.php:54
+msgid "You have no bookmarks"
+msgstr "您還沒有任何書籤"
+
+#: templates/list.php:59
+msgid "You can also try to import a bookmark file"
+msgstr "您也可以匯入書籤檔"
+
+#: templates/settings.php:11
+msgid "Bookmarklet"
+msgstr "Bookmarklet"
+
+#: templates/settings.php:23
+msgid "Export & Import"
+msgstr "匯出與匯入"
+
+#: templates/settings.php:24
+msgid "Export"
+msgstr "匯出"
+
+#: templates/settings.php:26
+msgid "Import"
+msgstr "匯入"
diff --cc apps/documents/ajax/sessionController.php
index c07bcc9,0000000..008f1a9
mode 100644,000000..100644
--- a/apps/documents/ajax/sessionController.php
+++ b/apps/documents/ajax/sessionController.php
@@@ -1,183 -1,0 +1,199 @@@
+<?php
+
+/**
+ * ownCloud - Documents App
+ *
+ * @author Victor Dubiniuk
+ * @copyright 2013 Victor Dubiniuk victor.dubiniuk at gmail.com
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ */
+
+namespace OCA\Documents;
+
+class SessionController extends Controller{
+
+ public static function joinAsGuest($args){
+ $uid = self::preDispatchGuest();
+ $uid = substr(@$_POST['name'], 0, 16) .' '. $uid;
+ $token = @$args['token'];
+ $file = File::getByShareToken($token);
+ self::join($uid, $file);
+ }
+
+ public static function joinAsUser($args){
+ $uid = self::preDispatch();
+ $fileId = intval(@$args['file_id']);
+ $file = new File($fileId);
- self::join($uid, $file);
++
++ if ($file->getPermissions() & \OCP\PERMISSION_UPDATE) {
++ self::join($uid, $file);
++ } else {
++ \OCP\JSON::success(array(
++ 'permissions' => $file->getPermissions(),
++ 'id' => $fileId
++ ));
++ }
++
++ exit();
+ }
+
+ protected static function join($uid, $file){
+ try{
+ $session = Db_Session::start($uid, $file);
+ \OCP\JSON::success($session);
+ exit();
+ } catch (\Exception $e){
+ Helper::warnLog('Starting a session failed. Reason: ' . $e->getMessage());
+ \OCP\JSON::error();
+ exit();
+ }
+ }
+
+ /**
+ * Store the document content to its origin
+ */
+ public static function save(){
+ try {
+ $esId = @$_SERVER['HTTP_WEBODF_SESSION_ID'];
+ if (!$esId){
+ throw new \Exception('Session id can not be empty');
+ }
+
+ $memberId = @$_SERVER['HTTP_WEBODF_MEMBER_ID'];
+ $sessionRevision = @$_SERVER['HTTP_WEBODF_SESSION_REVISION'];
+
+ $stream = fopen('php://input','r');
+ if (!$stream){
+ throw new \Exception('New content missing');
+ }
+ $content = stream_get_contents($stream);
+
+ $session = new Db_Session();
+ $session->load($esId);
+
+ if (!$session->hasData()){
+ throw new \Exception('Session does not exist');
+ }
+ $sessionData = $session->getData();
+ $file = new File($sessionData['file_id']);
+ if (!$file->isPublicShare()){
+ self::preDispatch();
+ } else {
+ self::preDispatchGuest();
+ }
+
+
+ list($view, $path) = $file->getOwnerViewAndPath();
+
+ $isWritable = ($view->file_exists($path) && $view->isUpdatable($path)) || $view->isCreatable($path);
+ if (!$isWritable){
+ throw new \Exception($path . ' does not exist or is not writable for user ' . $uid);
+ }
+
+ $member = new Db_Member();
+ $members = $member->getActiveCollection($esId);
+ $memberIds = array_map(
+ function($x){
+ return ($x['member_id']);
+ },
+ $members
+ );
+
+ //check if member belongs to the session
+ if (!in_array($memberId, $memberIds)){
+ throw new \Exception($memberId . ' does not belong to session ' . $esId);
+ }
+
+ // Active users except current user
+ $memberCount = count($memberIds) - 1;
+
+ if ($view->file_exists($path)){
++
++
++ $proxyStatus = \OC_FileProxy::$enabled;
++ \OC_FileProxy::$enabled = false;
+ $currentHash = sha1($view->file_get_contents($path));
++ \OC_FileProxy::$enabled = $proxyStatus;
++
+ if (!Helper::isVersionsEnabled() && $currentHash !== $sessionData['genesis_hash']){
+ // Original file was modified externally. Save to a new one
+ $path = Helper::getNewFileName($view, $path, '-conflict');
+ }
+ }
+
+ if ($view->file_put_contents($path, $content)){
+ // Not a last user
+ if ($memberCount>0){
+ // Update genesis hash to prevent conflicts
- Helper::warnLog('Update hash');
++ Helper::debugLog('Update hash');
+ $session->updateGenesisHash($esId, sha1($content));
+ } else {
+ // Last user. Kill session data
+ Db_Session::cleanUp($esId);
+ }
+
+ $view->touch($path);
+ }
+ \OCP\JSON::success();
+ exit();
+ } catch (\Exception $e){
+ Helper::warnLog('Saving failed. Reason:' . $e->getMessage());
+ \OCP\JSON::error(array('message'=>$e->getMessage()));
+ exit();
+ }
+ }
+
+ public static function info(){
+ self::preDispatch();
+ $items = @$_POST['items'];
+ $info = array();
+
+ if (is_array($items)){
+ $session = new Db_Session();
+ $info = $session->getInfoByFileId($items);
+ }
+
+ \OCP\JSON::success(array(
+ "info" => $info
+ ));
+ }
+
+ public static function listAll(){
+ self::preDispatch();
+ $session = new Db_Session();
+ $sessions = $session->getCollection();
+
+ $preparedSessions = array_map(
+ function($x){
+ return ($x['es_id']);
+ }, $sessions
+ );
+ \OCP\JSON::success(array(
+ "session_list" => $preparedSessions
+ ));
+ }
+
+ public static function listAllHtml(){
+ self::preDispatch();
+ $session = new Db_Session();
+ $sessions = $session->getCollection();
+
+ $preparedSessions = array_map(
+ function($x){
+ return ($x['es_id']);
+ }, $sessions
+ );
+
+ $invites = Invite::getAllInvites();
+ if (!is_array($invites)){
+ $invites = array();
+ }
+
+ $tmpl = new \OCP\Template('documents', 'part.sessions', '');
+ $tmpl->assign('invites', $invites);
+ $tmpl->assign('sessions', $sessions);
+ echo $tmpl->fetchPage();
+ }
+}
diff --cc apps/documents/css/style.css
index 0af1ee8,0000000..5146f73
mode 100644,000000..100644
--- a/apps/documents/css/style.css
+++ b/apps/documents/css/style.css
@@@ -1,290 -1,0 +1,283 @@@
+#editor ::-webkit-scrollbar-thumb {
+ background-color: #fff;
+}
+
- #documents-content #emptyfolder {
- position: static;
- margin:0;
- text-align:center;
- font-size:1.5em; font-weight:bold; color:#888; text-shadow:#fff 0 1px 0;
- }
-
+.documentslist { padding:5px; }
+
+.documentslist .document,
+.documentslist .progress,
+.documentslist .add-document{
+ display: inline-block;
+ height: 200px;
+ width: 200px;
+ float: left;
+ background-color: #e8e8e8;
+ margin: 14px;
+ vertical-align: top;
+ border-radius: 5px;
+}
+
+.add-document a {
+ display: inline-block;
+ position: relative;
+ height: 100px;
+ width: 200px;
+ background-repeat: no-repeat;
+ background-size: 32px;
+ background-position: 50%;
+}
+.add-document .add {
+ background-image: url('%webroot%/core/img/actions/add.svg');
+}
+.add-document .upload {
+ background-image: url('%webroot%/core/img/actions/upload.svg');
+}
+
+.add-document a.add {
+ border-bottom: 1px solid #fff;
+}
+.add-document .add,
+.add-document .upload {
+ opacity: .7;
+}
+.add-document .add:hover,
+.add-document .add:focus,
+.add-document #upload:hover .upload,
+.add-document .upload:focus {
+ opacity: 1;
+}
+
+.add-document label {
+ position: absolute;
+ bottom: 10px;
+ width: 100%;
+ font-weight: normal;
+ text-align: center;
+}
+
+.documentslist .progress{
+ position:absolute;
+ left:232px;
+ z-index:5;
+ background: #e8e8e8 url('%webroot%/core/img/loading.gif') 50% 50% no-repeat;
+}
+
+.documentslist .document:hover,
+.documentslist .document a:focus {
+ background-color: #ddd;
+}
+
+.documentslist .session-active {
+ position: relative;
+ margin-left: 128px;
+ margin-top: 128px;
+ width: 32px;
+}
+.document a {
+ display: block;
+ position: relative;
+ height: 200px;
+ width: 200px;
+ background-repeat: no-repeat;
+ background-size: 64px;
+ background-position: 68px;
+}
+.document label {
+ position: absolute;
+ bottom: 5px;
+ width: 100%;
+ font-weight: normal;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ text-align: center;
+ padding: 0 8px;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ white-space: nowrap;
+}
+
+#odf-toolbar{
+ text-align: left;
+ position: absolute;
+ width: 100%;
+ padding:0;
+ z-index: 500;
+}
+
+#odf-toolbar #dropdown{
+ right:auto;
+}
+
+#document-title{
+/* position: absolute;
+ top: 9px;
+ left:50%;
+ margin:0; */
+ padding: 4px 0 5px;
+ border-bottom: 1px solid #E9E9E9;
+
+ text-align: center;
+ font-weight: bold;
+}
+#document-title div{
+ position: relative;
+ /*margin-left:-50%;*/
+}
+#odf-close{
+ float: right;
+}
+
+#odf-invite{
+ float: left;
+}
+
+#invite-block{
+ position: absolute;
+ top:3em;
+ margin-top:-3px;
+ left:0;
+ padding: 10px;
+ background-color: #bbb;
+}
+
+#invitee-list li{
+ padding: 5px 0 5px 20px;
+ background: url('%webroot%/core/img/actions/delete.svg') 0 50% no-repeat;
+}
+
+#mainContainer{
+ position:absolute;
+ z-index:500;
+}
+
+#documents-overlay, #documents-overlay-below{
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ filter:alpha(opacity=30);
+ opacity: .3;
+ z-index: 1000;
+ background: #111 url('%webroot%/core/img/loading-dark.gif') 50% 50% no-repeat;
+}
+
+#documents-overlay-below{
+ left:0;
+ top:0;
+ filter:alpha(opacity=100);
+ opacity: 1;
+ background:#f0f0f0;
+ z-index: 999;
+}
+
+#file_upload_start{
+ display: block;
+ position:relative;
+ left:0; top:0; width:200px; height:100px;
+ margin-bottom: -110px;padding:0;
+ cursor:pointer; overflow:hidden;
+ font-size:1em;
+ -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter:alpha(opacity=0); opacity:0;
+ z-index:20;
+}
+
+#warning-connection-lost{
+ padding: 6px 0;
+ text-align: center;
+ color: #ffffff;
+ background-color: #CE7070;
+ font-size: 16px;
+ font-weight: bold;
+}
+
+#warning-connection-lost img {
+ margin-right: 4px;
+ float: right;
+ height: 20px;
+}
+
+#connection-lost{
+ right: 5px;
+ background: #fff;
+ width: 95%;
+ position: absolute;
+ top: 87px;
+}
+
+
+/* override WebODF styling here */
+
+#mainContainer #collaboration{
+ float:right;position: relative;z-index: 1;
+ width: 70px;padding:5px;
+}
+
+#members{
+ padding-top: 69px !important;
+}
+
+.memberListButton span{
+ display: block;
+ box-shadow: 0px 0px 5px rgb(90, 90, 90) inset;
+ background-color: rgb(200, 200, 200);
+ border-radius: 5px;
+ border: 2px solid;
+ display: block;
+ margin: auto;
+}
+
+.memberListButton img{
+ border: 0 none !important;
+}
+
+#toolbar {
+ border-bottom: none !important;
+ padding: 5px 0 0 !important;
+}
+
+#toolbar > .dijit{
+ margin-left:3px;
+}
+#toolbar > span.dijit{
+ margin-left: 0;
+}
+
+#container {
+ top: 38px !important;
+}
+
+cursor > div {
+ padding-bottom: 0 !important;
+}
+
+editinfo > div.editInfoMarker {
+ width: 4px;
+ border-radius: 0;
+ box-shadow: 0 0 0 #fff;
+ background-clip:content-box;
+ padding: 0 5px;
+}
+
+editinfo > div.editInfoMarker:hover {
+}
+
+.dijitToolbar .dijitDropDownButton {
+ padding-top: 2px;
+}
+
+.dijitSpinner .dijitSpinnerButtonContainer .dijitArrowButton {
+margin-top:-1px;
+}
+
+.claro .dijitTextBox .dijitInputInner,
+.claro .dijitSpinner .dijitSpinnerButtonInner {
+ margin: 0;
+}
+
+/* part of dojo.css */
+.dojoTabular {border-collapse: collapse; border-spacing: 0; border: 1px solid #ccc; margin: 0 1.5em;}
+.dojoTabular th {text-align: center; font-weight: bold;}
+.dojoTabular thead,.dojoTabular tfoot {background-color: #efefef; border: 1px solid #ccc; border-width: 1px 0;}
+.dojoTabular th,.dojoTabular td {padding: 0.25em 0.5em;}
diff --cc apps/documents/css/viewer/odfviewer.css
index 4ff53f0,0000000..ed5f570
mode 100644,000000..100644
--- a/apps/documents/css/viewer/odfviewer.css
+++ b/apps/documents/css/viewer/odfviewer.css
@@@ -1,19 -1,0 +1,10 @@@
+#odf-canvas{
+ position: relative;
+ top: 37px;
- left: 1px;
- border:1px solid darkgray;
++ left: 0px;
++ border:1px solid darkgray;
++ border-left:0 none;
+ box-shadow: 0px 4px 10px #000;
+ -moz-box-shadow: 0px 4px 10px #000;
+ -webkit-box-shadow: 0px 4px 10px #000;
+}
-
- #odf_close{
- top: 0px;
- position: absolute;
- left: 10px;
- }
-
- #odf-toolbar{
- padding: 0 0 0 1em
- }
diff --cc apps/documents/js/3rdparty/webodf/editor/Editor.js
index e05638b,0000000..86840e2
mode 100644,000000..100644
--- a/apps/documents/js/3rdparty/webodf/editor/Editor.js
+++ b/apps/documents/js/3rdparty/webodf/editor/Editor.js
@@@ -1,446 -1,0 +1,534 @@@
+/**
+ * @license
+ * Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+ *
+ * @licstart
+ * The JavaScript code in this page is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Affero General Public License
+ * (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version. The code is distributed
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this code. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As additional permission under GNU AGPL version 3 section 7, you
+ * may distribute non-source (e.g., minimized or compacted) forms of
+ * that code without the copy of the GNU GPL normally required by
+ * section 4, provided you include this license notice and a URL
+ * through which recipients can access the Corresponding Source.
+ *
+ * As a special exception to the AGPL, any HTML file which merely makes function
+ * calls to this code, and for that purpose includes it by reference shall be
+ * deemed a separate work for copyright law purposes. In addition, the copyright
+ * holders of this code give you permission to combine this code with free
+ * software libraries that are released under the GNU LGPL. You may copy and
+ * distribute such a system following the terms of the GNU AGPL for this code
+ * and the LGPL for the libraries. If you modify this code, you may extend this
+ * exception to your version of the code, but you are not obligated to do so.
+ * If you do not wish to do so, delete this exception statement from your
+ * version.
+ *
+ * This license applies to this entire compilation.
+ * @licend
+ * @source: http://www.webodf.org/
+ * @source: https://github.com/kogmbh/WebODF/
+ */
+
+/*global runtime, define, document, odf, ops, window, gui, alert, saveAs, Blob */
+
+define("webodf/editor/Editor", [
+ "webodf/editor/EditorSession",
+ "webodf/editor/MemberListView",
+ "dijit/layout/BorderContainer",
+ "dijit/layout/ContentPane",
+ "webodf/editor/Tools"],
+
+ function (EditorSession,
+ MemberListView,
+ BorderContainer,
+ ContentPane,
+ Tools) {
+ "use strict";
+
+ runtime.loadClass('odf.OdfCanvas');
+
+ /**
+ * @constructor
+ * @param {{unstableFeaturesEnabled:boolean,
+ * loadCallback:function(),
+ * saveCallback:function(),
+ * closeCallback:function()}}
+ * param {!ops.Server=} server
+ * @param {!ServerFactory=} serverFactory
+ */
+ function Editor(args, server, serverFactory) {
+
+ var self = this,
+ // Private
+ session,
+ editorSession,
+ mainContainer,
+ memberListView,
+ tools,
+ loadOdtFile = args.loadCallback,
+ saveOdtFile = args.saveCallback,
+ close = args.closeCallback,
+ odfCanvas,
++ eventNotifier = new core.EventNotifier([
++ Editor.EVENT_ERROR,
++ Editor.EVENT_BEFORESAVETOFILE,
++ Editor.EVENT_SAVEDTOFILE,
++ Editor.EVENT_HASLOCALUNSYNCEDOPERATIONSCHANGED,
++ Editor.EVENT_HASSESSIONHOSTCONNECTIONCHANGED
++ ]),
+ pendingMemberId,
+ pendingEditorReadyCallback;
+
++ /**
++ * @param {!string} eventid
++ * @param {*} args
++ * @return {undefined}
++ */
++ function fireEvent(eventid, args) {
++ eventNotifier.emit(eventid, args);
++ }
++
+ function getFileBlob(cbSuccess, cbError) {
+ var odfContainer = odfCanvas.odfContainer();
+
+ if (odfContainer) {
+ odfContainer.createByteArray(cbSuccess, cbError);
+ } else {
+ cbError("No odfContainer!");
+ }
+ }
+
+ /**
+ * prepare all gui elements and load the given document.
+ * after loading is completed, the given callback is called.
+ * the caller still has to call editorSession.startEditing
+ * which will insert the the cursor.
+ *
+ * @param {!string} initialDocumentUrl
+ * @param {!string} memberId
+ * @param {!function()} editorReadyCallback
+ * @return {undefined}
+ */
+ function initDocLoading(initialDocumentUrl, memberId, editorReadyCallback) {
+ runtime.assert(initialDocumentUrl, "document should be defined here.");
+ runtime.assert(memberId !== undefined, "memberId should be defined here.");
+ runtime.assert(!pendingEditorReadyCallback, "pendingEditorReadyCallback should not exist here.");
+ runtime.assert(!editorSession, "editorSession should not exist here.");
+ runtime.assert(!session, "session should not exist here.");
+
+ pendingMemberId = memberId;
+ pendingEditorReadyCallback = editorReadyCallback;
+
+ odfCanvas.load(initialDocumentUrl);
+ }
+
+
+ /**
+ * open the document,
+ * call editorReadyCallback once everything is done.
+ *
+ * @param {!string} docUrl
+ * @param {!string} memberId
+ * @param {!function()} editorReadyCallback
+ * @return {undefined}
+ */
+ this.openDocument = function (docUrl, memberId, editorReadyCallback) {
+ initDocLoading(docUrl, memberId, function () {
+ runtime.loadClass("ops.OpAddMember");
+ var op = new ops.OpAddMember();
+ op.init({
+ memberid: memberId,
+ setProperties: {
+ fullName: runtime.tr("Unknown Author"),
+ color: "black",
+ imageUrl: "avatar-joe.png"
+ }
+ });
+ session.enqueue([op]);
+ editorReadyCallback();
+ });
+ };
+
+ /**
+ * Closes a single-user document, and does cleanup.
+ * @param {!function(!Object=)} callback, passing an error object in case of error
+ * @return undefined;
+ */
+ this.closeDocument = function (callback) {
+ runtime.assert(session, "session should exist here.");
+ runtime.loadClass("ops.OpRemoveMember");
+
+ var op = new ops.OpRemoveMember();
+ op.init({
+ memberid: editorSession.sessionController.getInputMemberId()
+ });
+ session.enqueue([op]);
+
+ session.close(function (err) {
+ if (err) {
+ callback(err);
+ } else {
+ editorSession.destroy(function (err) {
+ if (err) {
+ callback(err);
+ } else {
+ editorSession = undefined;
+ session.destroy(function (err) {
+ if (err) {
+ callback(err);
+ } else {
+ session = undefined;
+ callback();
+ }
+ });
+ }
+ });
+ }
+ });
+ };
+
+ /**
+ * @param {!string} filename
+ * @param {?function()} callback
+ * @return {undefined}
+ */
+ this.saveDocument = function (filename, callback) {
+ function onsuccess(data) {
+ var mimebase = "application/vnd.oasis.opendocument.",
+ mimetype = mimebase + "text",
+ blob;
+ filename = filename || "doc.odt";
+ if (filename.substr(-4) === ".odp") {
+ mimetype = mimebase + "presentation";
+ } else if (filename.substr(-4) === ".ods") {
+ mimetype = mimebase + "spreadsheet";
+ }
+ blob = new Blob([data.buffer], {type: mimetype});
+ saveAs(blob, filename);
++ //TODO: add callback as event handler to saveAs
++ fireEvent(Editor.EVENT_SAVEDTOFILE, null);
+ }
+ function onerror(error) {
++ // TODO: use callback for that
+ alert(error);
+ }
+
++ fireEvent(Editor.EVENT_BEFORESAVETOFILE, null);
+ getFileBlob(onsuccess, onerror);
+ };
+
+ /**
++ * @param {!Object} error
++ * @return {undefined}
++ */
++ function handleOperationRouterErrors(error) {
++ // TODO: translate error into Editor ids or at least document the possible values
++ fireEvent(Editor.EVENT_ERROR, error);
++ }
++
++ /**
+ * open the initial document of an editing-session,
+ * request a replay of previous operations, call
+ * editorReadyCallback once everything is done.
+ *
+ * @param {!string} sessionId
+ * @param {!string} memberId
+ * @param {!function()} editorReadyCallback
+ * @return {undefined}
+ */
+ this.openSession = function (sessionId, memberId, editorReadyCallback) {
+ initDocLoading(server.getGenesisUrl(sessionId), memberId, function () {
+ // overwrite router
+ // TODO: serverFactory should be a backendFactory,
+ // and there should be a backendFactory for local editing
- var opRouter = serverFactory.createOperationRouter(sessionId, memberId, server, odfCanvas.odfContainer());
++ var opRouter = serverFactory.createOperationRouter(sessionId, memberId, server, odfCanvas.odfContainer(), handleOperationRouterErrors);
+ session.setOperationRouter(opRouter);
++ // forward events
++ // TODO: relying here on that opRouter uses the same id strings ATM, those should be defined at OperationRouter interface
++ opRouter.subscribe(Editor.EVENT_HASLOCALUNSYNCEDOPERATIONSCHANGED, function (hasUnsyncedOps) {
++ fireEvent(Editor.EVENT_HASLOCALUNSYNCEDOPERATIONSCHANGED, hasUnsyncedOps);
++ });
++ opRouter.subscribe(Editor.EVENT_HASSESSIONHOSTCONNECTIONCHANGED, function (hasSessionHostConnection) {
++ fireEvent(Editor.EVENT_HASSESSIONHOSTCONNECTIONCHANGED, hasSessionHostConnection);
++ });
++ opRouter.subscribe(Editor.EVENT_BEFORESAVETOFILE, function () {
++ fireEvent(Editor.EVENT_BEFORESAVETOFILE, null);
++ });
++ opRouter.subscribe(Editor.EVENT_SAVEDTOFILE, function () {
++ fireEvent(Editor.EVENT_SAVEDTOFILE, null);
++ });
+
++ // now get existing ops and after that let the user edit
+ opRouter.requestReplay(function done() {
+ editorReadyCallback();
+ });
+
+ });
+ };
+
+ /**
+ * Closes the current editing running editing (polling-timer),
+ * cleanup.
+ * @param {!function(!Object=)} callback, passing an error object in case of error
+ * @return {undefined}
+ */
+ this.closeSession = function (callback) {
+ runtime.assert(session, "session should exist here.");
+ // TODO: there is a better pattern for this instead of unrolling
+ session.close(function(err) {
+ if (err) {
+ callback(err);
+ } else {
+ // now also destroy session, will not be reused for new document
+ memberListView.setEditorSession(undefined);
+ editorSession.destroy(function(err) {
+ if (err) {
+ callback(err);
+ } else {
+ editorSession = undefined;
+ session.destroy(function(err) {
+ if (err) {
+ callback(err);
+ } else {
+ session = undefined;
+ callback();
+ }
+ });
+ }
+ });
+ }
+ });
+ };
+
+ /**
+ * Adds a cursor and enables the tools and allows modifications.
+ * Should be called inside/after editorReadyCallback.
+ * TODO: turn this and endEditing() into readonly switch
+ * @return {undefined}
+ */
+ this.startEditing = function () {
+ runtime.assert(editorSession, "editorSession should exist here.");
+
+ tools.setEditorSession(editorSession);
+ editorSession.sessionController.startEditing();
+ };
+
+ /**
+ * Removes the cursor and disables the tools and allows modifications.
+ * Should be called before closeDocument, if startEditing was called before
+ * @return {undefined}
+ */
+ this.endEditing = function () {
+ runtime.assert(editorSession, "editorSession should exist here.");
+
+ tools.setEditorSession(undefined);
+ editorSession.sessionController.endEditing();
+ };
+
+ /**
++ * Allows to register listeners for certain events. Currently
++ * available events are, with the type of the argument passed to the callback:
++ * Editor.EVENT_BEFORESAVETOFILE - no argument
++ * Editor.EVENT_SAVEDTOFILE - no argument
++ * Editor.EVENT_HASLOCALUNSYNCEDOPERATIONSCHANGED - boolean, reflecting new hasLocalUnsyncedOperations state
++ * Editor.EVENT_HASSESSIONHOSTCONNECTIONCHANGED - boolean, reflecting new hasSessionhostConnection state
++ * Editor.EVENT_ERROR - string, one of these errorcodes:
++ * "notMemberOfSession"
++ * "opExecutionFailure"
++ * "sessionDoesNotExist"
++ * "unknownOpReceived"
++ * "unknownServerReply"
++ * "unresolvableConflictingOps"
++ *
++ * @param {!string} eventid
++ * @param {!Function} listener
++ * @return {undefined}
++ */
++ this.addEventListener = function (eventid, listener) {
++ eventNotifier.subscribe(eventid, listener);
++ };
++
++ /**
++ * @param {!string} eventid
++ * @param {!Function} listener
++ * @return {undefined}
++ */
++ this.removeEventListener = function (eventid, listener) {
++ eventNotifier.unsubscribe(eventid, listener);
++ };
++
++ /**
+ * @param {!function(!Object=)} callback, passing an error object in case of error
+ * @return {undefined}
+ */
+ this.destroy = function (callback) {
+ var destroyMemberListView = memberListView ? memberListView.destroy : function(cb) { cb(); };
+
+ // TODO: decide if some forced close should be done here instead of enforcing proper API usage
+ runtime.assert(!session, "session should not exist here.");
+
+ // TODO: investigate what else needs to be done
+ mainContainer.destroyRecursive(true);
+
+ destroyMemberListView(function(err) {
+ if (err) {
+ callback(err);
+ } else {
+ tools.destroy(function(err) {
+ if (err) {
+ callback(err);
+ } else {
+ odfCanvas.destroy(function(err) {
+ if (err) {
+ callback(err);
+ } else {
+ callback();
+ }
+ });
+ }
+ });
+ }
+ });
+ };
+
+ function setFocusToOdfCanvas() {
+ editorSession.sessionController.getEventManager().focus();
+ }
+
+ // init
+ function init() {
+ var editorPane, memberListPane,
+ inviteButton,
+ canvasElement = document.getElementById("canvas"),
+ memberListElement = document.getElementById('memberList'),
+ collabEditing = Boolean(server),
+ directParagraphStylingEnabled = (! collabEditing) || args.unstableFeaturesEnabled,
+ imageInsertingEnabled = (! collabEditing) || args.unstableFeaturesEnabled,
+ // annotations not yet properly supported for OT
+ annotationsEnabled = (! collabEditing) || args.unstableFeaturesEnabled,
+ // undo manager is not yet integrated with collaboration
+ undoRedoEnabled = (! collabEditing),
+ closeCallback;
+
+ // Extend runtime with a convenient translation function
+ runtime.translateContent = function (node) {
+ var i,
+ element,
+ tag,
+ placeholder,
+ translatable = node.querySelectorAll("*[text-i18n]");
+
+ for (i = 0; i < translatable.length; i += 1) {
+ element = translatable[i];
+ tag = element.localName;
+ placeholder = element.getAttribute('text-i18n');
+ if (tag === "label"
+ || tag === "span"
+ || /h\d/i.test(tag)) {
+ element.textContent = runtime.tr(placeholder);
+ }
+ }
+ };
+
+ if (collabEditing) {
+ runtime.assert(memberListElement, 'missing "memberList" div in HTML');
+ }
+
+ runtime.assert(canvasElement, 'missing "canvas" div in HTML');
+
+ // App Widgets
+ mainContainer = new BorderContainer({}, 'mainContainer');
+
+ editorPane = new ContentPane({
+ region: 'center'
+ }, 'editor');
+ mainContainer.addChild(editorPane);
+
+ if (collabEditing) {
+ memberListPane = new ContentPane({
+ region: 'right',
+ title: runtime.tr("Members")
+ }, 'members');
+ mainContainer.addChild(memberListPane);
+ memberListView = new MemberListView(memberListElement);
+ }
+
+ mainContainer.startup();
+
+ if (window.inviteButtonProxy) {
+ inviteButton = document.getElementById('inviteButton');
+ runtime.assert(inviteButton, 'missing "inviteButton" div in HTML');
+ inviteButton.innerText = runtime.tr("Invite Members");
+ inviteButton.style.display = "block";
+ inviteButton.onclick = window.inviteButtonProxy.clicked;
+ }
+
+ tools = new Tools({
+ onToolDone: setFocusToOdfCanvas,
+ loadOdtFile: loadOdtFile,
+ saveOdtFile: saveOdtFile,
+ close: close,
+ directParagraphStylingEnabled: directParagraphStylingEnabled,
+ imageInsertingEnabled: imageInsertingEnabled,
+ annotationsEnabled: annotationsEnabled,
+ undoRedoEnabled: undoRedoEnabled
+ });
+
+ odfCanvas = new odf.OdfCanvas(canvasElement);
+ odfCanvas.enableAnnotations(annotationsEnabled);
+
+ odfCanvas.addListener("statereadychange", function () {
+ var viewOptions = {
+ editInfoMarkersInitiallyVisible: collabEditing,
+ caretAvatarsInitiallyVisible: false,
+ caretBlinksOnRangeSelect: true
+ };
+
+ // create session around loaded document
+ session = new ops.Session(odfCanvas);
+ editorSession = new EditorSession(session, pendingMemberId, {
+ viewOptions: viewOptions,
+ directParagraphStylingEnabled: directParagraphStylingEnabled,
+ imageInsertingEnabled: imageInsertingEnabled
+ });
+ if (undoRedoEnabled) {
+ editorSession.sessionController.setUndoManager(new gui.TrivialUndoManager());
+ }
+
+ if (memberListView) {
+ memberListView.setEditorSession(editorSession);
+ }
+
+ // and report back to caller
+ pendingEditorReadyCallback();
+ // reset
+ pendingEditorReadyCallback = null;
+ pendingMemberId = null;
+ });
+ }
+
+ init();
+ }
++
++ /**@const @type {!string}*/
++ Editor.EVENT_ERROR = "error";
++ /**@const @type {!string}*/
++ Editor.EVENT_BEFORESAVETOFILE = "beforeSaveToFile";
++ /**@const @type {!string}*/
++ Editor.EVENT_SAVEDTOFILE = "savedToFile";
++ /**@const @type {!string}*/
++ Editor.EVENT_HASLOCALUNSYNCEDOPERATIONSCHANGED = "hasLocalUnsyncedOperationsChanged";
++ /**@const @type {!string}*/
++ Editor.EVENT_HASSESSIONHOSTCONNECTIONCHANGED = "hasSessionHostConnectionChanged";
++
+ return Editor;
+ });
+
+// vim:expandtab
diff --cc apps/documents/js/3rdparty/webodf/editor/EditorSession.js
index b96f4a7,0000000..91d28b4
mode 100644,000000..100644
--- a/apps/documents/js/3rdparty/webodf/editor/EditorSession.js
+++ b/apps/documents/js/3rdparty/webodf/editor/EditorSession.js
@@@ -1,628 -1,0 +1,660 @@@
+/**
+ * @license
+ * Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+ *
+ * @licstart
+ * The JavaScript code in this page is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Affero General Public License
+ * (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version. The code is distributed
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this code. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As additional permission under GNU AGPL version 3 section 7, you
+ * may distribute non-source (e.g., minimized or compacted) forms of
+ * that code without the copy of the GNU GPL normally required by
+ * section 4, provided you include this license notice and a URL
+ * through which recipients can access the Corresponding Source.
+ *
+ * As a special exception to the AGPL, any HTML file which merely makes function
+ * calls to this code, and for that purpose includes it by reference shall be
+ * deemed a separate work for copyright law purposes. In addition, the copyright
+ * holders of this code give you permission to combine this code with free
+ * software libraries that are released under the GNU LGPL. You may copy and
+ * distribute such a system following the terms of the GNU AGPL for this code
+ * and the LGPL for the libraries. If you modify this code, you may extend this
+ * exception to your version of the code, but you are not obligated to do so.
+ * If you do not wish to do so, delete this exception statement from your
+ * version.
+ *
+ * This license applies to this entire compilation.
+ * @licend
+ * @source: http://www.webodf.org/
+ * @source: https://github.com/kogmbh/WebODF/
+ */
+
+/*global define, runtime, core, gui, ops, document */
+
+define("webodf/editor/EditorSession", [
+ "dojo/text!" + OC.filePath('documents', 'css', 'fonts.css')
+], function (fontsCSS) { // fontsCSS is retrieved as a string, using dojo's text retrieval AMD plugin
+ "use strict";
+
+ runtime.libraryPaths = function () {
+ return [ "../../webodf/lib" ];
+ };
+
+ runtime.loadClass("core.DomUtils");
++ runtime.loadClass("odf.OdfUtils");
+ runtime.loadClass("ops.OdtDocument");
++ runtime.loadClass("ops.StepsTranslator");
+ runtime.loadClass("ops.Session");
+ runtime.loadClass("odf.Namespaces");
+ runtime.loadClass("odf.OdfCanvas");
+ runtime.loadClass("gui.CaretManager");
+ runtime.loadClass("gui.Caret");
+ runtime.loadClass("gui.SessionController");
+ runtime.loadClass("gui.SessionView");
+ runtime.loadClass("gui.TrivialUndoManager");
+ runtime.loadClass("gui.SelectionViewManager");
+ runtime.loadClass("core.EventNotifier");
+ runtime.loadClass("gui.ShadowCursor");
+
+ /**
+ * Instantiate a new editor session attached to an existing operation session
+ * @param {!ops.Session} session
+ * @param {!string} localMemberId
+ * @param {{viewOptions:gui.SessionViewOptions,directParagraphStylingEnabled:boolean}} config
+ * @constructor
+ */
+ var EditorSession = function EditorSession(session, localMemberId, config) {
+ var self = this,
+ currentParagraphNode = null,
+ currentCommonStyleName = null,
+ currentStyleName = null,
+ caretManager,
+ selectionViewManager,
+ odtDocument = session.getOdtDocument(),
+ textns = odf.Namespaces.textns,
+ fontStyles = document.createElement('style'),
+ formatting = odtDocument.getFormatting(),
+ domUtils = new core.DomUtils(),
++ odfUtils = new odf.OdfUtils(),
+ eventNotifier = new core.EventNotifier([
+ EditorSession.signalMemberAdded,
+ EditorSession.signalMemberUpdated,
+ EditorSession.signalMemberRemoved,
+ EditorSession.signalCursorAdded,
+ EditorSession.signalCursorMoved,
+ EditorSession.signalCursorRemoved,
+ EditorSession.signalParagraphChanged,
+ EditorSession.signalCommonStyleCreated,
+ EditorSession.signalCommonStyleDeleted,
+ EditorSession.signalParagraphStyleModified,
+ EditorSession.signalUndoStackChanged]),
+ shadowCursor = new gui.ShadowCursor(odtDocument);
+
+ /**
+ * @return {Array.<!string>}
+ */
+ function getAvailableFonts() {
+ var availableFonts, regex, matches;
+
+ availableFonts = {};
+
+ regex = /font-family *: *(?:\'([^']*)\'|\"([^"]*)\")/gm;
+ matches = regex.exec(fontsCSS);
+
+ while (matches) {
+ availableFonts[matches[1] || matches[2]] = 1;
+ matches = regex.exec(fontsCSS);
+ }
+ availableFonts = Object.keys(availableFonts);
+
+ return availableFonts;
+ }
+
+ function checkParagraphStyleName() {
+ var newStyleName,
+ newCommonStyleName;
+
+ newStyleName = currentParagraphNode.getAttributeNS(textns, 'style-name');
+
+ if (newStyleName !== currentStyleName) {
+ currentStyleName = newStyleName;
+ // check if common style is still the same
+ newCommonStyleName = formatting.getFirstCommonParentStyleNameOrSelf(newStyleName);
+ if (!newCommonStyleName) {
+ // Default style, empty-string name
+ currentCommonStyleName = newStyleName = currentStyleName = "";
+ self.emit(EditorSession.signalParagraphChanged, {
+ type: 'style',
+ node: currentParagraphNode,
+ styleName: currentCommonStyleName
+ });
+ return;
+ }
+ // a common style
+ if (newCommonStyleName !== currentCommonStyleName) {
+ currentCommonStyleName = newCommonStyleName;
+ self.emit(EditorSession.signalParagraphChanged, {
+ type: 'style',
+ node: currentParagraphNode,
+ styleName: currentCommonStyleName
+ });
+ }
+ }
+ }
+ /**
+ * Creates a NCName from the passed string
+ * @param {!string} name
+ * @return {!string}
+ */
+ function createNCName(name) {
+ var letter,
+ result = "",
+ i;
+
+ // encode
+ for (i = 0; i < name.length; i++) {
+ letter = name[i];
+ // simple approach, can be improved to not skip other allowed chars
+ if (letter.match(/[a-zA-Z0-9.-_]/) !== null) {
+ result += letter;
+ } else {
+ result += "_" + letter.charCodeAt(0).toString(16) + "_";
+ }
+ }
+ // ensure leading char is from proper range
+ if (result.match(/^[a-zA-Z_]/) === null) {
+ result = "_" + result;
+ }
+
+ return result;
+ }
+
+ function uniqueParagraphStyleNCName(name) {
+ var result,
+ i = 0,
+ ncMemberId = createNCName(localMemberId),
+ ncName = createNCName(name);
+
+ // create default paragraph style
+ // localMemberId is used to avoid id conflicts with ids created by other members
+ result = ncName + "_" + ncMemberId;
+ // then loop until result is really unique
+ while (formatting.hasParagraphStyle(result)) {
+ result = ncName + "_" + i + "_" + ncMemberId;
+ i++;
+ }
+
+ return result;
+ }
+
+ function trackCursor(cursor) {
+ var node;
+
+ node = odtDocument.getParagraphElement(cursor.getNode());
+ if (!node) {
+ return;
+ }
+ currentParagraphNode = node;
+ checkParagraphStyleName();
+ }
+
+ function trackCurrentParagraph(info) {
+ var cursor = odtDocument.getCursor(localMemberId),
+ range = cursor && cursor.getSelectedRange(),
+ paragraphRange = odtDocument.getDOM().createRange();
+ paragraphRange.selectNode(info.paragraphElement);
+ if ((range && domUtils.rangesIntersect(range, paragraphRange)) || info.paragraphElement === currentParagraphNode) {
+ self.emit(EditorSession.signalParagraphChanged, info);
+ checkParagraphStyleName();
+ }
+ paragraphRange.detach();
+ }
+
+ function onMemberAdded(member) {
+ self.emit(EditorSession.signalMemberAdded, member.getMemberId());
+ }
+
+ function onMemberUpdated(member) {
+ self.emit(EditorSession.signalMemberUpdated, member.getMemberId());
+ }
+
+ function onMemberRemoved(memberId) {
+ self.emit(EditorSession.signalMemberRemoved, memberId);
+ }
+
+ function onCursorAdded(cursor) {
+ self.emit(EditorSession.signalCursorAdded, cursor.getMemberId());
+ trackCursor(cursor);
+ }
+
+ function onCursorRemoved(memberId) {
+ self.emit(EditorSession.signalCursorRemoved, memberId);
+ }
+
+ function onCursorMoved(cursor) {
+ // Emit 'cursorMoved' only when *I* am moving the cursor, not the other users
+ if (cursor.getMemberId() === localMemberId) {
+ self.emit(EditorSession.signalCursorMoved, cursor);
+ trackCursor(cursor);
+ }
+ }
+
+ function onStyleCreated(newStyleName) {
+ self.emit(EditorSession.signalCommonStyleCreated, newStyleName);
+ }
+
+ function onStyleDeleted(styleName) {
+ self.emit(EditorSession.signalCommonStyleDeleted, styleName);
+ }
+
+ function onParagraphStyleModified(styleName) {
+ self.emit(EditorSession.signalParagraphStyleModified, styleName);
+ }
+
+ /**
+ * Call all subscribers for the given event with the specified argument
+ * @param {!string} eventid
+ * @param {Object} args
+ */
+ this.emit = function (eventid, args) {
+ eventNotifier.emit(eventid, args);
+ };
+
+ /**
+ * Subscribe to a given event with a callback
+ * @param {!string} eventid
+ * @param {!Function} cb
+ */
+ this.subscribe = function (eventid, cb) {
+ eventNotifier.subscribe(eventid, cb);
+ };
+
+ /**
+ * @param {!string} eventid
+ * @param {!Function} cb
+ * @return {undefined}
+ */
+ this.unsubscribe = function (eventid, cb) {
+ eventNotifier.unsubscribe(eventid, cb);
+ };
+
+ this.getCursorPosition = function () {
+ return odtDocument.getCursorPosition(localMemberId);
+ };
+
+ this.getCursorSelection = function () {
+ return odtDocument.getCursorSelection(localMemberId);
+ };
+
+ this.getOdfCanvas = function () {
+ return odtDocument.getOdfCanvas();
+ };
+
+ this.getCurrentParagraph = function () {
+ return currentParagraphNode;
+ };
+
+ this.getAvailableParagraphStyles = function () {
+ return formatting.getAvailableParagraphStyles();
+ };
+
+ this.getCurrentParagraphStyle = function () {
+ return currentCommonStyleName;
+ };
+
- this.setCurrentParagraphStyle = function (value) {
- var op;
- if (currentCommonStyleName !== value) {
- op = new ops.OpSetParagraphStyle();
- op.init({
- memberid: localMemberId,
- position: self.getCursorPosition(),
- styleName: value
- });
- session.enqueue([op]);
++ /**
++ * Round the step up to the next step
++ * @param {!number} step
++ * @returns {!boolean}
++ */
++ function roundUp(step) {
++ return step === ops.StepsTranslator.NEXT_STEP;
++ }
++
++ /**
++ * Applies the paragraph style with the given
++ * style name to all the paragraphs within
++ * the cursor selection.
++ * @param {!string} styleName
++ * @return {undefined}
++ */
++ this.setCurrentParagraphStyle = function (styleName) {
++ var range = odtDocument.getCursor(localMemberId).getSelectedRange(),
++ paragraphs = odfUtils.getParagraphElements(range),
++ opQueue = [];
++
++ paragraphs.forEach(function (paragraph) {
++ var paragraphStartPoint = odtDocument.convertDomPointToCursorStep(paragraph, 0, roundUp),
++ paragraphStyleName = paragraph.getAttributeNS(odf.Namespaces.textns, "style-name"),
++ opSetParagraphStyle;
++
++ if (paragraphStyleName !== styleName) {
++ opSetParagraphStyle = new ops.OpSetParagraphStyle();
++ opSetParagraphStyle.init({
++ memberid: localMemberId,
++ styleName: styleName,
++ position: paragraphStartPoint
++ });
++ opQueue.push(opSetParagraphStyle);
++ }
++ });
++
++ if (opQueue.length > 0) {
++ session.enqueue(opQueue);
+ }
+ };
+
+ this.insertTable = function (initialRows, initialColumns, tableStyleName, tableColumnStyleName, tableCellStyleMatrix) {
+ var op = new ops.OpInsertTable();
+ op.init({
+ memberid: localMemberId,
+ position: self.getCursorPosition(),
+ initialRows: initialRows,
+ initialColumns: initialColumns,
+ tableStyleName: tableStyleName,
+ tableColumnStyleName: tableColumnStyleName,
+ tableCellStyleMatrix: tableCellStyleMatrix
+ });
+ session.enqueue([op]);
+ };
+
+ /**
+ * Takes a style name and returns the corresponding paragraph style
+ * element. If the style name is an empty string, the default style
+ * is returned.
+ * @param {!string} styleName
+ * @return {Element}
+ */
+ this.getParagraphStyleElement = function (styleName) {
+ return (styleName === "")
+ ? formatting.getDefaultStyleElement('paragraph')
+ : odtDocument.getParagraphStyleElement(styleName);
+ };
+
+ /**
+ * Returns if the style is used anywhere in the document
+ * @param {!Element} styleElement
+ * @return {boolean}
+ */
+ this.isStyleUsed = function (styleElement) {
+ return formatting.isStyleUsed(styleElement);
+ };
+
+ function getDefaultParagraphStyleAttributes () {
+ var styleNode = formatting.getDefaultStyleElement('paragraph');
+ if (styleNode) {
+ return formatting.getInheritedStyleAttributes(styleNode);
+ }
+
+ return null;
+ };
+
+ /**
+ * Returns the attributes of a given paragraph style name
+ * (with inheritance). If the name is an empty string,
+ * the attributes of the default style are returned.
+ * @param {!string} styleName
+ * @return {Object}
+ */
+ this.getParagraphStyleAttributes = function (styleName) {
+ return (styleName === "")
+ ? getDefaultParagraphStyleAttributes()
+ : odtDocument.getParagraphStyleAttributes(styleName);
+ };
+
+ /**
+ * Creates and enqueues a paragraph-style cloning operation.
+ * Returns the created id for the new style.
+ * @param {!string} styleName id of the style to update
+ * @param {!{paragraphProperties,textProperties}} setProperties properties which are set
+ * @param {!{paragraphPropertyNames,textPropertyNames}=} removedProperties properties which are removed
+ * @return {undefined}
+ */
+ this.updateParagraphStyle = function (styleName, setProperties, removedProperties) {
+ var op;
+ op = new ops.OpUpdateParagraphStyle();
+ op.init({
+ memberid: localMemberId,
+ styleName: styleName,
+ setProperties: setProperties,
+ removedProperties: (!removedProperties) ? {} : removedProperties
+ });
+ session.enqueue([op]);
+ };
+
+ /**
+ * Creates and enqueues a paragraph-style cloning operation.
+ * Returns the created id for the new style.
+ * @param {!string} styleName id of the style to clone
+ * @param {!string} newStyleDisplayName display name of the new style
+ * @return {!string}
+ */
+ this.cloneParagraphStyle = function (styleName, newStyleDisplayName) {
+ var newStyleName = uniqueParagraphStyleNCName(newStyleDisplayName),
+ styleNode = self.getParagraphStyleElement(styleName),
+ formatting = odtDocument.getFormatting(),
+ op, setProperties, attributes, i;
+
+ setProperties = formatting.getStyleAttributes(styleNode);
+ // copy any attributes directly on the style
+ attributes = styleNode.attributes;
+ for (i = 0; i < attributes.length; i += 1) {
+ // skip...
+ // * style:display-name -> not copied, set to new string below
+ // * style:name -> not copied, set from op by styleName property
+ // * style:family -> "paragraph" always, set by op
+ if (!/^(style:display-name|style:name|style:family)/.test(attributes[i].name)) {
+ setProperties[attributes[i].name] = attributes[i].value;
+ }
+ }
+
+ setProperties['style:display-name'] = newStyleDisplayName;
+
+ op = new ops.OpAddStyle();
+ op.init({
+ memberid: localMemberId,
+ styleName: newStyleName,
+ styleFamily: 'paragraph',
+ setProperties: setProperties
+ });
+ session.enqueue([op]);
+
+ return newStyleName;
+ };
+
+ this.deleteStyle = function (styleName) {
+ var op;
+ op = new ops.OpRemoveStyle();
+ op.init({
+ memberid: localMemberId,
+ styleName: styleName,
+ styleFamily: 'paragraph'
+ });
+ session.enqueue([op]);
+ };
+
+ /**
+ * Returns an array of the declared fonts in the ODF document,
+ * with 'duplicates' like Arial1, Arial2, etc removed. The alphabetically
+ * first font name for any given family is kept.
+ * The elements of the array are objects containing the font's name and
+ * the family.
+ * @return {Array.<!Object>}
+ */
+ this.getDeclaredFonts = function () {
+ var fontMap = formatting.getFontMap(),
+ usedFamilies = [],
+ array = [],
+ sortedNames,
+ key,
+ value,
+ i;
+
+ // Sort all the keys in the font map alphabetically
+ sortedNames = Object.keys(fontMap);
+ sortedNames.sort();
+
+ for (i = 0; i < sortedNames.length; i += 1) {
+ key = sortedNames[i];
+ value = fontMap[key];
+
+ // Use the font declaration only if the family is not already used.
+ // Therefore we are able to discard the alphabetic successors of the first
+ // font name.
+ if (usedFamilies.indexOf(value) === -1) {
+ array.push({
+ name: key,
+ family: value
+ });
+ if (value) {
+ usedFamilies.push(value);
+ }
+ }
+ }
+
+ return array;
+ };
+
+ function undoStackModified(e) {
+ self.emit(EditorSession.signalUndoStackChanged, e);
+ }
+
+ this.hasUndoManager = function () {
+ return Boolean(self.sessionController.getUndoManager());
+ };
+
+ this.undo = function () {
+ var undoManager = self.sessionController.getUndoManager();
+ undoManager.moveBackward(1);
+ };
+
+ this.redo = function () {
+ var undoManager = self.sessionController.getUndoManager();
+ undoManager.moveForward(1);
+ };
+
+ /**
+ *
+ * @param {!string} mimetype
+ * @param {!string} content base64 encoded string
+ * @param {!number} width
+ * @param {!number} height
+ */
+ this.insertImage = function (mimetype, content, width, height) {
+ self.sessionController.getTextManipulator().removeCurrentSelection();
+ self.sessionController.getImageManager().insertImage(mimetype, content, width, height);
+ };
+
+ /**
+ * @param {!string} memberId
+ * @return {?ops.Member}
+ */
+ this.getMember = function (memberId) {
+ return odtDocument.getMember(memberId);
+ };
+
+ /**
+ * @param {!function(!Object=)} callback, passing an error object in case of error
+ * @return {undefined}
+ */
+ this.destroy = function(callback) {
+ var head = document.getElementsByTagName('head')[0];
+
+ head.removeChild(fontStyles);
+
+ odtDocument.unsubscribe(ops.OdtDocument.signalMemberAdded, onMemberAdded);
+ odtDocument.unsubscribe(ops.OdtDocument.signalMemberUpdated, onMemberUpdated);
+ odtDocument.unsubscribe(ops.OdtDocument.signalMemberRemoved, onMemberRemoved);
+ odtDocument.unsubscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
+ odtDocument.unsubscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
+ odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
+ odtDocument.unsubscribe(ops.OdtDocument.signalCommonStyleCreated, onStyleCreated);
+ odtDocument.unsubscribe(ops.OdtDocument.signalCommonStyleDeleted, onStyleDeleted);
+ odtDocument.unsubscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified);
+ odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, trackCurrentParagraph);
+ odtDocument.unsubscribe(ops.OdtDocument.signalUndoStackChanged, undoStackModified);
+
+ self.sessionView.destroy(function(err) {
+ if (err) {
+ callback(err);
+ } else {
+ delete self.sessionView;
+ caretManager.destroy(function(err) {
+ if (err) {
+ callback(err);
+ } else {
+ selectionViewManager.destroy(function(err) {
+ if (err) {
+ callback(err);
+ } else {
+ self.sessionController.destroy(function(err) {
+ if (err) {
+ callback(err);
+ } else {
+ delete self.sessionController;
+ callback();
+ }
+ });
+ }
+ });
+ }
+ });
+ }
+ });
+ };
+
+ function init() {
+ var head = document.getElementsByTagName('head')[0];
+
+ // TODO: fonts.css should be rather done by odfCanvas, or?
+ fontStyles.type = 'text/css';
+ fontStyles.media = 'screen, print, handheld, projection';
+ fontStyles.appendChild(document.createTextNode(fontsCSS));
+ head.appendChild(fontStyles);
+
+ self.sessionController = new gui.SessionController(session, localMemberId, shadowCursor, {
+ directParagraphStylingEnabled: config.directParagraphStylingEnabled
+ });
+ caretManager = new gui.CaretManager(self.sessionController);
+ selectionViewManager = new gui.SelectionViewManager();
+ self.sessionView = new gui.SessionView(config.viewOptions, localMemberId, session, caretManager, selectionViewManager);
+ self.availableFonts = getAvailableFonts();
+ selectionViewManager.registerCursor(shadowCursor, true);
+ // Custom signals, that make sense in the Editor context. We do not want to expose webodf's ops signals to random bits of the editor UI.
+ odtDocument.subscribe(ops.OdtDocument.signalMemberAdded, onMemberAdded);
+ odtDocument.subscribe(ops.OdtDocument.signalMemberUpdated, onMemberUpdated);
+ odtDocument.subscribe(ops.OdtDocument.signalMemberRemoved, onMemberRemoved);
+ odtDocument.subscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
+ odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
+ odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
+ odtDocument.subscribe(ops.OdtDocument.signalCommonStyleCreated, onStyleCreated);
+ odtDocument.subscribe(ops.OdtDocument.signalCommonStyleDeleted, onStyleDeleted);
+ odtDocument.subscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified);
+ odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, trackCurrentParagraph);
+ odtDocument.subscribe(ops.OdtDocument.signalUndoStackChanged, undoStackModified);
+ }
+
+ init();
+ };
+
+ /**@const*/EditorSession.signalMemberAdded = "memberAdded";
+ /**@const*/EditorSession.signalMemberUpdated = "memberUpdated";
+ /**@const*/EditorSession.signalMemberRemoved = "memberRemoved";
+ /**@const*/EditorSession.signalCursorAdded = "cursorAdded";
+ /**@const*/EditorSession.signalCursorRemoved = "cursorRemoved";
+ /**@const*/EditorSession.signalCursorMoved = "cursorMoved";
+ /**@const*/EditorSession.signalParagraphChanged = "paragraphChanged";
+ /**@const*/EditorSession.signalCommonStyleCreated = "styleCreated";
+ /**@const*/EditorSession.signalCommonStyleDeleted = "styleDeleted";
+ /**@const*/EditorSession.signalParagraphStyleModified = "paragraphStyleModified";
+ /**@const*/EditorSession.signalUndoStackChanged = "signalUndoStackChanged";
+
+ return EditorSession;
+});
diff --cc apps/documents/js/3rdparty/webodf/editor/server/ServerFactory.js
index c028c42,0000000..2368044
mode 100644,000000..100644
--- a/apps/documents/js/3rdparty/webodf/editor/server/ServerFactory.js
+++ b/apps/documents/js/3rdparty/webodf/editor/server/ServerFactory.js
@@@ -1,64 -1,0 +1,65 @@@
+/**
+ * @license
+ * Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+ *
+ * @licstart
+ * The JavaScript code in this page is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Affero General Public License
+ * (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version. The code is distributed
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this code. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As additional permission under GNU AGPL version 3 section 7, you
+ * may distribute non-source (e.g., minimized or compacted) forms of
+ * that code without the copy of the GNU GPL normally required by
+ * section 4, provided you include this license notice and a URL
+ * through which recipients can access the Corresponding Source.
+ *
+ * As a special exception to the AGPL, any HTML file which merely makes function
+ * calls to this code, and for that purpose includes it by reference shall be
+ * deemed a separate work for copyright law purposes. In addition, the copyright
+ * holders of this code give you permission to combine this code with free
+ * software libraries that are released under the GNU LGPL. You may copy and
+ * distribute such a system following the terms of the GNU AGPL for this code
+ * and the LGPL for the libraries. If you modify this code, you may extend this
+ * exception to your version of the code, but you are not obligated to do so.
+ * If you do not wish to do so, delete this exception statement from your
+ * version.
+ *
+ * This license applies to this entire compilation.
+ * @licend
+ * @source: http://www.webodf.org/
+ * @source: https://github.com/kogmbh/WebODF/
+ */
+
+/*global ops, SessionList*/
+
+/**
+ * @interface
+ */
+function ServerFactory() {"use strict"; };
+
+/**
+ * @return {!ops.Server}
+ */
+ServerFactory.prototype.createServer = function () {"use strict"; };
+
+/**
+ * @param {!string} sessionId
+ * @param {!string} memberId
+ * @param {!ops.Server} server
+ * @param {!odf.OdfContainer} odfContainer TODO: needed for pullbox writing to server at end, find better solution
++ * @param {!function(!Object)} errorCallback
+ * @return {!ops.OperationRouter}
+ */
- ServerFactory.prototype.createOperationRouter = function (sessionId, memberId, server, odfContainer) {"use strict"; };
++ServerFactory.prototype.createOperationRouter = function (sessionId, memberId, server, odfContainer, errorCallback) {"use strict"; };
+
+/**
+ * @param {!ops.Server} server
+ * @return {!SessionList}
+ */
+ServerFactory.prototype.createSessionList = function (server) {"use strict"; };
diff --cc apps/documents/js/3rdparty/webodf/editor/server/owncloud/ServerFactory.js
index 7c4e106,0000000..0d6b2b4
mode 100644,000000..100644
--- a/apps/documents/js/3rdparty/webodf/editor/server/owncloud/ServerFactory.js
+++ b/apps/documents/js/3rdparty/webodf/editor/server/owncloud/ServerFactory.js
@@@ -1,60 -1,0 +1,60 @@@
+/**
+ * @license
+ * Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+ *
+ * @licstart
+ * This file is part of WebODF.
+ *
+ * WebODF is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Affero General Public License (GNU AGPL)
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * WebODF is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ * @licend
+ *
+ * @source: http://www.webodf.org/
+ * @source: https://github.com/kogmbh/WebODF/
+ */
+
+/*global define, require, OC*/
+
+define("webodf/editor/server/owncloud/ServerFactory", [
+ "webodf/editor/server/pullbox/Server",
+ "webodf/editor/server/pullbox/OperationRouter",
+ "webodf/editor/server/pullbox/SessionList"],
+ function (PullBoxServer, PullBoxOperationRouter, PullBoxSessionList) {
+ "use strict";
+
+ /**
+ * @constructor
+ * @implements ServerFactory
+ */
+ return function OwnCloudServerFactory() {
+ this.createServer = function (args) {
+ var server;
+ args = args || {};
+ args.url = OC.filePath('documents', 'ajax', 'otpoll.php');
+ args.sessionStateToFileUrl = OC.Router.generate('documents_session_save');
+
+ server = new PullBoxServer(args);
+ server.getGenesisUrl = function(sid) {
+ // what a dirty hack :)
+ return OC.Router.generate('documents_genesis') + '/' + sid;
+ };
+ return server;
+ };
- this.createOperationRouter = function (sid, mid, server, odfContainer) {
- return new PullBoxOperationRouter(sid, mid, server, odfContainer);
++ this.createOperationRouter = function (sid, mid, server, odfContainer, errorCallback) {
++ return new PullBoxOperationRouter(sid, mid, server, odfContainer, errorCallback);
+ };
+ this.createSessionList = function (server) {
+ return new PullBoxSessionList(server);
+ };
+ };
+});
diff --cc apps/documents/js/3rdparty/webodf/editor/server/pullbox/OperationRouter.js
index a24744a,0000000..a6cf8d6
mode 100644,000000..100644
--- a/apps/documents/js/3rdparty/webodf/editor/server/pullbox/OperationRouter.js
+++ b/apps/documents/js/3rdparty/webodf/editor/server/pullbox/OperationRouter.js
@@@ -1,458 -1,0 +1,590 @@@
+/**
+ * @license
+ * Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+ *
+ * @licstart
+ * This file is part of WebODF.
+ *
+ * WebODF is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Affero General Public License (GNU AGPL)
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * WebODF is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ * @licend
+ *
+ * @source: http://www.webodf.org/
+ * @source: https://github.com/kogmbh/WebODF/
+ */
+
+/*global runtime, ops*/
+
+define("webodf/editor/server/pullbox/OperationRouter", [], function () {
+ "use strict";
+
++ // TODO: these eventid strings should be defined at OperationRouter interface
++ var /**@const @type {!string}*/
++ EVENT_BEFORESAVETOFILE = "beforeSaveToFile",
++ /**@const @type {!string}*/
++ EVENT_SAVEDTOFILE = "savedToFile",
++ /**@const @type {!string}*/
++ EVENT_HASLOCALUNSYNCEDOPERATIONSCHANGED = "hasLocalUnsyncedOperationsChanged",
++ /**@const @type {!string}*/
++ EVENT_HASSESSIONHOSTCONNECTIONCHANGED = "hasSessionHostConnectionChanged";
++
+ runtime.loadClass("ops.OperationTransformer");
++ runtime.loadClass("core.EventNotifier");
+
+ /**
+ * route operations in a networked collaborative manner.
+ *
+ * incoming operations (from controller) are sent to a server,
+ * who will distribute them.
+ *
+ * incoming operations (from the server are played on the DOM.
+ */
+
+ /**
+ * @constructor
+ * @implements ops.OperationRouter
+ */
- return function PullBoxOperationRouter(sessionId, memberId, server, odfContainer) {
++ return function PullBoxOperationRouter(sessionId, memberId, server, odfContainer, errorCallback) {
+ "use strict";
+
+ var operationFactory,
- /**@type{function(!ops.Operation)}*/
++ /**@type{function(!ops.Operation):boolean}*/
+ playbackFunction,
+ idleTimeout = null,
+ syncOpsTimeout = null,
+ /**@type{!boolean}*/
+ isInstantSyncRequested = false,
+ /**@type{!boolean}*/
+ isPlayingUnplayedServerOpSpecs = false,
+ /**@type{!boolean}*/
+ isSyncCallRunning = false,
+ /**@type{!boolean}*/
- hasUnresolvableConflict = false,
++ hasError = false,
+ /**@type{!boolean}*/
+ syncingBlocked = false,
+ /** @type {!string} id of latest op stack state known on the server */
+ lastServerSeq = "",
+ /** @type {!Array.<!Function>} sync request callbacks created since the last sync call to the server */
+ syncRequestCallbacksQueue = [],
+ /** @type {!Array.<!Object>} ops created since the last sync call to the server */
+ unsyncedClientOpspecQueue = [],
+ /** @type {!Array.<!Object>} ops already received from the server but not yet applied */
+ unplayedServerOpspecQueue = [],
+ /** @type {!Array.<!Function>} sync request callbacks which should be called after the received ops have been applied server */
+ uncalledSyncRequestCallbacksQueue = [],
++ /** @type {!Array.<!function(!boolean):undefined>} ops created since the last sync call to the server */
++ hasLocalUnsyncedOpsStateSubscribers = [],
+ /**@type{!boolean}*/
+ hasLocalUnsyncedOps = false,
++ /** @type {!Array.<!function(!boolean):undefined>} */
++ hasSessionHostConnectionStateSubscribers = [],
++ /**@type{!boolean}*/
++ hasSessionHostConnection = true,
++ eventNotifier = new core.EventNotifier([
++ EVENT_BEFORESAVETOFILE,
++ EVENT_SAVEDTOFILE,
++ EVENT_HASLOCALUNSYNCEDOPERATIONSCHANGED,
++ EVENT_HASSESSIONHOSTCONNECTIONCHANGED
++ ]),
+ /**@type{!boolean} tells if any local ops have been modifying ops */
+ hasPushedModificationOps = false,
+ operationTransformer = new ops.OperationTransformer(),
+ /**@const*/replayTime = 500,
+ /**@const*/syncOpsDelay = 3000,
+ /**@const*/idleDelay = 5000;
+
+ /**
+ * @return {undefined}
+ */
+ function updateHasLocalUnsyncedOpsState() {
- var hasLocalUnsyncedOpsNow = (unsyncedClientOpspecQueue.length > 0);
++ var i,
++ hasLocalUnsyncedOpsNow = (unsyncedClientOpspecQueue.length > 0);
+
+ // no change?
+ if (hasLocalUnsyncedOps === hasLocalUnsyncedOpsNow) {
+ return;
+ }
+
+ hasLocalUnsyncedOps = hasLocalUnsyncedOpsNow;
++ eventNotifier.emit(EVENT_HASLOCALUNSYNCEDOPERATIONSCHANGED, hasLocalUnsyncedOps);
++ }
++
++ /**
++ * @param {!boolean} hasConnection
++ * @return {undefined}
++ */
++ function updateHasSessionHostConnectionState(hasConnection) {
++ var i;
++
++ // no change?
++ if (hasSessionHostConnection === hasConnection) {
++ return;
++ }
++
++ hasSessionHostConnection = hasConnection;
++ eventNotifier.emit(EVENT_HASSESSIONHOSTCONNECTIONCHANGED, hasSessionHostConnection);
+ }
+
+ /**
+ * @return {undefined}
+ */
+ function playUnplayedServerOpSpecs() {
+ /**
+ * @return {undefined}
+ */
+ function doPlayUnplayedServerOpSpecs() {
+ var opspec, op, startTime, i;
+
+ isPlayingUnplayedServerOpSpecs = false;
+
+ // take start time
+ startTime = (new Date()).getTime();
+
+ // apply as much as possible in the given time
+ while (unplayedServerOpspecQueue.length > 0) {
+ // time over?
+ if ((new Date().getTime()) - startTime > replayTime) {
+ break;
+ }
+
+ opspec = unplayedServerOpspecQueue.shift();
+
+ // use factory to create an instance, and playback!
+ op = operationFactory.create(opspec);
+ runtime.log(" op in: "+runtime.toJson(opspec));
+ if (op !== null) {
- playbackFunction(op);
++ if (!playbackFunction(op)) {
++ hasError = true;
++ errorCallback("opExecutionFailure");
++ return;
++ }
+ } else {
++ hasError = true;
+ runtime.log("ignoring invalid incoming opspec: " + opspec);
++ errorCallback("unknownOpReceived");
++ return;
+ }
+ }
+
+ // still unplayed opspecs?
+ if (unplayedServerOpspecQueue.length > 0) {
+ // let other events be handled. then continue
+ isPlayingUnplayedServerOpSpecs = true;
+ runtime.getWindow().setTimeout(doPlayUnplayedServerOpSpecs, 1);
+ } else {
+ // finally call all the callbacks waiting for that sync!
+ for (i = 0; i < uncalledSyncRequestCallbacksQueue.length; i += 1) {
+ uncalledSyncRequestCallbacksQueue[i]();
+ }
+
+ uncalledSyncRequestCallbacksQueue = [];
+ }
+ }
+
+ if (isPlayingUnplayedServerOpSpecs) {
+ return;
+ }
+ doPlayUnplayedServerOpSpecs();
+ }
+
+ /**
+ * @param {Array.<!Object>} opspecs
+ * @param {Array.<!Function>} callbacks
+ * @return {undefined}
+ */
+ function receiveOpSpecsFromNetwork(opspecs, callbacks) {
+ // append to existing unplayed
+ unplayedServerOpspecQueue = unplayedServerOpspecQueue.concat(opspecs);
+ uncalledSyncRequestCallbacksQueue = uncalledSyncRequestCallbacksQueue.concat(callbacks);
+ }
+
+ /**
+ * Transforms the unsynced client ops and the server ops,
+ * applies the server ops after transformation
+ * @param {Array.<!Object>} serverOpspecs
+ * @return {!boolean}
+ */
+ function handleOpsSyncConflict(serverOpspecs) {
+ var i,
+ transformResult;
+
+ if (! serverOpspecs) {
+ // TODO: proper error message, stop working
+ runtime.assert(false, "no opspecs received!");
+ return false;
+ } // TODO: more checking of proper content in serverOpspecs
+
+ transformResult = operationTransformer.transform(unsyncedClientOpspecQueue, /**@type{!Array.<!Object>}*/(serverOpspecs));
+
+ if (!transformResult) {
+ return false;
+ }
+
+ // store transformed server ops
+ for (i = 0; i < transformResult.opsB.length; i += 1) {
+ unplayedServerOpspecQueue.push(transformResult.opsB[i].spec());
+ }
+
+ // store opspecs of all transformed client opspecs
+ unsyncedClientOpspecQueue = [];
+ for (i = 0; i < transformResult.opsA.length; i += 1) {
+ unsyncedClientOpspecQueue.push(transformResult.opsA[i].spec());
+ }
+
+ return true;
+ }
+
+ /**
+ * @return {undefined}
+ */
+ function syncOps() {
+ var syncedClientOpspecs,
+ syncRequestCallbacksArray;
+
+ /**
+ * @return {undefined}
+ */
+ function startSyncOpsTimeout() {
+ idleTimeout = null;
+ syncOpsTimeout = runtime.getWindow().setTimeout(function() {
+ syncOpsTimeout = null;
+ syncOps();
+ }, syncOpsDelay);
+ }
+
- if (isSyncCallRunning || hasUnresolvableConflict) {
++ if (isSyncCallRunning || hasError) {
+ return;
+ }
+ // TODO: hack, remove
+ if (syncingBlocked) {
+ return;
+ }
+
+runtime.log("OperationRouter: sending sync_ops call");
+ // no more instant pull request in any case
+ isInstantSyncRequested = false;
+ // set lock
+ isSyncCallRunning = true;
+
+ // take specs from queue, if any
+ syncedClientOpspecs = unsyncedClientOpspecQueue;
+ unsyncedClientOpspecQueue = [];
+ syncRequestCallbacksArray = syncRequestCallbacksQueue;
+ syncRequestCallbacksQueue = [];
+
+ server.call({
+ command: 'sync_ops',
+ args: {
+ es_id: sessionId,
+ member_id: memberId,
+ seq_head: String(lastServerSeq),
+ client_ops: syncedClientOpspecs
+ }
+ }, function(responseData) {
- var response = /** @type{{result:string, head_seq:string, ops:Array.<!Object>}} */(runtime.fromJson(responseData));
++ var response,
++ /**@type{!boolean}*/
++ hasUnresolvableConflict = false;
++
++ updateHasSessionHostConnectionState(true);
+
- // TODO: hack, remove
+ if (syncingBlocked) {
+ return;
+ }
+
++ try {
++ response = /** @type{{result:string, head_seq:string, ops:Array.<!Object>}} */(runtime.fromJson(responseData));
++ } catch (e) {
++ hasError = true;
++ runtime.log("Could not parse reply: "+responseData);
++ errorCallback("unknownServerReply");
++ return;
++ }
++ // TODO: hack, remove
+ runtime.log("sync_ops reply: " + responseData);
+
+ // just new ops?
+ if (response.result === "new_ops") {
+ if (response.ops.length > 0) {
+ // no new locally in the meantime?
+ if (unsyncedClientOpspecQueue.length === 0) {
+ receiveOpSpecsFromNetwork(response.ops, syncRequestCallbacksArray);
+ } else {
+ // transform server ops against new local ones and apply,
+ // transform and send new local ops to server
+ runtime.log("meh, have new ops locally meanwhile, have to do transformations.");
+ hasUnresolvableConflict = !handleOpsSyncConflict(response.ops);
+ syncRequestCallbacksQueue = syncRequestCallbacksArray.concat(syncRequestCallbacksQueue);
+ }
+ // and note server state
+ lastServerSeq = response.head_seq;
+ } else {
+ receiveOpSpecsFromNetwork([], syncRequestCallbacksArray);
+ }
+ } else if (response.result === "added") {
+ runtime.log("All added to server");
+ receiveOpSpecsFromNetwork([], syncRequestCallbacksArray);
+ // note server state
+ lastServerSeq = response.head_seq;
+ updateHasLocalUnsyncedOpsState();
+ } else if (response.result === "conflict") {
+ // put the send ops back into the outgoing queue
+ unsyncedClientOpspecQueue = syncedClientOpspecs.concat(unsyncedClientOpspecQueue);
+ syncRequestCallbacksQueue = syncRequestCallbacksArray.concat(syncRequestCallbacksQueue);
+ // transform server ops against new local ones and apply,
+ // transform and request new send new local ops to server
+ runtime.log("meh, server has new ops meanwhile, have to do transformations.");
+ hasUnresolvableConflict = !handleOpsSyncConflict(response.ops);
+ // and note server state
+ lastServerSeq = response.head_seq;
+ // try again instantly
+ if (!hasUnresolvableConflict) {
+ isInstantSyncRequested = true;
+ }
++ } else if (response.result === "error") {
++ runtime.log("server reports an error: "+response.error);
++ hasError = true;
++ errorCallback(
++ response.error === "ENOSESSION" ? "sessionDoesNotExist":
++ response.error === "ENOMEMBER" ? "notMemberOfSession":
++ "unknownServerReply"
++ );
++ return;
+ } else {
- runtime.assert(false, "Unexpected result on sync-ops call: "+response.result);
++ hasError = true;
++ runtime.log("Unexpected result on sync-ops call: "+response.result);
++ errorCallback("unknownServerReply");
++ return;
+ }
+
+ // unlock
+ isSyncCallRunning = false;
+
+ if (hasUnresolvableConflict) {
- // TODO: offer option to reload session automatically?
- runtime.assert(false,
- "Sorry to tell:\n" +
- "we hit a pair of operations in a state which yet need to be supported for transformation against each other.\n" +
- "Client disconnected from session, no further editing accepted.\n\n" +
- "Please reconnect manually for now.");
++ hasError = true;
++ errorCallback("unresolvableConflictingOps");
+ } else {
+ // prepare next sync
+ if (isInstantSyncRequested) {
+ syncOps();
+ } else {
+ // nothing on client to sync?
+ if (unsyncedClientOpspecQueue.length === 0) {
+ idleTimeout = runtime.getWindow().setTimeout(startSyncOpsTimeout, idleDelay);
+ } else {
+ startSyncOpsTimeout();
+ }
+ }
+ playUnplayedServerOpSpecs();
+ }
++ }, function() {
++ runtime.log("meh, server cannot be reached ATM.");
++ // signal connection problem, but do not give up for now
++ updateHasSessionHostConnectionState(false);
++ // put the (not) send ops back into the outgoing queue
++ unsyncedClientOpspecQueue = syncedClientOpspecs.concat(unsyncedClientOpspecQueue);
++ syncRequestCallbacksQueue = syncRequestCallbacksArray.concat(syncRequestCallbacksQueue);
++ // unlock
++ isSyncCallRunning = false;
++ // nothing on client to sync?
++ if (unsyncedClientOpspecQueue.length === 0) {
++ idleTimeout = runtime.getWindow().setTimeout(startSyncOpsTimeout, idleDelay);
++ } else {
++ startSyncOpsTimeout();
++ }
++ playUnplayedServerOpSpecs();
+ });
+ }
+
+ function triggerPushingOps() {
+ // disable any idle timeout
+ if (idleTimeout) {
+ runtime.clearTimeout(idleTimeout);
+ idleTimeout = null;
+ }
+
+ // enable syncOps timeout, if needed
+ if (!syncOpsTimeout && !isSyncCallRunning) {
+runtime.log("OperationRouter: opsSync requested for pushing");
+ syncOpsTimeout = runtime.getWindow().setTimeout(function() {
+ syncOpsTimeout = null;
+ syncOps();
+ }, syncOpsDelay);
+ }
+ }
+
+ /**
+ * @param {!Funtion} cb
+ * @return {undefined}
+ */
+ function requestInstantOpsSync(cb) {
+ // register callback
+ syncRequestCallbacksQueue.push(cb);
+
+ // disable any idle timeout
+ if (idleTimeout) {
+ runtime.clearTimeout(idleTimeout);
+ idleTimeout = null;
+ }
+
+ // disable any syncOps timeout
+ if (syncOpsTimeout) {
+ runtime.clearTimeout(syncOpsTimeout);
+ syncOpsTimeout = null;
+ }
+
+runtime.log("OperationRouter: instant opsSync requested");
+ isInstantSyncRequested = true;
+ syncOps();
+ };
+
+ this.requestReplay = function (done_cb) {
+ requestInstantOpsSync(done_cb);
+ };
+
+ /**
+ * Sets the factory to use to create operation instances from operation specs.
+ *
+ * @param {!ops.OperationFactory} f
+ * @return {undefined}
+ */
+ this.setOperationFactory = function (f) {
+ operationFactory = f;
+ operationTransformer.setOperationFactory(f);
+ };
+
+ /**
+ * Sets the method which should be called to apply operations.
+ *
- * @param {!function(!ops.Operation)} playback_func
++ * @param {!function(!ops.Operation):boolean} playback_func
+ * @return {undefined}
+ */
+ this.setPlaybackFunction = function (playback_func) {
+ playbackFunction = playback_func;
+ };
+
+ /**
+ * Brings the locally created operations into the game.
+ *
+ * @param {!Array.<!ops.Operation>} operations
+ * @return {undefined}
+ */
+ this.push = function (operations) {
- if (hasUnresolvableConflict) {
++ var i, op, opspec,
++ timestamp = (new Date()).getTime();
++
++ if (hasError) {
+ return;
+ }
+ // TODO: should be an assert in the future
+ // there needs to be a flag telling that processing is happening,
+ // and thus any input should be dropped in the sessioncontroller
+ // ideally also have some UI element showing the processing state
+ if (unplayedServerOpspecQueue.length > 0) {
+ return;
+ }
+
- operations.forEach(function(op) {
- var timedOp,
- opspec = op.spec();
++ for (i = 0; i < operations.length; i += 1) {
++ op = operations[i];
++ opspec = op.spec();
+
+ // note if any local ops modified
+ hasPushedModificationOps = hasPushedModificationOps || op.isEdit;
+
- // apply locally
- opspec.timestamp = (new Date()).getTime();
- timedOp = operationFactory.create(opspec);
++ // add timestamp TODO: improve the useless recreation of the op
++ opspec.timestamp = timestamp;
++ op = operationFactory.create(opspec);
+
- playbackFunction(timedOp);
++ // apply locally
++ if (!playbackFunction(op)) {
++ hasError = true;
++ errorCallback("opExecutionFailure");
++ return;
++ }
+
+ // send to server
+ unsyncedClientOpspecQueue.push(opspec);
- });
++ }
+
+ triggerPushingOps();
+
+ updateHasLocalUnsyncedOpsState();
+ };
+
+ /**
+ * Requests a gracefull shutdown of the Operation Router.
+ * Buffered operations shall be sent to the server.
+ * A callback is called on success.
+ */
+ this.close = function (cb) {
++ function cbDoneSaving(err) {
++ eventNotifier.emit(EVENT_SAVEDTOFILE, null);
++ cb(err);
++ }
++
+ function cbSuccess(fileData) {
- server.writeSessionStateToFile(sessionId, memberId, lastServerSeq, fileData, cb);
++ server.writeSessionStateToFile(sessionId, memberId, lastServerSeq, fileData, cbDoneSaving);
+ }
+
+ function doClose() {
+ syncingBlocked = true;
+ if (hasPushedModificationOps) {
- odfContainer.createByteArray(cbSuccess, cb);
++ eventNotifier.emit(EVENT_BEFORESAVETOFILE, null);
++
++ odfContainer.createByteArray(cbSuccess, cbDoneSaving);
+ } else {
+ cb();
+ }
+ }
+
- if (hasLocalUnsyncedOps) {
++ if (hasError) {
++ cb();
++ } else if (hasLocalUnsyncedOps) {
+ requestInstantOpsSync(doClose);
+ } else {
+ doClose();
+ }
+ };
+
++ /**
++ * @param {!string} eventId
++ * @param {!Function} cb
++ * @return {undefined}
++ */
++ this.subscribe = function (eventId, cb) {
++ eventNotifier.subscribe(eventId, cb);
++ };
++
++ /**
++ * @param {!string} eventId
++ * @param {!Function} cb
++ * @return {undefined}
++ */
++ this.unsubscribe = function (eventId, cb) {
++ eventNotifier.unsubscribe(eventId, cb);
++ };
++
++ /**
++ * @return {!boolean}
++ */
++ this.hasLocalUnsyncedOps = function () {
++ return hasLocalUnsyncedOps;
++ };
++
++ /**
++ * @return {!boolean}
++ */
++ this.hasSessionHostConnection = function () {
++ return hasSessionHostConnection;
++ };
+ };
+});
diff --cc apps/documents/js/3rdparty/webodf/editor/server/pullbox/Server.js
index ee17cee,0000000..9b749fd
mode 100644,000000..100644
--- a/apps/documents/js/3rdparty/webodf/editor/server/pullbox/Server.js
+++ b/apps/documents/js/3rdparty/webodf/editor/server/pullbox/Server.js
@@@ -1,272 -1,0 +1,283 @@@
+/**
+ * @license
+ * Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+ *
+ * @licstart
+ * This file is part of WebODF.
+ *
+ * WebODF is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Affero General Public License (GNU AGPL)
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * WebODF is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ * @licend
+ *
+ * @source: http://www.webodf.org/
+ * @source: https://github.com/kogmbh/WebODF/
+ */
+
+/*global XMLHttpRequest, runtime, core, ops*/
+
+define("webodf/editor/server/pullbox/Server", [], function () {
+ "use strict";
+
+ runtime.loadClass("core.Base64");
+ runtime.loadClass("core.ByteArrayWriter");
+
+ /**
+ * @constructor
+ * @implements ops.Server
+ * @param {{url:string}} args
+ */
+ return function PullBoxServer(args) {
+
+ var self = this,
+ token,
++ /**@const*/serverCallTimeout = 10000,
+ base64 = new core.Base64();
+
+ args = args || {};
+ args.url = args.url || "/WSER";
+ args.sessionStateToFileUrl = args.sessionStateToFileUrl || "/SS2F"
+
+ this.getGenesisUrl = function (sessionId) {
+ return "/session/" + sessionId + "/genesis";
+ };
+
+ /**
+ * @param {!Object} message
+ * @param {!function(!string)} cb
++ * @param {!function(!number,!string)} cbError passes the status number
++ * and the statustext, or -1 if there was an exception on sending
+ * @return {undefined}
+ */
- function call(message, cb) {
++ function call(message, cb, cbError) {
+ var xhr = new XMLHttpRequest(),
+ messageString = JSON.stringify(message);
+
+ function handleResult() {
+ if (xhr.readyState === 4) {
- if ((xhr.status < 200 || xhr.status >= 300) && xhr.status === 0) {
++ if (xhr.status < 200 || xhr.status >= 300) {
+ // report error
+ runtime.log("Status " + String(xhr.status) + ": " +
+ xhr.responseText || xhr.statusText);
++ cbError(xhr.status, xhr.statusText);
++ } else {
++ runtime.log("Status " + String(xhr.status) + ": " +
++ xhr.responseText || xhr.statusText);
++ cb(xhr.responseText);
+ }
- cb(xhr.responseText);
+ }
+ }
++ function handleTimeout() {
++ runtime.log("Timeout on call to server.");
++ cbError(0, xhr.statusText);
++ }
++
+runtime.log("Sending message to server: "+messageString);
+ // create body data for request from metadata and payload
+
+ // do the request
+ xhr.open('POST', args.url, true);
+ if (token) {
+ xhr.setRequestHeader("requesttoken", token);
+ }
+ xhr.onreadystatechange = handleResult;
++ xhr.timeout = serverCallTimeout;
++ // TODO: seems handleResult is called on timeout as well, with xhr.status === 0
++// xhr.ontimeout = handleTimeout;
+ try {
+ xhr.send(messageString);
+ } catch (e) {
+ runtime.log("Problem with calling server: " + e + " " + data);
- cb(e.message);
++ cbError(-1, e.message);
+ }
+ }
+
+ this.call = call;
+
+ this.getToken = function () {
+ return token;
+ };
+
+ /**
+ * for pre-authenticated use
+ */
+ this.setToken = function (a_token) {
+ token = a_token;
+ };
+
+
+ /*jslint unparam: true*/
+ /**
+ * @param {!number} timeout in milliseconds
+ * @param {!function(!string)} callback
+ * @return {undefined}
+ */
+ this.connect = function (timeout, callback) {
+ /*
+ var accumulatedWaitingTime = 0;
+
+ // already tried connecting?
+ if (self.networkStatus() === "ready") {
+ return;
+ }
+ */
+ callback("ready");
+ };
+ /*jslint unparam: false*/
+
+ /**
+ * @return {!string}
+ */
+ this.networkStatus = function () {
+ return "ready";
+ };
+
+ /**
+ * @param {!string} login
+ * @param {!string} password
+ * @param {function(!Object)} successCb
+ * @param {function(!string)} failCb
+ * @return {undefined}
+ */
+ this.login = function (login, password, successCb, failCb) {
+ call({
+ command: "login",
+ args: {
+ login: base64.toBase64(login),
+ password: base64.toBase64(password)
+ }
+ }, function(responseData) {
+ var response = /**@type {{token:string}}*/(runtime.fromJson(responseData));
+ runtime.log("Login reply: " + responseData);
+
+ if (response.hasOwnProperty("token")) {
+ token = response.token;
+ runtime.log("Caching token: " + self.getToken());
+ successCb(response);
+ } else {
+ failCb(responseData);
+ }
- });
++ }, failCb);
+ };
+
+ /**
+ * @param {!string} userId
+ * @param {!string} sessionId
+ * @param {!function(!string)} successCb
- * @param {function()=} failCb
++ * @param {!function()} failCb
+ * @return {undefined}
+ */
+ this.joinSession = function (userId, sessionId, successCb, failCb) {
+ call({
+ command: "join_session",
+ args: {
+ user_id: userId,
+ es_id: sessionId
+ }
+ }, function(responseData) {
+ var response = /**@type {{success:string, member_id:string}}*/(runtime.fromJson(responseData));
+ runtime.log("join_session reply: " + responseData);
+
+ if (response.hasOwnProperty("success") && response.success) {
+ successCb(response.member_id);
+ } else {
- if (failCb) {
- failCb();
- }
++ failCb();
+ }
- });
++ }, failCb);
+ };
+
+ /**
+ * @param {!string} sessionId
+ * @param {!string} memberId
+ * @param {!function()} successCb
- * @param {function()=} failCb
++ * @param {!function()} failCb
+ * @return {undefined}
+ */
+ this.leaveSession = function (sessionId, memberId, successCb, failCb) {
+ call({
+ command: "leave_session",
+ args: {
+ es_id: sessionId,
+ member_id: memberId
+ }
+ }, function(responseData) {
+ var response = /**@type {{success:string, member_id:string}}*/(runtime.fromJson(responseData));
+ runtime.log("leave_session reply: " + responseData);
+
+ if (response.hasOwnProperty("success") && response.success) {
+ successCb();
+ } else {
- if (failCb) {
- failCb();
- }
++ failCb();
+ }
- });
++ }, failCb);
+ };
+
+ /**
+ * @param {!string} sessionId
+ * @param {!string} memberId
+ * @param {!string} seqHead
- * @param {function()=} callback
++ * @param {!function(!Object=)} callback
+ * @return {undefined}
+ */
+ this.writeSessionStateToFile = function(sessionId, memberId, seqHead, fileData, callback) {
+ // code copied from BrowserRuntime.writeFile and adapted
+ var xhr = new XMLHttpRequest();
+
+ function handleResult() {
+ if (xhr.readyState === 4) {
+ if (xhr.status === 0 && !xhr.responseText) {// TODO: check makes sense here as well?
+ // for local files there is no difference between missing
+ // and empty files, so empty files are considered as errors
+ runtime.log("File " + args.sessionStateToFileUrl + " is empty.");
+ } else if ((xhr.status >= 200 && xhr.status < 300) ||
+ xhr.status === 0) {
+ // report success
+ runtime.log(null);
+ } else {
+ // report error
+ runtime.log("Status " + String(xhr.status) + ": " +
+ xhr.responseText || xhr.statusText);
+ }
+ callback();
+ }
+ }
+
+ // do the request
+ xhr.open('POST', args.sessionStateToFileUrl, true);
+ if (token) {
+ xhr.setRequestHeader("requesttoken", token);
+ }
+ xhr.setRequestHeader("webodf-session-id", sessionId);
+ xhr.setRequestHeader("webodf-member-id", memberId);
+ xhr.setRequestHeader("webodf-session-revision", seqHead);
+ xhr.onreadystatechange = handleResult;
+ // ArrayBufferView will have an ArrayBuffer property, in WebKit, XHR can send()
+ // an ArrayBuffer, In Firefox, one must use sendAsBinary with a string
+ if (fileData.buffer && !xhr.sendAsBinary) {
+ fileData = fileData.buffer; // webkit supports sending an ArrayBuffer
+ } else {
+ // encode into a string, this works in FireFox >= 3
+ fileData = runtime.byteArrayToString(fileData, "binary");
+ }
+ try {
+ if (xhr.sendAsBinary) {
+ xhr.sendAsBinary(fileData);
+ } else {
+ xhr.send(fileData);
+ }
+ } catch (e) {
+ runtime.log("Problem with calling \"writeSessionStateToFile\" on server");
+ callback(e.message);
+ }
+ };
+ };
+});
diff --cc apps/documents/js/3rdparty/webodf/editor/server/pullbox/ServerFactory.js
index b2b5478,0000000..626b5ed
mode 100644,000000..100644
--- a/apps/documents/js/3rdparty/webodf/editor/server/pullbox/ServerFactory.js
+++ b/apps/documents/js/3rdparty/webodf/editor/server/pullbox/ServerFactory.js
@@@ -1,50 -1,0 +1,50 @@@
+/**
+ * @license
+ * Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+ *
+ * @licstart
+ * This file is part of WebODF.
+ *
+ * WebODF is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Affero General Public License (GNU AGPL)
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * WebODF is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ * @licend
+ *
+ * @source: http://www.webodf.org/
+ * @source: https://github.com/kogmbh/WebODF/
+ */
+
+/*global define, document, require, runtime, ops */
+
+define("webodf/editor/server/pullbox/ServerFactory", [
+ "webodf/editor/server/pullbox/Server",
+ "webodf/editor/server/pullbox/OperationRouter",
+ "webodf/editor/server/pullbox/SessionList"],
+ function (PullBoxServer, PullBoxOperationRouter, PullBoxSessionList) {
+ "use strict";
+
+ /**
+ * @constructor
+ * @implements ServerFactory
+ */
+ return function PullBoxServerFactory() {
+ this.createServer = function (args) {
+ return new PullBoxServer(args);
+ };
- this.createOperationRouter = function (sid, mid, server, odfContainer) {
- return new PullBoxOperationRouter(sid, mid, server, odfContainer);
++ this.createOperationRouter = function (sid, mid, server, odfContainer, errorCallback) {
++ return new PullBoxOperationRouter(sid, mid, server, odfContainer, errorCallback);
+ };
+ this.createSessionList = function (server) {
+ return new PullBoxSessionList(server);
+ };
+ };
+});
diff --cc apps/documents/js/3rdparty/webodf/editor/server/pullbox/SessionList.js
index 988da2e,0000000..68b9616
mode 100644,000000..100644
--- a/apps/documents/js/3rdparty/webodf/editor/server/pullbox/SessionList.js
+++ b/apps/documents/js/3rdparty/webodf/editor/server/pullbox/SessionList.js
@@@ -1,172 -1,0 +1,174 @@@
+/**
+ * @license
+ * Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+ *
+ * @licstart
+ * This file is part of WebODF.
+ *
+ * WebODF is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Affero General Public License (GNU AGPL)
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * WebODF is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ * @licend
+ *
+ * @source: http://www.webodf.org/
+ * @source: https://github.com/kogmbh/WebODF/
+ */
+
+/*global define, ops, runtime */
+
+define("webodf/editor/server/pullbox/SessionList", [], function () {
+ "use strict";
+
+ return function PullBoxSessionList(server) {
+ var cachedSessionData = {},
+ subscribers = [],
+ serverPullingTimeoutId = null,
+ pullingActive = true;
+
+ function onSessionData(sessionData) {
+ var i,
+ isNew = ! cachedSessionData.hasOwnProperty(sessionData.id);
+
+ // extend data with download url
+ sessionData.fileUrl = "/session/" + sessionData.id + "/last/" + sessionData.filename;
+ // cache
+ cachedSessionData[sessionData.id] = sessionData;
+ runtime.log("get session data for:"+sessionData.title+", is new:"+isNew);
+
+ for (i = 0; i < subscribers.length; i += 1) {
+ if (isNew) {
+ subscribers[i].onCreated(sessionData);
+ } else {
+ subscribers[i].onUpdated(sessionData);
+ }
+ }
+ }
+
+ function onSessionRemoved(sessionId) {
+ var i;
+
+ if (cachedSessionData.hasOwnProperty(sessionId)) {
+ delete cachedSessionData[sessionId];
+
+ for (i = 0; i < subscribers.length; i += 1) {
+ subscribers[i].onRemoved(sessionId);
+ }
+ }
+ }
+
+ function pullSessionList() {
+ serverPullingTimeoutId = null;
+
+ server.call({
+ command: "query_sessiondata_list"
+ }, function(responseData) {
+ var response = runtime.fromJson(responseData),
+ sessionList, i,
+ unupdatedSessions = {};
+
+ // stopped meanwhile? TODO: support for cancelling calls
+ if (!pullingActive) {
+ return;
+ }
+
+ runtime.log("query_sessiondata_list reply: " + responseData);
+
+ if (response.hasOwnProperty("sessiondata_list")) {
+ // collect known sessions
+ for (i in cachedSessionData) {
+ if (cachedSessionData.hasOwnProperty(i)) {
+ unupdatedSessions[i] = ""; // some dummy value, unused
+ }
+ }
+
+ // add/update with all delivered sessions
+ sessionList = response.sessiondata_list;
+ for (i = 0; i < sessionList.length; i++) {
+ if (unupdatedSessions.hasOwnProperty(sessionList[i].id)) {
+ delete unupdatedSessions[sessionList[i].id];
+ }
+ onSessionData(sessionList[i]);
+ }
+
+ // remove unupdated sessions
+ for (i in unupdatedSessions) {
+ if (unupdatedSessions.hasOwnProperty(i)) {
+ onSessionRemoved(i);
+ }
+ }
+
+ // next update in 5 secs
+ serverPullingTimeoutId = runtime.getWindow().setTimeout(pullSessionList, 5000);
+ } else {
+ runtime.log("Meh, sessionlist data broken: " + responseData);
+ }
++ }, function() {
++ // ignore error for now
+ });
+ }
+
+ this.getSessions = function (subscriber) {
+ var i,
+ sessionList = [];
+
+ if (subscriber) {
+ subscribers.push(subscriber);
+ }
+
+ for (i in cachedSessionData) {
+ if (cachedSessionData.hasOwnProperty(i)) {
+ sessionList.push(cachedSessionData[i]);
+ }
+ }
+
+ return sessionList;
+ };
+
+ this.unsubscribe = function (subscriber) {
+ var i;
+
+ for (i=0; i<subscribers.length; i+=1) {
+ if (subscribers[i] === subscriber) {
+ break;
+ }
+ }
+
+ runtime.assert((i < subscribers.length),
+ "tried to unsubscribe when not subscribed.");
+
+ subscribers.splice(i,1);
+ };
+
+ this.setUpdatesEnabled = function (enabled) {
+ if (pullingActive === enabled) {
+ return;
+ }
+
+ pullingActive = enabled;
+ if (pullingActive) {
+ pullSessionList();
+ } else {
+ // cancel any running pulling timeout
+ if (serverPullingTimeoutId !== null) {
+ runtime.clearTimeout(serverPullingTimeoutId);
+ serverPullingTimeoutId = null;
+ }
+ }
+ };
+
+ function init() {
+ pullSessionList();
+ }
+
+ init();
+ };
+});
diff --cc apps/documents/js/3rdparty/webodf/editor/widgets/paragraphStyles.js
index e7a9364,0000000..57acaac
mode 100644,000000..100644
--- a/apps/documents/js/3rdparty/webodf/editor/widgets/paragraphStyles.js
+++ b/apps/documents/js/3rdparty/webodf/editor/widgets/paragraphStyles.js
@@@ -1,200 -1,0 +1,200 @@@
+/**
+ * @license
+ * Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+ *
+ * @licstart
+ * The JavaScript code in this page is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Affero General Public License
+ * (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version. The code is distributed
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this code. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As additional permission under GNU AGPL version 3 section 7, you
+ * may distribute non-source (e.g., minimized or compacted) forms of
+ * that code without the copy of the GNU GPL normally required by
+ * section 4, provided you include this license notice and a URL
+ * through which recipients can access the Corresponding Source.
+ *
+ * As a special exception to the AGPL, any HTML file which merely makes function
+ * calls to this code, and for that purpose includes it by reference shall be
+ * deemed a separate work for copyright law purposes. In addition, the copyright
+ * holders of this code give you permission to combine this code with free
+ * software libraries that are released under the GNU LGPL. You may copy and
+ * distribute such a system following the terms of the GNU AGPL for this code
+ * and the LGPL for the libraries. If you modify this code, you may extend this
+ * exception to your version of the code, but you are not obligated to do so.
+ * If you do not wish to do so, delete this exception statement from your
+ * version.
+ *
+ * This license applies to this entire compilation.
+ * @licend
+ * @source: http://www.webodf.org/
+ * @source: https://github.com/kogmbh/WebODF/
+ */
+
+/*global define,require */
+
+define("webodf/editor/widgets/paragraphStyles",
+ ["webodf/editor/EditorSession"],
+
+ function (EditorSession) {
+ "use strict";
+ /**
+ * @constructor
+ */
+ var ParagraphStyles = function (callback) {
+ var self = this,
+ editorSession,
+ select,
+ defaultStyleUIId = ":default";
+
+ this.widget = function () {
+ return select;
+ };
+
+ /*
+ * In this widget, we name the default style
+ * (which is referred to as "" in webodf) as
+ * ":default". The ":" is disallowed in an NCName, so this
+ * avoids clashes with other styles.
+ */
+
+ this.value = function () {
+ var value = select.get('value');
+ if (value === defaultStyleUIId) {
+ value = "";
+ }
+ return value;
+ };
+
+ this.setValue = function (value) {
+ if (value === "") {
+ value = defaultStyleUIId;
+ }
- select.set('value', value);
++ select.set('value', value, false);
+ };
+
+ // events
+ this.onAdd = null;
+ this.onRemove = null;
+ this.onChange = function () {};
+
+ function populateStyles() {
+ var i, selectionList, availableStyles;
+
+ if (! select) {
+ return;
+ }
+
+ // Populate the Default Style always
+ selectionList = [{
+ label: runtime.tr("Default Style"),
+ value: defaultStyleUIId
+ }];
+ availableStyles = editorSession ? editorSession.getAvailableParagraphStyles() : [];
+
+ for (i = 0; i < availableStyles.length; i += 1) {
+ selectionList.push({
+ label: availableStyles[i].displayName,
+ value: availableStyles[i].name
+ });
+ }
+
+ select.removeOption(select.getOptions());
+ select.addOption(selectionList);
+ }
+
+ function addStyle(styleInfo) {
+ var stylens = "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
+ newStyleElement;
+
+ if (styleInfo.family !== 'paragraph') {
+ return;
+ }
+
+ newStyleElement = editorSession.getParagraphStyleElement(styleInfo.name);
+ if (select) {
+ select.addOption({
+ value: styleInfo.name,
+ label: newStyleElement.getAttributeNS(stylens, 'display-name')
+ });
+ }
+
+ if (self.onAdd) {
+ self.onAdd(styleInfo.name);
+ }
+ }
+
+ function removeStyle(styleInfo) {
+ if (styleInfo.family !== 'paragraph') {
+ return;
+ }
+
+ if (select) {
+ select.removeOption(styleInfo.name);
+ }
+
+ if (self.onRemove) {
+ self.onRemove(styleInfo.name);
+ }
+ }
+
+ function init(cb) {
+ require(["dijit/form/Select"], function (Select) {
+ select = new Select({
+ name: 'ParagraphStyles',
+ maxHeight: 200,
+ style: {
+ width: '100px'
+ }
+ });
+
+ populateStyles();
+
+ // Call ParagraphStyles's onChange handler every time
+ // the select's onchange is called, and pass the value
+ // as reported by ParagraphStyles.value(), because we do not
+ // want to expose the internal naming like ":default" outside this
+ // class.
+ select.onChange = function () {
+ self.onChange(self.value());
+ };
+
+ return cb();
+ });
+ }
+
+ function handleCursorMoved(cursor) {
+ var disabled = cursor.getSelectionType() === ops.OdtCursor.RegionSelection;
+ if (select) {
+ select.setAttribute('disabled', disabled);
+ }
+ }
+
+ this.setEditorSession = function(session) {
+ if (editorSession) {
+ editorSession.unsubscribe(EditorSession.signalCommonStyleCreated, addStyle);
+ editorSession.unsubscribe(EditorSession.signalCommonStyleDeleted, removeStyle);
+ editorSession.unsubscribe(EditorSession.signalCursorMoved, handleCursorMoved);
+ }
+ editorSession = session;
+ if (editorSession) {
+ editorSession.subscribe(EditorSession.signalCommonStyleCreated, addStyle);
+ editorSession.subscribe(EditorSession.signalCommonStyleDeleted, removeStyle);
+ editorSession.subscribe(EditorSession.signalCursorMoved, handleCursorMoved);
+ populateStyles();
+ }
+ };
+
+ // init
+ init(function () {
+ return callback(self);
+ });
+ };
+
+ return ParagraphStyles;
+});
diff --cc apps/documents/js/3rdparty/webodf/webodf-debug.js
index 52a5ea3,0000000..0781352
mode 100644,000000..100644
--- a/apps/documents/js/3rdparty/webodf/webodf-debug.js
+++ b/apps/documents/js/3rdparty/webodf/webodf-debug.js
@@@ -1,18005 -1,0 +1,18164 @@@
- /*
-
-
- Copyright (C) 2012 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- var core = {};
- var gui = {};
- var xmldom = {};
- var odf = {};
- var ops = {};
++var webodf_version = "0.4.2-1556-gf8a94ee";
+function Runtime() {
+}
+Runtime.prototype.getVariable = function(name) {
+};
+Runtime.prototype.toJson = function(anything) {
+};
+Runtime.prototype.fromJson = function(jsonstr) {
+};
+Runtime.prototype.byteArrayFromString = function(string, encoding) {
+};
+Runtime.prototype.byteArrayToString = function(bytearray, encoding) {
+};
+Runtime.prototype.read = function(path, offset, length, callback) {
+};
+Runtime.prototype.readFile = function(path, encoding, callback) {
+};
+Runtime.prototype.readFileSync = function(path, encoding) {
+};
+Runtime.prototype.loadXML = function(path, callback) {
+};
+Runtime.prototype.writeFile = function(path, data, callback) {
+};
+Runtime.prototype.isFile = function(path, callback) {
+};
+Runtime.prototype.getFileSize = function(path, callback) {
+};
+Runtime.prototype.deleteFile = function(path, callback) {
+};
+Runtime.prototype.log = function(msgOrCategory, msg) {
+};
+Runtime.prototype.setTimeout = function(callback, milliseconds) {
+};
+Runtime.prototype.clearTimeout = function(timeoutID) {
+};
+Runtime.prototype.libraryPaths = function() {
+};
++Runtime.prototype.currentDirectory = function() {
++};
++Runtime.prototype.setCurrentDirectory = function(dir) {
++};
+Runtime.prototype.type = function() {
+};
+Runtime.prototype.getDOMImplementation = function() {
+};
+Runtime.prototype.parseXML = function(xml) {
+};
++Runtime.prototype.exit = function(exitCode) {
++};
+Runtime.prototype.getWindow = function() {
+};
+Runtime.prototype.assert = function(condition, message, callback) {
+};
- var IS_COMPILED_CODE = false;
++var IS_COMPILED_CODE = true;
+Runtime.byteArrayToString = function(bytearray, encoding) {
+ function byteArrayToString(bytearray) {
+ var s = "", i, l = bytearray.length;
+ for(i = 0;i < l;i += 1) {
+ s += String.fromCharCode(bytearray[i] & 255)
+ }
+ return s
+ }
+ function utf8ByteArrayToString(bytearray) {
+ var s = "", i, l = bytearray.length, chars = [], c0, c1, c2, c3, codepoint;
+ for(i = 0;i < l;i += 1) {
+ c0 = (bytearray[i]);
+ if(c0 < 128) {
+ chars.push(c0)
+ }else {
+ i += 1;
+ c1 = (bytearray[i]);
+ if(c0 >= 194 && c0 < 224) {
+ chars.push((c0 & 31) << 6 | c1 & 63)
+ }else {
+ i += 1;
+ c2 = (bytearray[i]);
+ if(c0 >= 224 && c0 < 240) {
+ chars.push((c0 & 15) << 12 | (c1 & 63) << 6 | c2 & 63)
+ }else {
+ i += 1;
+ c3 = (bytearray[i]);
+ if(c0 >= 240 && c0 < 245) {
+ codepoint = (c0 & 7) << 18 | (c1 & 63) << 12 | (c2 & 63) << 6 | c3 & 63;
+ codepoint -= 65536;
+ chars.push((codepoint >> 10) + 55296, (codepoint & 1023) + 56320)
+ }
+ }
+ }
+ }
+ if(chars.length === 1E3) {
+ s += String.fromCharCode.apply(null, chars);
+ chars.length = 0
+ }
+ }
+ return s + String.fromCharCode.apply(null, chars)
+ }
+ var result;
+ if(encoding === "utf8") {
+ result = utf8ByteArrayToString(bytearray)
+ }else {
+ if(encoding !== "binary") {
+ this.log("Unsupported encoding: " + encoding)
+ }
+ result = byteArrayToString(bytearray)
+ }
+ return result
+};
+Runtime.getVariable = function(name) {
+ try {
+ return eval(name)
+ }catch(e) {
+ return undefined
+ }
+};
+Runtime.toJson = function(anything) {
+ return JSON.stringify(anything)
+};
+Runtime.fromJson = function(jsonstr) {
+ return JSON.parse(jsonstr)
+};
+Runtime.getFunctionName = function getFunctionName(f) {
+ var m;
+ if(f.name === undefined) {
+ m = (new RegExp("function\\s+(\\w+)")).exec(f);
+ return m && m[1]
+ }
+ return f.name
+};
+function BrowserRuntime(logoutput) {
+ var self = this, cache = {};
+ function utf8ByteArrayFromString(string) {
+ var l = string.length, bytearray, i, n, j = 0;
+ for(i = 0;i < l;i += 1) {
+ n = string.charCodeAt(i);
+ j += 1 + (n > 128) + (n > 2048)
+ }
+ bytearray = new Uint8Array(new ArrayBuffer(j));
+ j = 0;
+ for(i = 0;i < l;i += 1) {
+ n = string.charCodeAt(i);
+ if(n < 128) {
+ bytearray[j] = n;
+ j += 1
+ }else {
+ if(n < 2048) {
+ bytearray[j] = 192 | n >>> 6;
+ bytearray[j + 1] = 128 | n & 63;
+ j += 2
+ }else {
+ bytearray[j] = 224 | n >>> 12 & 15;
+ bytearray[j + 1] = 128 | n >>> 6 & 63;
+ bytearray[j + 2] = 128 | n & 63;
+ j += 3
+ }
+ }
+ }
+ return bytearray
+ }
+ function byteArrayFromString(string) {
+ var l = string.length, a = new Uint8Array(new ArrayBuffer(l)), i;
+ for(i = 0;i < l;i += 1) {
+ a[i] = string.charCodeAt(i) & 255
+ }
+ return a
+ }
+ this.byteArrayFromString = function(string, encoding) {
+ var result;
+ if(encoding === "utf8") {
+ result = utf8ByteArrayFromString(string)
+ }else {
+ if(encoding !== "binary") {
+ self.log("unknown encoding: " + encoding)
+ }
+ result = byteArrayFromString(string)
+ }
+ return result
+ };
+ this.byteArrayToString = Runtime.byteArrayToString;
+ this.getVariable = Runtime.getVariable;
+ this.fromJson = Runtime.fromJson;
+ this.toJson = Runtime.toJson;
+ function log(msgOrCategory, msg) {
+ var node, doc, category;
+ if(msg !== undefined) {
+ category = msgOrCategory
+ }else {
+ msg = msgOrCategory
+ }
+ if(logoutput) {
+ doc = logoutput.ownerDocument;
+ if(category) {
+ node = doc.createElement("span");
+ node.className = category;
+ node.appendChild(doc.createTextNode(category));
+ logoutput.appendChild(node);
+ logoutput.appendChild(doc.createTextNode(" "))
+ }
+ node = doc.createElement("span");
+ if(msg.length > 0 && msg[0] === "<") {
+ node.innerHTML = msg
+ }else {
+ node.appendChild(doc.createTextNode(msg))
+ }
+ logoutput.appendChild(node);
+ logoutput.appendChild(doc.createElement("br"))
+ }else {
+ if(console) {
+ console.log(msg)
+ }
+ }
+ if(category === "alert") {
+ alert(msg)
+ }
+ }
+ function assert(condition, message, callback) {
+ if(!condition) {
+ log("alert", "ASSERTION FAILED:\n" + message);
+ if(callback) {
+ callback()
+ }
+ throw message;
+ }
+ }
+ function arrayToUint8Array(buffer) {
+ var l = buffer.length, i, a = new Uint8Array(new ArrayBuffer(l));
+ for(i = 0;i < l;i += 1) {
+ a[i] = buffer[i]
+ }
+ return a
+ }
+ function handleXHRResult(path, encoding, xhr) {
+ var data, r, d, a;
+ if(xhr.status === 0 && !xhr.responseText) {
+ r = {err:"File " + path + " is empty.", data:null}
+ }else {
+ if(xhr.status === 200 || xhr.status === 0) {
+ if(xhr.response && typeof xhr.response !== "string") {
+ if(encoding === "binary") {
+ d = (xhr.response);
+ data = new Uint8Array(d)
+ }else {
+ data = String(xhr.response)
+ }
+ }else {
+ if(encoding === "binary") {
+ if(xhr.responseBody !== null && String(typeof VBArray) !== "undefined") {
+ a = (new VBArray(xhr.responseBody)).toArray();
+ data = arrayToUint8Array(a)
+ }else {
+ data = self.byteArrayFromString(xhr.responseText, "binary")
+ }
+ }else {
+ data = xhr.responseText
+ }
+ }
+ cache[path] = data;
+ r = {err:null, data:data}
+ }else {
+ r = {err:xhr.responseText || xhr.statusText, data:null}
+ }
+ }
+ return r
+ }
+ function createXHR(path, encoding, async) {
+ var xhr = new XMLHttpRequest;
+ xhr.open("GET", path, async);
+ if(xhr.overrideMimeType) {
+ if(encoding !== "binary") {
+ xhr.overrideMimeType("text/plain; charset=" + encoding)
+ }else {
+ xhr.overrideMimeType("text/plain; charset=x-user-defined")
+ }
+ }
+ return xhr
+ }
+ function readFile(path, encoding, callback) {
+ if(cache.hasOwnProperty(path)) {
+ callback(null, cache[path]);
+ return
+ }
+ var xhr = createXHR(path, encoding, true);
+ function handleResult() {
+ var r;
+ if(xhr.readyState === 4) {
+ r = handleXHRResult(path, encoding, xhr);
+ callback(r.err, r.data)
+ }
+ }
+ xhr.onreadystatechange = handleResult;
+ try {
+ xhr.send(null)
+ }catch(e) {
+ callback(e.message, null)
+ }
+ }
+ function read(path, offset, length, callback) {
+ readFile(path, "binary", function(err, result) {
+ var r = null;
+ if(result) {
+ if(typeof result === "string") {
+ throw"This should not happen.";
+ }
+ r = (result.subarray(offset, offset + length))
+ }
+ callback(err, r)
+ })
+ }
+ function readFileSync(path, encoding) {
+ var xhr = createXHR(path, encoding, false), r;
+ try {
+ xhr.send(null);
+ r = handleXHRResult(path, encoding, xhr);
+ if(r.err) {
+ throw r.err;
+ }
+ if(r.data === null) {
+ throw"No data read from " + path + ".";
+ }
+ }catch(e) {
+ throw e;
+ }
+ return r.data
+ }
+ function writeFile(path, data, callback) {
+ cache[path] = data;
+ var xhr = new XMLHttpRequest, d;
+ function handleResult() {
+ if(xhr.readyState === 4) {
+ if(xhr.status === 0 && !xhr.responseText) {
+ callback("File " + path + " is empty.")
+ }else {
+ if(xhr.status >= 200 && xhr.status < 300 || xhr.status === 0) {
+ callback(null)
+ }else {
+ callback("Status " + String(xhr.status) + ": " + xhr.responseText || xhr.statusText)
+ }
+ }
+ }
+ }
+ xhr.open("PUT", path, true);
+ xhr.onreadystatechange = handleResult;
+ if(data.buffer && !xhr.sendAsBinary) {
+ d = data.buffer
+ }else {
+ d = self.byteArrayToString(data, "binary")
+ }
+ try {
+ if(xhr.sendAsBinary) {
+ xhr.sendAsBinary(d)
+ }else {
+ xhr.send(d)
+ }
+ }catch(e) {
+ self.log("HUH? " + e + " " + data);
+ callback(e.message)
+ }
+ }
+ function deleteFile(path, callback) {
+ delete cache[path];
+ var xhr = new XMLHttpRequest;
+ xhr.open("DELETE", path, true);
+ xhr.onreadystatechange = function() {
+ if(xhr.readyState === 4) {
+ if(xhr.status < 200 && xhr.status >= 300) {
+ callback(xhr.responseText)
+ }else {
+ callback(null)
+ }
+ }
+ };
+ xhr.send(null)
+ }
+ function loadXML(path, callback) {
+ var xhr = new XMLHttpRequest;
+ function handleResult() {
+ if(xhr.readyState === 4) {
+ if(xhr.status === 0 && !xhr.responseText) {
+ callback("File " + path + " is empty.", null)
+ }else {
+ if(xhr.status === 200 || xhr.status === 0) {
+ callback(null, xhr.responseXML)
+ }else {
+ callback(xhr.responseText, null)
+ }
+ }
+ }
+ }
+ xhr.open("GET", path, true);
+ if(xhr.overrideMimeType) {
+ xhr.overrideMimeType("text/xml")
+ }
+ xhr.onreadystatechange = handleResult;
+ try {
+ xhr.send(null)
+ }catch(e) {
+ callback(e.message, null)
+ }
+ }
+ function isFile(path, callback) {
+ self.getFileSize(path, function(size) {
+ callback(size !== -1)
+ })
+ }
+ function getFileSize(path, callback) {
+ if(cache.hasOwnProperty(path) && typeof cache[path] !== "string") {
+ callback(cache[path].length);
+ return
+ }
+ var xhr = new XMLHttpRequest;
+ xhr.open("HEAD", path, true);
+ xhr.onreadystatechange = function() {
+ if(xhr.readyState !== 4) {
+ return
+ }
+ var cl = xhr.getResponseHeader("Content-Length");
+ if(cl) {
+ callback(parseInt(cl, 10))
+ }else {
+ readFile(path, "binary", function(err, data) {
+ if(!err) {
+ callback(data.length)
+ }else {
+ callback(-1)
+ }
+ })
+ }
+ };
+ xhr.send(null)
+ }
+ this.readFile = readFile;
+ this.read = read;
+ this.readFileSync = readFileSync;
+ this.writeFile = writeFile;
+ this.deleteFile = deleteFile;
+ this.loadXML = loadXML;
+ this.isFile = isFile;
+ this.getFileSize = getFileSize;
+ this.log = log;
+ this.assert = assert;
+ this.setTimeout = function(f, msec) {
+ return setTimeout(function() {
+ f()
+ }, msec)
+ };
+ this.clearTimeout = function(timeoutID) {
+ clearTimeout(timeoutID)
+ };
+ this.libraryPaths = function() {
+ return["lib"]
+ };
+ this.setCurrentDirectory = function() {
+ };
++ this.currentDirectory = function() {
++ return""
++ };
+ this.type = function() {
+ return"BrowserRuntime"
+ };
+ this.getDOMImplementation = function() {
+ return window.document.implementation
+ };
+ this.parseXML = function(xml) {
+ var parser = new DOMParser;
+ return parser.parseFromString(xml, "text/xml")
+ };
+ this.exit = function(exitCode) {
+ log("Calling exit with code " + String(exitCode) + ", but exit() is not implemented.")
+ };
+ this.getWindow = function() {
+ return window
+ }
+}
+function NodeJSRuntime() {
+ var self = this, fs = require("fs"), pathmod = require("path"), currentDirectory = "", parser, domImplementation;
+ function bufferToUint8Array(buffer) {
+ var l = buffer.length, i, a = new Uint8Array(new ArrayBuffer(l));
+ for(i = 0;i < l;i += 1) {
+ a[i] = buffer[i]
+ }
+ return a
+ }
+ this.byteArrayFromString = function(string, encoding) {
+ var buf = new Buffer(string, encoding), i, l = buf.length, a = new Uint8Array(new ArrayBuffer(l));
+ for(i = 0;i < l;i += 1) {
+ a[i] = buf[i]
+ }
+ return a
+ };
+ this.byteArrayToString = Runtime.byteArrayToString;
+ this.getVariable = Runtime.getVariable;
+ this.fromJson = Runtime.fromJson;
+ this.toJson = Runtime.toJson;
+ function isFile(path, callback) {
+ path = pathmod.resolve(currentDirectory, path);
+ fs.stat(path, function(err, stats) {
+ callback(!err && stats.isFile())
+ })
+ }
+ function readFile(path, encoding, callback) {
+ function convert(err, data) {
+ if(err) {
+ return callback(err, null)
+ }
+ if(!data) {
+ return callback("No data for " + path + ".", null)
+ }
+ var d;
+ if(typeof data === "string") {
+ d = (data);
+ return callback(err, d)
+ }
+ d = (data);
+ callback(err, bufferToUint8Array(d))
+ }
+ path = pathmod.resolve(currentDirectory, path);
+ if(encoding !== "binary") {
+ fs.readFile(path, encoding, convert)
+ }else {
+ fs.readFile(path, null, convert)
+ }
+ }
+ this.readFile = readFile;
+ function loadXML(path, callback) {
+ readFile(path, "utf-8", function(err, data) {
+ if(err) {
+ return callback(err, null)
+ }
+ if(!data) {
+ return callback("No data for " + path + ".", null)
+ }
+ var d = (data);
+ callback(null, self.parseXML(d))
+ })
+ }
+ this.loadXML = loadXML;
+ this.writeFile = function(path, data, callback) {
+ var buf = new Buffer(data);
+ path = pathmod.resolve(currentDirectory, path);
+ fs.writeFile(path, buf, "binary", function(err) {
+ callback(err || null)
+ })
+ };
+ this.deleteFile = function(path, callback) {
+ path = pathmod.resolve(currentDirectory, path);
+ fs.unlink(path, callback)
+ };
+ this.read = function(path, offset, length, callback) {
+ path = pathmod.resolve(currentDirectory, path);
+ fs.open(path, "r+", 666, function(err, fd) {
+ if(err) {
+ callback(err, null);
+ return
+ }
+ var buffer = new Buffer(length);
+ fs.read(fd, buffer, 0, length, offset, function(err) {
+ fs.close(fd);
+ callback(err, bufferToUint8Array(buffer))
+ })
+ })
+ };
+ this.readFileSync = function(path, encoding) {
- var enc = encoding === "binary" ? null : encoding, r = fs.readFileSync(path, enc), s;
++ var s, enc = encoding === "binary" ? null : encoding, r = fs.readFileSync(path, enc);
+ if(r === null) {
+ throw"File " + path + " could not be read.";
+ }
+ if(encoding === "binary") {
+ s = (r);
+ s = bufferToUint8Array(s)
+ }else {
+ s = (r)
+ }
+ return s
+ };
+ this.isFile = isFile;
+ this.getFileSize = function(path, callback) {
+ path = pathmod.resolve(currentDirectory, path);
+ fs.stat(path, function(err, stats) {
+ if(err) {
+ callback(-1)
+ }else {
+ callback(stats.size)
+ }
+ })
+ };
+ function log(msgOrCategory, msg) {
+ var category;
+ if(msg !== undefined) {
+ category = msgOrCategory
+ }else {
+ msg = msgOrCategory
+ }
+ if(category === "alert") {
+ process.stderr.write("\n!!!!! ALERT !!!!!" + "\n")
+ }
+ process.stderr.write(msg + "\n");
+ if(category === "alert") {
+ process.stderr.write("!!!!! ALERT !!!!!" + "\n")
+ }
+ }
+ this.log = log;
+ function assert(condition, message, callback) {
+ if(!condition) {
+ process.stderr.write("ASSERTION FAILED: " + message);
+ if(callback) {
+ callback()
+ }
+ }
+ }
+ this.assert = assert;
+ this.setTimeout = function(f, msec) {
+ return setTimeout(function() {
+ f()
+ }, msec)
+ };
+ this.clearTimeout = function(timeoutID) {
+ clearTimeout(timeoutID)
+ };
+ this.libraryPaths = function() {
+ return[__dirname]
+ };
+ this.setCurrentDirectory = function(dir) {
+ currentDirectory = dir
+ };
+ this.currentDirectory = function() {
+ return currentDirectory
+ };
+ this.type = function() {
+ return"NodeJSRuntime"
+ };
+ this.getDOMImplementation = function() {
+ return domImplementation
+ };
+ this.parseXML = function(xml) {
+ return parser.parseFromString(xml, "text/xml")
+ };
+ this.exit = process.exit;
+ this.getWindow = function() {
+ return null
+ };
+ function init() {
+ var DOMParser = require("xmldom").DOMParser;
+ parser = new DOMParser;
+ domImplementation = self.parseXML("<a/>").implementation
+ }
+ init()
+}
+function RhinoRuntime() {
- var self = this, dom = Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance(), builder, entityresolver, currentDirectory = "";
++ var self = this, Packages = {}, dom = Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance(), builder, entityresolver, currentDirectory = "";
+ dom.setValidating(false);
+ dom.setNamespaceAware(true);
+ dom.setExpandEntityReferences(false);
+ dom.setSchema(null);
+ entityresolver = Packages.org.xml.sax.EntityResolver({resolveEntity:function(publicId, systemId) {
+ var file;
+ function open(path) {
+ var reader = new Packages.java.io.FileReader(path), source = new Packages.org.xml.sax.InputSource(reader);
+ return source
+ }
+ file = systemId;
+ return open(file)
+ }});
+ builder = dom.newDocumentBuilder();
+ builder.setEntityResolver(entityresolver);
+ this.byteArrayFromString = function(string, encoding) {
- var a = [], i, l = string.length;
++ var i, l = string.length, a = new Uint8Array(new ArrayBuffer(l));
+ for(i = 0;i < l;i += 1) {
+ a[i] = string.charCodeAt(i) & 255
+ }
+ return a
+ };
+ this.byteArrayToString = Runtime.byteArrayToString;
+ this.getVariable = Runtime.getVariable;
+ this.fromJson = Runtime.fromJson;
+ this.toJson = Runtime.toJson;
+ function loadXML(path, callback) {
- var file = new Packages.java.io.File(path), xmlDocument;
++ var file = new Packages.java.io.File(path), xmlDocument = null;
+ try {
+ xmlDocument = builder.parse(file)
+ }catch(err) {
+ print(err);
- callback(err);
- return
++ return callback(err, null)
+ }
+ callback(null, xmlDocument)
+ }
+ function runtimeReadFile(path, encoding, callback) {
+ if(currentDirectory) {
+ path = currentDirectory + "/" + path
+ }
+ var file = new Packages.java.io.File(path), data, rhinoencoding = encoding === "binary" ? "latin1" : encoding;
+ if(!file.isFile()) {
- callback(path + " is not a file.")
++ callback(path + " is not a file.", null)
+ }else {
+ data = readFile(path, rhinoencoding);
- if(encoding === "binary") {
++ if(data && encoding === "binary") {
+ data = self.byteArrayFromString(data, "binary")
+ }
+ callback(null, data)
+ }
+ }
+ function runtimeReadFileSync(path, encoding) {
+ var file = new Packages.java.io.File(path);
+ if(!file.isFile()) {
+ return null
+ }
+ if(encoding === "binary") {
+ encoding = "latin1"
+ }
+ return readFile(path, encoding)
+ }
+ function isFile(path, callback) {
+ if(currentDirectory) {
+ path = currentDirectory + "/" + path
+ }
+ var file = new Packages.java.io.File(path);
+ callback(file.isFile())
+ }
+ this.loadXML = loadXML;
+ this.readFile = runtimeReadFile;
+ this.writeFile = function(path, data, callback) {
+ if(currentDirectory) {
+ path = currentDirectory + "/" + path
+ }
+ var out = new Packages.java.io.FileOutputStream(path), i, l = data.length;
+ for(i = 0;i < l;i += 1) {
+ out.write(data[i])
+ }
+ out.close();
+ callback(null)
+ };
+ this.deleteFile = function(path, callback) {
+ if(currentDirectory) {
+ path = currentDirectory + "/" + path
+ }
- var file = new Packages.java.io.File(path);
- if(file["delete"]()) {
++ var file = new Packages.java.io.File(path), otherPath = path + Math.random(), other = new Packages.java.io.File(otherPath);
++ if(file.rename(other)) {
++ other.deleteOnExit();
+ callback(null)
+ }else {
+ callback("Could not delete " + path)
+ }
+ };
+ this.read = function(path, offset, length, callback) {
+ if(currentDirectory) {
+ path = currentDirectory + "/" + path
+ }
+ var data = runtimeReadFileSync(path, "binary");
+ if(data) {
+ callback(null, this.byteArrayFromString(data.substring(offset, offset + length), "binary"))
+ }else {
- callback("Cannot read " + path)
++ callback("Cannot read " + path, null)
+ }
+ };
+ this.readFileSync = function(path, encoding) {
+ if(!encoding) {
+ return""
+ }
+ var s = readFile(path, encoding);
+ if(s === null) {
+ throw"File could not be read.";
+ }
+ return s
+ };
+ this.isFile = isFile;
+ this.getFileSize = function(path, callback) {
+ if(currentDirectory) {
+ path = currentDirectory + "/" + path
+ }
+ var file = new Packages.java.io.File(path);
+ callback(file.length())
+ };
+ function log(msgOrCategory, msg) {
+ var category;
+ if(msg !== undefined) {
+ category = msgOrCategory
+ }else {
+ msg = msgOrCategory
+ }
+ if(category === "alert") {
+ print("\n!!!!! ALERT !!!!!")
+ }
+ print(msg);
+ if(category === "alert") {
+ print("!!!!! ALERT !!!!!")
+ }
+ }
+ this.log = log;
+ function assert(condition, message, callback) {
+ if(!condition) {
+ log("alert", "ASSERTION FAILED: " + message);
+ if(callback) {
+ callback()
+ }
+ }
+ }
+ this.assert = assert;
+ this.setTimeout = function(f) {
+ f();
+ return 0
+ };
+ this.clearTimeout = function() {
+ };
+ this.libraryPaths = function() {
+ return["lib"]
+ };
+ this.setCurrentDirectory = function(dir) {
+ currentDirectory = dir
+ };
+ this.currentDirectory = function() {
+ return currentDirectory
+ };
+ this.type = function() {
+ return"RhinoRuntime"
+ };
+ this.getDOMImplementation = function() {
+ return builder.getDOMImplementation()
+ };
+ this.parseXML = function(xml) {
- return builder.parse(xml)
++ var reader = new Packages.java.io.StringReader(xml), source = new Packages.org.xml.sax.InputSource(reader);
++ return builder.parse(source)
+ };
+ this.exit = quit;
+ this.getWindow = function() {
+ return null
+ }
+}
- var runtime = function() {
++Runtime.create = function create() {
+ var result;
+ if(String(typeof window) !== "undefined") {
+ result = new BrowserRuntime(window.document.getElementById("logoutput"))
+ }else {
+ if(String(typeof require) !== "undefined") {
+ result = new NodeJSRuntime
+ }else {
+ result = new RhinoRuntime
+ }
+ }
+ return result
- }();
++};
++var runtime = Runtime.create();
++var core = {};
++var gui = {};
++var xmldom = {};
++var odf = {};
++var ops = {};
+(function() {
- var cache = {}, dircontents = {};
- function getOrDefinePackage(packageNameComponents) {
- var topname = packageNameComponents[0], i, pkg;
- pkg = eval("if (typeof " + topname + " === 'undefined') {" + "eval('" + topname + " = {};');}" + topname);
- for(i = 1;i < packageNameComponents.length - 1;i += 1) {
- if(!pkg.hasOwnProperty(packageNameComponents[i])) {
- pkg = pkg[packageNameComponents[i]] = {}
- }else {
- pkg = pkg[packageNameComponents[i]]
- }
- }
- return pkg[packageNameComponents[packageNameComponents.length - 1]]
- }
- runtime.loadClass = function(classpath) {
- if(IS_COMPILED_CODE) {
++ var dependencies = {}, loadedFiles = {};
++ function loadManifest(dir, manifests) {
++ var path = dir + "/manifest.json", content, list, manifest, m;
++ if(loadedFiles.hasOwnProperty(path)) {
+ return
+ }
- if(cache.hasOwnProperty(classpath)) {
++ loadedFiles[path] = 1;
++ try {
++ content = runtime.readFileSync(path, "utf-8")
++ }catch(e) {
++ console.log(String(e));
+ return
+ }
- var names = classpath.split("."), impl;
- impl = getOrDefinePackage(names);
- if(impl) {
- cache[classpath] = true;
- return
++ list = JSON.parse((content));
++ manifest = (list);
++ for(m in manifest) {
++ if(manifest.hasOwnProperty(m)) {
++ manifests[m] = {dir:dir, deps:manifest[m]}
++ }
+ }
- function getPathFromManifests(classpath) {
- var path = classpath.replace(/\./g, "/") + ".js", dirs = runtime.libraryPaths(), i, dir, code, codestr;
- if(runtime.currentDirectory) {
- dirs.push(runtime.currentDirectory())
++ }
++ function expandPathDependencies(path, manifests, allDeps) {
++ var d = manifests[path].deps, deps = {};
++ allDeps[path] = deps;
++ d.forEach(function(dp) {
++ deps[dp] = 1
++ });
++ d.forEach(function(dp) {
++ if(!allDeps[dp]) {
++ expandPathDependencies(dp, manifests, allDeps)
+ }
- for(i = 0;i < dirs.length;i += 1) {
- dir = dirs[i];
- if(!dircontents.hasOwnProperty(dir)) {
- try {
- code = runtime.readFileSync(dirs[i] + "/manifest.js", "utf8");
- if(code && code.length) {
- codestr = (code);
- dircontents[dir] = eval(codestr)
- }else {
- dircontents[dir] = null
- }
- }catch(e1) {
- dircontents[dir] = null;
- runtime.log("Cannot load manifest for " + dir + ".")
++ });
++ d.forEach(function(dp) {
++ Object.keys(allDeps[dp]).forEach(function(k) {
++ deps[k] = 1
++ })
++ })
++ }
++ function sortDeps(deps, allDeps) {
++ var i, sorted = [];
++ function add(path, stack) {
++ var j, d = allDeps[path];
++ if(sorted.indexOf(path) === -1 && stack.indexOf(path) === -1) {
++ stack.push(path);
++ for(j = 0;j < deps.length;j += 1) {
++ if(d[deps[j]]) {
++ add(deps[j], stack)
+ }
+ }
- code = null;
- dir = dircontents[dir];
- if(dir && (dir.indexOf && dir.indexOf(path) !== -1)) {
- return dirs[i] + "/" + path
- }
++ stack.pop();
++ sorted.push(path)
+ }
- return null
+ }
- function load(classpath) {
- var code, path;
- path = getPathFromManifests(classpath);
- if(!path) {
- throw classpath + " is not listed in any manifest.js.";
++ for(i = 0;i < deps.length;i += 1) {
++ add(deps[i], [])
++ }
++ return sorted
++ }
++ function expandDependencies(manifests) {
++ var path, deps, allDeps = {};
++ for(path in manifests) {
++ if(manifests.hasOwnProperty(path)) {
++ expandPathDependencies(path, manifests, allDeps)
+ }
- try {
- code = runtime.readFileSync(path, "utf8")
- }catch(e2) {
- runtime.log("Error loading " + classpath + " " + e2);
- throw e2;
++ }
++ for(path in manifests) {
++ if(manifests.hasOwnProperty(path)) {
++ deps = (Object.keys(allDeps[path]));
++ manifests[path].deps = sortDeps(deps, allDeps);
++ manifests[path].deps.push(path)
++ }
++ }
++ dependencies = manifests
++ }
++ function loadManifests() {
++ if(Object.keys(dependencies).length > 0) {
++ return
++ }
++ var paths = runtime.libraryPaths(), manifests = {}, i;
++ if(runtime.currentDirectory()) {
++ loadManifest(runtime.currentDirectory(), manifests)
++ }
++ for(i = 0;i < paths.length;i += 1) {
++ loadManifest(paths[i], manifests)
++ }
++ expandDependencies(manifests)
++ }
++ function classPath(classname) {
++ return classname.replace(".", "/") + ".js"
++ }
++ function getDependencies(classname) {
++ var classpath = classPath(classname), deps = [], d = dependencies[classpath].deps, i;
++ for(i = 0;i < d.length;i += 1) {
++ if(!loadedFiles.hasOwnProperty(d[i])) {
++ deps.push(d[i])
+ }
- if(code === undefined) {
- throw"Cannot load class " + classpath;
++ }
++ return deps
++ }
++ function evalArray(paths, contents) {
++ var i = 0;
++ while(i < paths.length && contents[i] !== undefined) {
++ if(contents[i] !== null) {
++ eval((contents[i]));
++ contents[i] = null
+ }
- code += "\n//# sourceURL=" + path;
- code += "\n//@ sourceURL=" + path;
- try {
- code = eval(classpath + " = eval(code);")
- }catch(e4) {
- runtime.log("Error loading " + classpath + " " + e4);
- throw e4;
++ i += 1
++ }
++ }
++ function loadFiles(paths) {
++ var contents = [], i, p, c, async = false;
++ contents.length = paths.length;
++ function addContent(pos, path, content) {
++ content += "\n//# sourceURL=" + path;
++ content += "\n//@ sourceURL=" + path;
++ contents[pos] = content
++ }
++ function loadFile(pos) {
++ var path = dependencies[paths[pos]].dir + "/" + paths[pos];
++ runtime.readFile(path, "utf8", function(err, content) {
++ if(err) {
++ throw err;
++ }
++ if(contents[pos] === undefined) {
++ addContent(pos, path, (content))
++ }
++ })
++ }
++ if(async) {
++ for(i = 0;i < paths.length;i += 1) {
++ loadedFiles[paths[i]] = 1;
++ loadFile(i)
++ }
++ }
++ for(i = paths.length - 1;i >= 0;i -= 1) {
++ loadedFiles[paths[i]] = 1;
++ if(contents[i] === undefined) {
++ p = paths[i];
++ p = dependencies[p].dir + "/" + p;
++ c = runtime.readFileSync(p, "utf-8");
++ addContent(i, p, (c))
+ }
- return code
+ }
- impl = load(classpath);
- if(!impl || Runtime.getFunctionName(impl) !== names[names.length - 1]) {
- runtime.log("Loaded code is not for " + names[names.length - 1]);
- throw"Loaded code is not for " + names[names.length - 1];
++ evalArray(paths, contents)
++ }
++ runtime.loadClass = function(classname) {
++ if(IS_COMPILED_CODE) {
++ return
++ }
++ var classpath = classPath(classname), paths;
++ if(loadedFiles.hasOwnProperty(classpath)) {
++ return
+ }
- cache[classpath] = true
++ loadManifests();
++ paths = getDependencies(classname);
++ loadFiles(paths)
+ }
+})();
+(function() {
- var translator = function() {
++ var translator = function(string) {
++ return string
+ };
+ function tr(original) {
+ var result = translator(original);
+ if(!result || String(typeof result) !== "string") {
+ return original
+ }
+ return result
+ }
+ runtime.getTranslator = function() {
+ return translator
+ };
+ runtime.setTranslator = function(translatorFunction) {
+ translator = translatorFunction
+ };
+ runtime.tr = tr
+})();
+(function(args) {
+ if(args) {
+ args = Array.prototype.slice.call((args))
+ }else {
+ args = []
+ }
+ function run(argv) {
+ if(!argv.length) {
+ return
+ }
+ var script = argv[0];
+ runtime.readFile(script, "utf8", function(err, code) {
+ var path = "", codestring = (code);
+ if(script.indexOf("/") !== -1) {
+ path = script.substring(0, script.indexOf("/"))
+ }
+ runtime.setCurrentDirectory(path);
+ function inner_run() {
+ var script, path, args, argv, result;
- result = eval(codestring);
++ result = (eval(codestring));
+ if(result) {
+ runtime.exit(result)
+ }
+ return
+ }
+ if(err) {
+ runtime.log(err);
+ runtime.exit(1)
+ }else {
+ if(codestring === null) {
+ runtime.log("No code found for " + script);
+ runtime.exit(1)
+ }else {
+ inner_run.apply(null, argv)
+ }
+ }
+ })
+ }
+ if(runtime.type() === "NodeJSRuntime") {
+ run(process.argv.slice(2))
+ }else {
+ if(runtime.type() === "RhinoRuntime") {
+ run(args)
+ }else {
+ run(args.slice(1))
+ }
+ }
+})(String(typeof arguments) !== "undefined" && arguments);
++core.Async = function Async() {
++ this.forEach = function(items, f, callback) {
++ var i, l = items.length, itemsDone = 0;
++ function end(err) {
++ if(itemsDone !== l) {
++ if(err) {
++ itemsDone = l;
++ callback(err)
++ }else {
++ itemsDone += 1;
++ if(itemsDone === l) {
++ callback(null)
++ }
++ }
++ }
++ }
++ for(i = 0;i < l;i += 1) {
++ f(items[i], end)
++ }
++ };
++ this.destroyAll = function(items, callback) {
++ function destroy(itemIndex, err) {
++ if(err) {
++ callback(err)
++ }else {
++ if(itemIndex < items.length) {
++ items[itemIndex](function(err) {
++ destroy(itemIndex + 1, err)
++ })
++ }else {
++ callback()
++ }
++ }
++ }
++ destroy(0, undefined)
++ }
++};
+function makeBase64() {
+ function makeB64tab(bin) {
+ var t = {}, i, l;
+ for(i = 0, l = bin.length;i < l;i += 1) {
+ t[bin.charAt(i)] = i
+ }
+ return t
+ }
+ var b64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", b64tab = makeB64tab(b64chars), convertUTF16StringToBase64, convertBase64ToUTF16String, window = runtime.getWindow(), btoa, atob;
+ function stringToArray(s) {
+ var i, l = s.length, a = new Uint8Array(new ArrayBuffer(l));
+ for(i = 0;i < l;i += 1) {
+ a[i] = s.charCodeAt(i) & 255
+ }
+ return a
+ }
+ function convertUTF8ArrayToBase64(bin) {
+ var n, b64 = "", i, l = bin.length - 2;
+ for(i = 0;i < l;i += 3) {
+ n = bin[i] << 16 | bin[i + 1] << 8 | bin[i + 2];
+ b64 += (b64chars[n >>> 18]);
+ b64 += (b64chars[n >>> 12 & 63]);
+ b64 += (b64chars[n >>> 6 & 63]);
+ b64 += (b64chars[n & 63])
+ }
+ if(i === l + 1) {
+ n = bin[i] << 4;
+ b64 += (b64chars[n >>> 6]);
+ b64 += (b64chars[n & 63]);
+ b64 += "=="
+ }else {
+ if(i === l) {
+ n = bin[i] << 10 | bin[i + 1] << 2;
+ b64 += (b64chars[n >>> 12]);
+ b64 += (b64chars[n >>> 6 & 63]);
+ b64 += (b64chars[n & 63]);
+ b64 += "="
+ }
+ }
+ return b64
+ }
+ function convertBase64ToUTF8Array(b64) {
+ b64 = b64.replace(/[^A-Za-z0-9+\/]+/g, "");
+ var l = b64.length, bin = new Uint8Array(new ArrayBuffer(3 * l)), padlen = b64.length % 4, o = 0, i, n;
+ for(i = 0;i < l;i += 4) {
+ n = (b64tab[b64.charAt(i)] || 0) << 18 | (b64tab[b64.charAt(i + 1)] || 0) << 12 | (b64tab[b64.charAt(i + 2)] || 0) << 6 | (b64tab[b64.charAt(i + 3)] || 0);
+ bin[o] = n >> 16;
+ bin[o + 1] = n >> 8 & 255;
+ bin[o + 2] = n & 255;
+ o += 3
+ }
+ l = 3 * l - [0, 0, 2, 1][padlen];
+ return bin.subarray(0, l)
+ }
+ function convertUTF16ArrayToUTF8Array(uni) {
+ var i, n, l = uni.length, o = 0, bin = new Uint8Array(new ArrayBuffer(3 * l));
+ for(i = 0;i < l;i += 1) {
+ n = (uni[i]);
+ if(n < 128) {
+ bin[o++] = n
+ }else {
+ if(n < 2048) {
+ bin[o++] = 192 | n >>> 6;
+ bin[o++] = 128 | n & 63
+ }else {
+ bin[o++] = 224 | n >>> 12 & 15;
+ bin[o++] = 128 | n >>> 6 & 63;
+ bin[o++] = 128 | n & 63
+ }
+ }
+ }
+ return bin.subarray(0, o)
+ }
+ function convertUTF8ArrayToUTF16Array(bin) {
+ var i, c0, c1, c2, l = bin.length, uni = new Uint8Array(new ArrayBuffer(l)), o = 0;
+ for(i = 0;i < l;i += 1) {
+ c0 = (bin[i]);
+ if(c0 < 128) {
+ uni[o++] = c0
+ }else {
+ i += 1;
+ c1 = (bin[i]);
+ if(c0 < 224) {
+ uni[o++] = (c0 & 31) << 6 | c1 & 63
+ }else {
+ i += 1;
+ c2 = (bin[i]);
+ uni[o++] = (c0 & 15) << 12 | (c1 & 63) << 6 | c2 & 63
+ }
+ }
+ }
+ return uni.subarray(0, o)
+ }
+ function convertUTF8StringToBase64(bin) {
+ return convertUTF8ArrayToBase64(stringToArray(bin))
+ }
+ function convertBase64ToUTF8String(b64) {
+ return String.fromCharCode.apply(String, convertBase64ToUTF8Array(b64))
+ }
+ function convertUTF8StringToUTF16Array(bin) {
+ return convertUTF8ArrayToUTF16Array(stringToArray(bin))
+ }
+ function convertUTF8ArrayToUTF16String(bin) {
+ var b = convertUTF8ArrayToUTF16Array(bin), r = "", i = 0, chunksize = 45E3;
+ while(i < b.length) {
+ r += String.fromCharCode.apply(String, b.subarray(i, i + chunksize));
+ i += chunksize
+ }
+ return r
+ }
+ function convertUTF8StringToUTF16String_internal(bin, i, end) {
+ var c0, c1, c2, j, str = "";
+ for(j = i;j < end;j += 1) {
+ c0 = bin.charCodeAt(j) & 255;
+ if(c0 < 128) {
+ str += String.fromCharCode(c0)
+ }else {
+ j += 1;
+ c1 = bin.charCodeAt(j) & 255;
+ if(c0 < 224) {
+ str += String.fromCharCode((c0 & 31) << 6 | c1 & 63)
+ }else {
+ j += 1;
+ c2 = bin.charCodeAt(j) & 255;
+ str += String.fromCharCode((c0 & 15) << 12 | (c1 & 63) << 6 | c2 & 63)
+ }
+ }
+ }
+ return str
+ }
+ function convertUTF8StringToUTF16String(bin, callback) {
+ var partsize = 1E5, str = "", pos = 0;
+ if(bin.length < partsize) {
+ callback(convertUTF8StringToUTF16String_internal(bin, 0, bin.length), true);
+ return
+ }
+ if(typeof bin !== "string") {
+ bin = bin.slice()
+ }
+ function f() {
+ var end = pos + partsize;
+ if(end > bin.length) {
+ end = bin.length
+ }
+ str += convertUTF8StringToUTF16String_internal(bin, pos, end);
+ pos = end;
+ end = pos === bin.length;
+ if(callback(str, end) && !end) {
+ runtime.setTimeout(f, 0)
+ }
+ }
+ f()
+ }
+ function convertUTF16StringToUTF8Array(uni) {
+ return convertUTF16ArrayToUTF8Array(stringToArray(uni))
+ }
+ function convertUTF16ArrayToUTF8String(uni) {
+ return String.fromCharCode.apply(String, convertUTF16ArrayToUTF8Array(uni))
+ }
+ function convertUTF16StringToUTF8String(uni) {
+ return String.fromCharCode.apply(String, convertUTF16ArrayToUTF8Array(stringToArray(uni)))
+ }
+ if(window && window.btoa) {
+ btoa = window.btoa;
+ convertUTF16StringToBase64 = function(uni) {
+ return btoa(convertUTF16StringToUTF8String(uni))
+ }
+ }else {
+ btoa = convertUTF8StringToBase64;
+ convertUTF16StringToBase64 = function(uni) {
+ return convertUTF8ArrayToBase64(convertUTF16StringToUTF8Array(uni))
+ }
+ }
+ if(window && window.atob) {
+ atob = window.atob;
+ convertBase64ToUTF16String = function(b64) {
+ var b = atob(b64);
+ return convertUTF8StringToUTF16String_internal(b, 0, b.length)
+ }
+ }else {
+ atob = convertBase64ToUTF8String;
+ convertBase64ToUTF16String = function(b64) {
+ return convertUTF8ArrayToUTF16String(convertBase64ToUTF8Array(b64))
+ }
+ }
+ core.Base64 = function Base64() {
+ this.convertUTF8ArrayToBase64 = convertUTF8ArrayToBase64;
+ this.convertByteArrayToBase64 = convertUTF8ArrayToBase64;
+ this.convertBase64ToUTF8Array = convertBase64ToUTF8Array;
+ this.convertBase64ToByteArray = convertBase64ToUTF8Array;
+ this.convertUTF16ArrayToUTF8Array = convertUTF16ArrayToUTF8Array;
+ this.convertUTF16ArrayToByteArray = convertUTF16ArrayToUTF8Array;
+ this.convertUTF8ArrayToUTF16Array = convertUTF8ArrayToUTF16Array;
+ this.convertByteArrayToUTF16Array = convertUTF8ArrayToUTF16Array;
+ this.convertUTF8StringToBase64 = convertUTF8StringToBase64;
+ this.convertBase64ToUTF8String = convertBase64ToUTF8String;
+ this.convertUTF8StringToUTF16Array = convertUTF8StringToUTF16Array;
+ this.convertUTF8ArrayToUTF16String = convertUTF8ArrayToUTF16String;
+ this.convertByteArrayToUTF16String = convertUTF8ArrayToUTF16String;
+ this.convertUTF8StringToUTF16String = convertUTF8StringToUTF16String;
+ this.convertUTF16StringToUTF8Array = convertUTF16StringToUTF8Array;
+ this.convertUTF16StringToByteArray = convertUTF16StringToUTF8Array;
+ this.convertUTF16ArrayToUTF8String = convertUTF16ArrayToUTF8String;
+ this.convertUTF16StringToUTF8String = convertUTF16StringToUTF8String;
+ this.convertUTF16StringToBase64 = convertUTF16StringToBase64;
+ this.convertBase64ToUTF16String = convertBase64ToUTF16String;
+ this.fromBase64 = convertBase64ToUTF8String;
+ this.toBase64 = convertUTF8StringToBase64;
+ this.atob = atob;
+ this.btoa = btoa;
+ this.utob = convertUTF16StringToUTF8String;
+ this.btou = convertUTF8StringToUTF16String;
+ this.encode = convertUTF16StringToBase64;
+ this.encodeURI = function(u) {
+ return convertUTF16StringToBase64(u).replace(/[+\/]/g, function(m0) {
+ return m0 === "+" ? "-" : "_"
+ }).replace(/\\=+$/, "")
+ };
+ this.decode = function(a) {
+ return convertBase64ToUTF16String(a.replace(/[\-_]/g, function(m0) {
+ return m0 === "-" ? "+" : "/"
+ }))
+ };
+ return this
+ };
+ return core.Base64
+}
+core.Base64 = makeBase64();
- core.RawDeflate = function() {
- var zip_WSIZE = 32768, zip_STORED_BLOCK = 0, zip_STATIC_TREES = 1, zip_DYN_TREES = 2, zip_DEFAULT_LEVEL = 6, zip_FULL_SEARCH = true, zip_INBUFSIZ = 32768, zip_INBUF_EXTRA = 64, zip_OUTBUFSIZ = 1024 * 8, zip_window_size = 2 * zip_WSIZE, zip_MIN_MATCH = 3, zip_MAX_MATCH = 258, zip_BITS = 16, zip_LIT_BUFSIZE = 8192, zip_HASH_BITS = 13, zip_DIST_BUFSIZE = zip_LIT_BUFSIZE, zip_HASH_SIZE = 1 << zip_HASH_BITS, zip_HASH_MASK = zip_HASH_SIZE - 1, zip_WMASK = zip_WSIZE - 1, zip_NIL = 0, zip_TOO [...]
- zip_MIN_LOOKAHEAD = zip_MAX_MATCH + zip_MIN_MATCH + 1, zip_MAX_DIST = zip_WSIZE - zip_MIN_LOOKAHEAD, zip_SMALLEST = 1, zip_MAX_BITS = 15, zip_MAX_BL_BITS = 7, zip_LENGTH_CODES = 29, zip_LITERALS = 256, zip_END_BLOCK = 256, zip_L_CODES = zip_LITERALS + 1 + zip_LENGTH_CODES, zip_D_CODES = 30, zip_BL_CODES = 19, zip_REP_3_6 = 16, zip_REPZ_3_10 = 17, zip_REPZ_11_138 = 18, zip_HEAP_SIZE = 2 * zip_L_CODES + 1, zip_H_SHIFT = parseInt((zip_HASH_BITS + zip_MIN_MATCH - 1) / zip_MIN_MATCH, 10), [...]
- zip_qhead, zip_qtail, zip_initflag, zip_outbuf = null, zip_outcnt, zip_outoff, zip_complete, zip_window, zip_d_buf, zip_l_buf, zip_prev, zip_bi_buf, zip_bi_valid, zip_block_start, zip_ins_h, zip_hash_head, zip_prev_match, zip_match_available, zip_match_length, zip_prev_length, zip_strstart, zip_match_start, zip_eofile, zip_lookahead, zip_max_chain_length, zip_max_lazy_match, zip_compr_level, zip_good_match, zip_nice_match, zip_dyn_ltree, zip_dyn_dtree, zip_static_ltree, zip_static_dtr [...]
- zip_l_desc, zip_d_desc, zip_bl_desc, zip_bl_count, zip_heap, zip_heap_len, zip_heap_max, zip_depth, zip_length_code, zip_dist_code, zip_base_length, zip_base_dist, zip_flag_buf, zip_last_lit, zip_last_dist, zip_last_flags, zip_flags, zip_flag_bit, zip_opt_len, zip_static_len, zip_deflate_data, zip_deflate_pos, zip_extra_lbits = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0], zip_extra_dbits = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, [...]
- 9, 10, 10, 11, 11, 12, 12, 13, 13], zip_extra_blbits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7], zip_bl_order = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15], zip_configuration_table;
- if(zip_LIT_BUFSIZE > zip_INBUFSIZ) {
- runtime.log("error: zip_INBUFSIZ is too small")
- }
- if(zip_WSIZE << 1 > 1 << zip_BITS) {
- runtime.log("error: zip_WSIZE is too large")
- }
- if(zip_HASH_BITS > zip_BITS - 1) {
- runtime.log("error: zip_HASH_BITS is too large")
- }
- if(zip_HASH_BITS < 8 || zip_MAX_MATCH !== 258) {
- runtime.log("error: Code too clever")
++core.ByteArray = function ByteArray(data) {
++ this.pos = 0;
++ this.data = data;
++ this.readUInt32LE = function() {
++ this.pos += 4;
++ var d = this.data, pos = this.pos;
++ return d[--pos] << 24 | d[--pos] << 16 | d[--pos] << 8 | d[--pos]
++ };
++ this.readUInt16LE = function() {
++ this.pos += 2;
++ var d = this.data, pos = this.pos;
++ return d[--pos] << 8 | d[--pos]
+ }
- function Zip_DeflateCT() {
- this.fc = 0;
- this.dl = 0
++};
++core.ByteArrayWriter = function ByteArrayWriter(encoding) {
++ var self = this, length = 0, bufferSize = 1024, data = new Uint8Array(new ArrayBuffer(bufferSize));
++ function expand(extraLength) {
++ var newData;
++ if(extraLength > bufferSize - length) {
++ bufferSize = Math.max(2 * bufferSize, length + extraLength);
++ newData = new Uint8Array(new ArrayBuffer(bufferSize));
++ newData.set(data);
++ data = newData
++ }
+ }
- function Zip_DeflateTreeDesc() {
- this.dyn_tree = null;
- this.static_tree = null;
- this.extra_bits = null;
- this.extra_base = 0;
- this.elems = 0;
- this.max_length = 0;
- this.max_code = 0
++ this.appendByteArrayWriter = function(writer) {
++ self.appendByteArray(writer.getByteArray())
++ };
++ this.appendByteArray = function(array) {
++ var l = array.length;
++ expand(l);
++ data.set(array, length);
++ length += l
++ };
++ this.appendArray = function(array) {
++ var l = array.length;
++ expand(l);
++ data.set(array, length);
++ length += l
++ };
++ this.appendUInt16LE = function(value) {
++ self.appendArray([value & 255, value >> 8 & 255])
++ };
++ this.appendUInt32LE = function(value) {
++ self.appendArray([value & 255, value >> 8 & 255, value >> 16 & 255, value >> 24 & 255])
++ };
++ this.appendString = function(string) {
++ self.appendByteArray(runtime.byteArrayFromString(string, encoding))
++ };
++ this.getLength = function() {
++ return length
++ };
++ this.getByteArray = function() {
++ var a = new Uint8Array(new ArrayBuffer(length));
++ a.set(data.subarray(0, length));
++ return a
+ }
- function Zip_DeflateConfiguration(a, b, c, d) {
- this.good_length = a;
- this.max_lazy = b;
- this.nice_length = c;
- this.max_chain = d
++};
++core.CSSUnits = function CSSUnits() {
++ var self = this, sizemap = {"in":1, "cm":2.54, "mm":25.4, "pt":72, "pc":12};
++ this.convert = function(value, oldUnit, newUnit) {
++ return value * sizemap[newUnit] / sizemap[oldUnit]
++ };
++ this.convertMeasure = function(measure, newUnit) {
++ var value, oldUnit, newMeasure;
++ if(measure && newUnit) {
++ value = parseFloat(measure);
++ oldUnit = measure.replace(value.toString(), "");
++ newMeasure = self.convert(value, oldUnit, newUnit).toString()
++ }else {
++ newMeasure = ""
++ }
++ return newMeasure
++ };
++ this.getUnits = function(measure) {
++ return measure.substr(measure.length - 2, measure.length)
+ }
- function Zip_DeflateBuffer() {
- this.next = null;
- this.len = 0;
- this.ptr = [];
- this.ptr.length = zip_OUTBUFSIZ;
- this.off = 0
++};
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++(function() {
++ var browserQuirks;
++ function getBrowserQuirks() {
++ var range, directBoundingRect, rangeBoundingRect, testContainer, testElement, detectedQuirks, window, document;
++ if(browserQuirks === undefined) {
++ window = runtime.getWindow();
++ document = window && window.document;
++ browserQuirks = {rangeBCRIgnoresElementBCR:false, unscaledRangeClientRects:false};
++ if(document) {
++ testContainer = document.createElement("div");
++ testContainer.style.position = "absolute";
++ testContainer.style.left = "-99999px";
++ testContainer.style.transform = "scale(2)";
++ testContainer.style["-webkit-transform"] = "scale(2)";
++ testElement = document.createElement("div");
++ testContainer.appendChild(testElement);
++ document.body.appendChild(testContainer);
++ range = document.createRange();
++ range.selectNode(testElement);
++ browserQuirks.rangeBCRIgnoresElementBCR = range.getClientRects().length === 0;
++ testElement.appendChild(document.createTextNode("Rect transform test"));
++ directBoundingRect = testElement.getBoundingClientRect();
++ rangeBoundingRect = range.getBoundingClientRect();
++ browserQuirks.unscaledRangeClientRects = Math.abs(directBoundingRect.height - rangeBoundingRect.height) > 2;
++ range.detach();
++ document.body.removeChild(testContainer);
++ detectedQuirks = Object.keys(browserQuirks).map(function(quirk) {
++ return quirk + ":" + String(browserQuirks[quirk])
++ }).join(", ");
++ runtime.log("Detected browser quirks - " + detectedQuirks)
++ }
++ }
++ return browserQuirks
+ }
- zip_configuration_table = [new Zip_DeflateConfiguration(0, 0, 0, 0), new Zip_DeflateConfiguration(4, 4, 8, 4), new Zip_DeflateConfiguration(4, 5, 16, 8), new Zip_DeflateConfiguration(4, 6, 32, 32), new Zip_DeflateConfiguration(4, 4, 16, 16), new Zip_DeflateConfiguration(8, 16, 32, 32), new Zip_DeflateConfiguration(8, 16, 128, 128), new Zip_DeflateConfiguration(8, 32, 128, 256), new Zip_DeflateConfiguration(32, 128, 258, 1024), new Zip_DeflateConfiguration(32, 258, 258, 4096)];
- function zip_deflate_start(level) {
- var i;
- if(!level) {
- level = zip_DEFAULT_LEVEL
- }else {
- if(level < 1) {
- level = 1
++ core.DomUtils = function DomUtils() {
++ var sharedRange = null;
++ function getSharedRange(doc) {
++ var range;
++ if(sharedRange) {
++ range = sharedRange
+ }else {
- if(level > 9) {
- level = 9
- }
++ sharedRange = range = (doc.createRange())
+ }
++ return range
+ }
- zip_compr_level = level;
- zip_initflag = false;
- zip_eofile = false;
- if(zip_outbuf !== null) {
- return
- }
- zip_free_queue = zip_qhead = zip_qtail = null;
- zip_outbuf = [];
- zip_outbuf.length = zip_OUTBUFSIZ;
- zip_window = [];
- zip_window.length = zip_window_size;
- zip_d_buf = [];
- zip_d_buf.length = zip_DIST_BUFSIZE;
- zip_l_buf = [];
- zip_l_buf.length = zip_INBUFSIZ + zip_INBUF_EXTRA;
- zip_prev = [];
- zip_prev.length = 1 << zip_BITS;
- zip_dyn_ltree = [];
- zip_dyn_ltree.length = zip_HEAP_SIZE;
- for(i = 0;i < zip_HEAP_SIZE;i++) {
- zip_dyn_ltree[i] = new Zip_DeflateCT
- }
- zip_dyn_dtree = [];
- zip_dyn_dtree.length = 2 * zip_D_CODES + 1;
- for(i = 0;i < 2 * zip_D_CODES + 1;i++) {
- zip_dyn_dtree[i] = new Zip_DeflateCT
- }
- zip_static_ltree = [];
- zip_static_ltree.length = zip_L_CODES + 2;
- for(i = 0;i < zip_L_CODES + 2;i++) {
- zip_static_ltree[i] = new Zip_DeflateCT
++ function findStablePoint(container, offset) {
++ var c = container;
++ if(offset < c.childNodes.length) {
++ c = c.childNodes.item(offset);
++ offset = 0;
++ while(c.firstChild) {
++ c = c.firstChild
++ }
++ }else {
++ while(c.lastChild) {
++ c = c.lastChild;
++ offset = c.nodeType === Node.TEXT_NODE ? c.textContent.length : c.childNodes.length
++ }
++ }
++ return{container:c, offset:offset}
+ }
- zip_static_dtree = [];
- zip_static_dtree.length = zip_D_CODES;
- for(i = 0;i < zip_D_CODES;i++) {
- zip_static_dtree[i] = new Zip_DeflateCT
++ function splitBoundaries(range) {
++ var modifiedNodes = [], end, splitStart, node, text;
++ if(range.startContainer.nodeType === Node.TEXT_NODE || range.endContainer.nodeType === Node.TEXT_NODE) {
++ end = range.endContainer && findStablePoint(range.endContainer, range.endOffset);
++ range.setEnd(end.container, end.offset);
++ node = range.endContainer;
++ if(range.endOffset !== 0 && node.nodeType === Node.TEXT_NODE) {
++ text = (node);
++ if(range.endOffset !== text.length) {
++ modifiedNodes.push(text.splitText(range.endOffset));
++ modifiedNodes.push(text)
++ }
++ }
++ node = range.startContainer;
++ if(range.startOffset !== 0 && node.nodeType === Node.TEXT_NODE) {
++ text = (node);
++ if(range.startOffset !== text.length) {
++ splitStart = text.splitText(range.startOffset);
++ modifiedNodes.push(text);
++ modifiedNodes.push(splitStart);
++ range.setStart(splitStart, 0)
++ }
++ }
++ }
++ return modifiedNodes
+ }
- zip_bl_tree = [];
- zip_bl_tree.length = 2 * zip_BL_CODES + 1;
- for(i = 0;i < 2 * zip_BL_CODES + 1;i++) {
- zip_bl_tree[i] = new Zip_DeflateCT
++ this.splitBoundaries = splitBoundaries;
++ function containsRange(container, insideRange) {
++ return container.compareBoundaryPoints(Range.START_TO_START, insideRange) <= 0 && container.compareBoundaryPoints(Range.END_TO_END, insideRange) >= 0
+ }
- zip_l_desc = new Zip_DeflateTreeDesc;
- zip_d_desc = new Zip_DeflateTreeDesc;
- zip_bl_desc = new Zip_DeflateTreeDesc;
- zip_bl_count = [];
- zip_bl_count.length = zip_MAX_BITS + 1;
- zip_heap = [];
- zip_heap.length = 2 * zip_L_CODES + 1;
- zip_depth = [];
- zip_depth.length = 2 * zip_L_CODES + 1;
- zip_length_code = [];
- zip_length_code.length = zip_MAX_MATCH - zip_MIN_MATCH + 1;
- zip_dist_code = [];
- zip_dist_code.length = 512;
- zip_base_length = [];
- zip_base_length.length = zip_LENGTH_CODES;
- zip_base_dist = [];
- zip_base_dist.length = zip_D_CODES;
- zip_flag_buf = [];
- zip_flag_buf.length = parseInt(zip_LIT_BUFSIZE / 8, 10)
- }
- var zip_reuse_queue = function(p) {
- p.next = zip_free_queue;
- zip_free_queue = p
- };
- var zip_new_queue = function() {
- var p;
- if(zip_free_queue !== null) {
- p = zip_free_queue;
- zip_free_queue = zip_free_queue.next
- }else {
- p = new Zip_DeflateBuffer
++ this.containsRange = containsRange;
++ function rangesIntersect(range1, range2) {
++ return range1.compareBoundaryPoints(Range.END_TO_START, range2) <= 0 && range1.compareBoundaryPoints(Range.START_TO_END, range2) >= 0
+ }
- p.next = null;
- p.len = p.off = 0;
- return p
- };
- var zip_head1 = function(i) {
- return zip_prev[zip_WSIZE + i]
- };
- var zip_head2 = function(i, val) {
- zip_prev[zip_WSIZE + i] = val;
- return val
- };
- var zip_qoutbuf = function() {
- var q, i;
- if(zip_outcnt !== 0) {
- q = zip_new_queue();
- if(zip_qhead === null) {
- zip_qhead = zip_qtail = q
- }else {
- zip_qtail = zip_qtail.next = q
++ this.rangesIntersect = rangesIntersect;
++ function getNodesInRange(range, nodeFilter) {
++ var document = range.startContainer.ownerDocument, elements = [], rangeRoot = range.commonAncestorContainer, root = (rangeRoot.nodeType === Node.TEXT_NODE ? rangeRoot.parentNode : rangeRoot), n, filterResult, treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_ALL, nodeFilter, false);
++ treeWalker.currentNode = range.startContainer;
++ n = range.startContainer;
++ while(n) {
++ filterResult = nodeFilter(n);
++ if(filterResult === NodeFilter.FILTER_ACCEPT) {
++ elements.push(n)
++ }else {
++ if(filterResult === NodeFilter.FILTER_REJECT) {
++ break
++ }
++ }
++ n = n.parentNode
+ }
- q.len = zip_outcnt - zip_outoff;
- for(i = 0;i < q.len;i++) {
- q.ptr[i] = zip_outbuf[zip_outoff + i]
++ elements.reverse();
++ n = treeWalker.nextNode();
++ while(n) {
++ elements.push(n);
++ n = treeWalker.nextNode()
+ }
- zip_outcnt = zip_outoff = 0
++ return elements
+ }
- };
- var zip_put_byte = function(c) {
- zip_outbuf[zip_outoff + zip_outcnt++] = c;
- if(zip_outoff + zip_outcnt === zip_OUTBUFSIZ) {
- zip_qoutbuf()
- }
- };
- var zip_put_short = function(w) {
- w &= 65535;
- if(zip_outoff + zip_outcnt < zip_OUTBUFSIZ - 2) {
- zip_outbuf[zip_outoff + zip_outcnt++] = w & 255;
- zip_outbuf[zip_outoff + zip_outcnt++] = w >>> 8
- }else {
- zip_put_byte(w & 255);
- zip_put_byte(w >>> 8)
++ this.getNodesInRange = getNodesInRange;
++ function mergeTextNodes(node, nextNode) {
++ var mergedNode = null, text, nextText;
++ if(node.nodeType === Node.TEXT_NODE) {
++ text = (node);
++ if(text.length === 0) {
++ text.parentNode.removeChild(text);
++ if(nextNode.nodeType === Node.TEXT_NODE) {
++ mergedNode = nextNode
++ }
++ }else {
++ if(nextNode.nodeType === Node.TEXT_NODE) {
++ nextText = (nextNode);
++ text.appendData(nextText.data);
++ nextNode.parentNode.removeChild(nextNode)
++ }
++ mergedNode = node
++ }
++ }
++ return mergedNode
+ }
- };
- var zip_INSERT_STRING = function() {
- zip_ins_h = (zip_ins_h << zip_H_SHIFT ^ zip_window[zip_strstart + zip_MIN_MATCH - 1] & 255) & zip_HASH_MASK;
- zip_hash_head = zip_head1(zip_ins_h);
- zip_prev[zip_strstart & zip_WMASK] = zip_hash_head;
- zip_head2(zip_ins_h, zip_strstart)
- };
- var zip_Buf_size = 16;
- var zip_send_bits = function(value, length) {
- if(zip_bi_valid > zip_Buf_size - length) {
- zip_bi_buf |= value << zip_bi_valid;
- zip_put_short(zip_bi_buf);
- zip_bi_buf = value >> zip_Buf_size - zip_bi_valid;
- zip_bi_valid += length - zip_Buf_size
- }else {
- zip_bi_buf |= value << zip_bi_valid;
- zip_bi_valid += length
++ function normalizeTextNodes(node) {
++ if(node && node.nextSibling) {
++ node = mergeTextNodes(node, node.nextSibling)
++ }
++ if(node && node.previousSibling) {
++ mergeTextNodes(node.previousSibling, node)
++ }
+ }
- };
- var zip_SEND_CODE = function(c, tree) {
- zip_send_bits(tree[c].fc, tree[c].dl)
- };
- var zip_D_CODE = function(dist) {
- return(dist < 256 ? zip_dist_code[dist] : zip_dist_code[256 + (dist >> 7)]) & 255
- };
- var zip_SMALLER = function(tree, n, m) {
- return tree[n].fc < tree[m].fc || tree[n].fc === tree[m].fc && zip_depth[n] <= zip_depth[m]
- };
- var zip_read_buff = function(buff, offset, n) {
- var i;
- for(i = 0;i < n && zip_deflate_pos < zip_deflate_data.length;i++) {
- buff[offset + i] = zip_deflate_data.charCodeAt(zip_deflate_pos++) & 255
++ this.normalizeTextNodes = normalizeTextNodes;
++ function rangeContainsNode(limits, node) {
++ var range = node.ownerDocument.createRange(), nodeRange = node.ownerDocument.createRange(), result;
++ range.setStart(limits.startContainer, limits.startOffset);
++ range.setEnd(limits.endContainer, limits.endOffset);
++ nodeRange.selectNodeContents(node);
++ result = containsRange(range, nodeRange);
++ range.detach();
++ nodeRange.detach();
++ return result
+ }
- return i
- };
- var zip_fill_window = function() {
- var n, m;
- var more = zip_window_size - zip_lookahead - zip_strstart;
- if(more === -1) {
- more--
- }else {
- if(zip_strstart >= zip_WSIZE + zip_MAX_DIST) {
- for(n = 0;n < zip_WSIZE;n++) {
- zip_window[n] = zip_window[n + zip_WSIZE]
- }
- zip_match_start -= zip_WSIZE;
- zip_strstart -= zip_WSIZE;
- zip_block_start -= zip_WSIZE;
- for(n = 0;n < zip_HASH_SIZE;n++) {
- m = zip_head1(n);
- zip_head2(n, m >= zip_WSIZE ? m - zip_WSIZE : zip_NIL)
- }
- for(n = 0;n < zip_WSIZE;n++) {
- m = zip_prev[n];
- zip_prev[n] = m >= zip_WSIZE ? m - zip_WSIZE : zip_NIL
- }
- more += zip_WSIZE
++ this.rangeContainsNode = rangeContainsNode;
++ function mergeIntoParent(targetNode) {
++ var parent = targetNode.parentNode;
++ while(targetNode.firstChild) {
++ parent.insertBefore(targetNode.firstChild, targetNode)
+ }
++ parent.removeChild(targetNode);
++ return parent
+ }
- if(!zip_eofile) {
- n = zip_read_buff(zip_window, zip_strstart + zip_lookahead, more);
- if(n <= 0) {
- zip_eofile = true
- }else {
- zip_lookahead += n
++ this.mergeIntoParent = mergeIntoParent;
++ function removeUnwantedNodes(targetNode, shouldRemove) {
++ var parent = targetNode.parentNode, node = targetNode.firstChild, next;
++ while(node) {
++ next = node.nextSibling;
++ removeUnwantedNodes(node, shouldRemove);
++ node = next
+ }
++ if(shouldRemove(targetNode)) {
++ parent = mergeIntoParent(targetNode)
++ }
++ return parent
+ }
- };
- var zip_lm_init = function() {
- var j;
- for(j = 0;j < zip_HASH_SIZE;j++) {
- zip_prev[zip_WSIZE + j] = 0
- }
- zip_max_lazy_match = zip_configuration_table[zip_compr_level].max_lazy;
- zip_good_match = zip_configuration_table[zip_compr_level].good_length;
- if(!zip_FULL_SEARCH) {
- zip_nice_match = zip_configuration_table[zip_compr_level].nice_length
++ this.removeUnwantedNodes = removeUnwantedNodes;
++ function getElementsByTagNameNS(node, namespace, tagName) {
++ var e = [], list, i, l;
++ list = node.getElementsByTagNameNS(namespace, tagName);
++ e.length = l = list.length;
++ for(i = 0;i < l;i += 1) {
++ e[i] = (list.item(i))
++ }
++ return e
+ }
- zip_max_chain_length = zip_configuration_table[zip_compr_level].max_chain;
- zip_strstart = 0;
- zip_block_start = 0;
- zip_lookahead = zip_read_buff(zip_window, 0, 2 * zip_WSIZE);
- if(zip_lookahead <= 0) {
- zip_eofile = true;
- zip_lookahead = 0;
- return
++ this.getElementsByTagNameNS = getElementsByTagNameNS;
++ function rangeIntersectsNode(range, node) {
++ var nodeRange = node.ownerDocument.createRange(), result;
++ nodeRange.selectNodeContents(node);
++ result = rangesIntersect(range, nodeRange);
++ nodeRange.detach();
++ return result
+ }
- zip_eofile = false;
- while(zip_lookahead < zip_MIN_LOOKAHEAD && !zip_eofile) {
- zip_fill_window()
++ this.rangeIntersectsNode = rangeIntersectsNode;
++ function containsNode(parent, descendant) {
++ return parent === descendant || (parent).contains((descendant))
+ }
- zip_ins_h = 0;
- for(j = 0;j < zip_MIN_MATCH - 1;j++) {
- zip_ins_h = (zip_ins_h << zip_H_SHIFT ^ zip_window[j] & 255) & zip_HASH_MASK
++ this.containsNode = containsNode;
++ function containsNodeForBrokenWebKit(parent, descendant) {
++ return parent === descendant || Boolean(parent.compareDocumentPosition(descendant) & Node.DOCUMENT_POSITION_CONTAINED_BY)
+ }
- };
- var zip_longest_match = function(cur_match) {
- var chain_length = zip_max_chain_length;
- var scanp = zip_strstart;
- var matchp;
- var len;
- var best_len = zip_prev_length;
- var limit = zip_strstart > zip_MAX_DIST ? zip_strstart - zip_MAX_DIST : zip_NIL;
- var strendp = zip_strstart + zip_MAX_MATCH;
- var scan_end1 = zip_window[scanp + best_len - 1];
- var scan_end = zip_window[scanp + best_len];
- if(zip_prev_length >= zip_good_match) {
- chain_length >>= 2
++ function getPositionInContainingNode(node, container) {
++ var offset = 0, n;
++ while(node.parentNode !== container) {
++ runtime.assert(node.parentNode !== null, "parent is null");
++ node = (node.parentNode)
++ }
++ n = container.firstChild;
++ while(n !== node) {
++ offset += 1;
++ n = n.nextSibling
++ }
++ return offset
+ }
- do {
- matchp = cur_match;
- if(zip_window[matchp + best_len] !== scan_end || (zip_window[matchp + best_len - 1] !== scan_end1 || (zip_window[matchp] !== zip_window[scanp] || zip_window[++matchp] !== zip_window[scanp + 1]))) {
- continue
++ function comparePoints(c1, o1, c2, o2) {
++ if(c1 === c2) {
++ return o2 - o1
+ }
- scanp += 2;
- matchp++;
- do {
- ++scanp
- }while(zip_window[scanp] === zip_window[++matchp] && (zip_window[++scanp] === zip_window[++matchp] && (zip_window[++scanp] === zip_window[++matchp] && (zip_window[++scanp] === zip_window[++matchp] && (zip_window[++scanp] === zip_window[++matchp] && (zip_window[++scanp] === zip_window[++matchp] && (zip_window[++scanp] === zip_window[++matchp] && (zip_window[++scanp] === zip_window[++matchp] && scanp < strendp))))))));
- len = zip_MAX_MATCH - (strendp - scanp);
- scanp = strendp - zip_MAX_MATCH;
- if(len > best_len) {
- zip_match_start = cur_match;
- best_len = len;
- if(zip_FULL_SEARCH) {
- if(len >= zip_MAX_MATCH) {
- break
- }
++ var comparison = c1.compareDocumentPosition(c2);
++ if(comparison === 2) {
++ comparison = -1
++ }else {
++ if(comparison === 4) {
++ comparison = 1
+ }else {
- if(len >= zip_nice_match) {
- break
++ if(comparison === 10) {
++ o1 = getPositionInContainingNode(c1, c2);
++ comparison = o1 < o2 ? 1 : -1
++ }else {
++ o2 = getPositionInContainingNode(c2, c1);
++ comparison = o2 < o1 ? -1 : 1
+ }
+ }
- scan_end1 = zip_window[scanp + best_len - 1];
- scan_end = zip_window[scanp + best_len]
+ }
- cur_match = zip_prev[cur_match & zip_WMASK]
- }while(cur_match > limit && --chain_length !== 0);
- return best_len
- };
- var zip_ct_tally = function(dist, lc) {
- zip_l_buf[zip_last_lit++] = lc;
- if(dist === 0) {
- zip_dyn_ltree[lc].fc++
- }else {
- dist--;
- zip_dyn_ltree[zip_length_code[lc] + zip_LITERALS + 1].fc++;
- zip_dyn_dtree[zip_D_CODE(dist)].fc++;
- zip_d_buf[zip_last_dist++] = dist;
- zip_flags |= zip_flag_bit
- }
- zip_flag_bit <<= 1;
- if((zip_last_lit & 7) === 0) {
- zip_flag_buf[zip_last_flags++] = zip_flags;
- zip_flags = 0;
- zip_flag_bit = 1
++ return comparison
+ }
- if(zip_compr_level > 2 && (zip_last_lit & 4095) === 0) {
- var out_length = zip_last_lit * 8;
- var in_length = zip_strstart - zip_block_start;
- var dcode;
- for(dcode = 0;dcode < zip_D_CODES;dcode++) {
- out_length += zip_dyn_dtree[dcode].fc * (5 + zip_extra_dbits[dcode])
- }
- out_length >>= 3;
- if(zip_last_dist < parseInt(zip_last_lit / 2, 10) && out_length < parseInt(in_length / 2, 10)) {
- return true
++ this.comparePoints = comparePoints;
++ function adaptRangeDifferenceToZoomLevel(inputNumber, zoomLevel) {
++ if(getBrowserQuirks().unscaledRangeClientRects) {
++ return inputNumber
+ }
++ return inputNumber / zoomLevel
+ }
- return zip_last_lit === zip_LIT_BUFSIZE - 1 || zip_last_dist === zip_DIST_BUFSIZE
- };
- var zip_pqdownheap = function(tree, k) {
- var v = zip_heap[k];
- var j = k << 1;
- while(j <= zip_heap_len) {
- if(j < zip_heap_len && zip_SMALLER(tree, zip_heap[j + 1], zip_heap[j])) {
- j++
- }
- if(zip_SMALLER(tree, v, zip_heap[j])) {
- break
++ this.adaptRangeDifferenceToZoomLevel = adaptRangeDifferenceToZoomLevel;
++ function getBoundingClientRect(node) {
++ var doc = (node.ownerDocument), quirks = getBrowserQuirks(), range, element;
++ if(quirks.unscaledRangeClientRects === false || quirks.rangeBCRIgnoresElementBCR) {
++ if(node.nodeType === Node.ELEMENT_NODE) {
++ element = (node);
++ return element.getBoundingClientRect()
++ }
+ }
- zip_heap[k] = zip_heap[j];
- k = j;
- j <<= 1
++ range = getSharedRange(doc);
++ range.selectNode(node);
++ return range.getBoundingClientRect()
+ }
- zip_heap[k] = v
- };
- var zip_gen_bitlen = function(desc) {
- var tree = desc.dyn_tree;
- var extra = desc.extra_bits;
- var base = desc.extra_base;
- var max_code = desc.max_code;
- var max_length = desc.max_length;
- var stree = desc.static_tree;
- var h;
- var n, m;
- var bits;
- var xbits;
- var f;
- var overflow = 0;
- for(bits = 0;bits <= zip_MAX_BITS;bits++) {
- zip_bl_count[bits] = 0
++ this.getBoundingClientRect = getBoundingClientRect;
++ function mapKeyValObjOntoNode(node, properties, nsResolver) {
++ Object.keys(properties).forEach(function(key) {
++ var parts = key.split(":"), prefix = parts[0], localName = parts[1], ns = nsResolver(prefix), value = properties[key], element;
++ if(ns) {
++ element = (node.getElementsByTagNameNS(ns, localName)[0]);
++ if(!element) {
++ element = node.ownerDocument.createElementNS(ns, key);
++ node.appendChild(element)
++ }
++ element.textContent = value
++ }else {
++ runtime.log("Key ignored: " + key)
++ }
++ })
+ }
- tree[zip_heap[zip_heap_max]].dl = 0;
- for(h = zip_heap_max + 1;h < zip_HEAP_SIZE;h++) {
- n = zip_heap[h];
- bits = tree[tree[n].dl].dl + 1;
- if(bits > max_length) {
- bits = max_length;
- overflow++
- }
- tree[n].dl = bits;
- if(n > max_code) {
- continue
- }
- zip_bl_count[bits]++;
- xbits = 0;
- if(n >= base) {
- xbits = extra[n - base]
- }
- f = tree[n].fc;
- zip_opt_len += f * (bits + xbits);
- if(stree !== null) {
- zip_static_len += f * (stree[n].dl + xbits)
++ this.mapKeyValObjOntoNode = mapKeyValObjOntoNode;
++ function removeKeyElementsFromNode(node, propertyNames, nsResolver) {
++ propertyNames.forEach(function(propertyName) {
++ var parts = propertyName.split(":"), prefix = parts[0], localName = parts[1], ns = nsResolver(prefix), element;
++ if(ns) {
++ element = (node.getElementsByTagNameNS(ns, localName)[0]);
++ if(element) {
++ element.parentNode.removeChild(element)
++ }else {
++ runtime.log("Element for " + propertyName + " not found.")
++ }
++ }else {
++ runtime.log("Property Name ignored: " + propertyName)
++ }
++ })
++ }
++ this.removeKeyElementsFromNode = removeKeyElementsFromNode;
++ function getKeyValRepresentationOfNode(node, prefixResolver) {
++ var properties = {}, currentSibling = node.firstElementChild, prefix;
++ while(currentSibling) {
++ prefix = prefixResolver(currentSibling.namespaceURI);
++ if(prefix) {
++ properties[prefix + ":" + currentSibling.localName] = currentSibling.textContent
++ }
++ currentSibling = currentSibling.nextElementSibling
+ }
++ return properties
+ }
- if(overflow === 0) {
- return
++ this.getKeyValRepresentationOfNode = getKeyValRepresentationOfNode;
++ function mapObjOntoNode(node, properties, nsResolver) {
++ Object.keys(properties).forEach(function(key) {
++ var parts = key.split(":"), prefix = parts[0], localName = parts[1], ns = nsResolver(prefix), value = properties[key], element;
++ if(typeof value === "object" && Object.keys((value)).length) {
++ if(ns) {
++ element = (node.getElementsByTagNameNS(ns, localName)[0]) || node.ownerDocument.createElementNS(ns, key)
++ }else {
++ element = (node.getElementsByTagName(localName)[0]) || node.ownerDocument.createElement(key)
++ }
++ node.appendChild(element);
++ mapObjOntoNode(element, (value), nsResolver)
++ }else {
++ if(ns) {
++ node.setAttributeNS(ns, key, String(value))
++ }
++ }
++ })
+ }
- do {
- bits = max_length - 1;
- while(zip_bl_count[bits] === 0) {
- bits--
++ this.mapObjOntoNode = mapObjOntoNode;
++ function init(self) {
++ var appVersion, webKitOrSafari, ie, window = runtime.getWindow();
++ if(window === null) {
++ return
+ }
- zip_bl_count[bits]--;
- zip_bl_count[bits + 1] += 2;
- zip_bl_count[max_length]--;
- overflow -= 2
- }while(overflow > 0);
- for(bits = max_length;bits !== 0;bits--) {
- n = zip_bl_count[bits];
- while(n !== 0) {
- m = zip_heap[--h];
- if(m > max_code) {
- continue
- }
- if(tree[m].dl !== bits) {
- zip_opt_len += (bits - tree[m].dl) * tree[m].fc;
- tree[m].fc = bits
- }
- n--
++ appVersion = window.navigator.appVersion.toLowerCase();
++ webKitOrSafari = appVersion.indexOf("chrome") === -1 && (appVersion.indexOf("applewebkit") !== -1 || appVersion.indexOf("safari") !== -1);
++ ie = appVersion.indexOf("msie");
++ if(webKitOrSafari || ie) {
++ self.containsNode = containsNodeForBrokenWebKit
+ }
+ }
++ init(this)
+ };
- var zip_bi_reverse = function(code, len) {
- var res = 0;
- do {
- res |= code & 1;
- code >>= 1;
- res <<= 1
- }while(--len > 0);
- return res >> 1
- };
- var zip_gen_codes = function(tree, max_code) {
- var next_code = [];
- next_code.length = zip_MAX_BITS + 1;
- var code = 0;
- var bits;
- var n;
- for(bits = 1;bits <= zip_MAX_BITS;bits++) {
- code = code + zip_bl_count[bits - 1] << 1;
- next_code[bits] = code
++ return core.DomUtils
++})();
++/*
++
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++core.EventNotifier = function EventNotifier(eventIds) {
++ var eventListener = {};
++ this.emit = function(eventId, args) {
++ var i, subscribers;
++ runtime.assert(eventListener.hasOwnProperty(eventId), 'unknown event fired "' + eventId + '"');
++ subscribers = eventListener[eventId];
++ for(i = 0;i < subscribers.length;i += 1) {
++ subscribers[i](args)
+ }
- var len;
- for(n = 0;n <= max_code;n++) {
- len = tree[n].dl;
- if(len === 0) {
- continue
- }
- tree[n].fc = zip_bi_reverse(next_code[len]++, len)
++ };
++ this.subscribe = function(eventId, cb) {
++ runtime.assert(eventListener.hasOwnProperty(eventId), 'tried to subscribe to unknown event "' + eventId + '"');
++ eventListener[eventId].push(cb);
++ runtime.log('event "' + eventId + '" subscribed.')
++ };
++ this.unsubscribe = function(eventId, cb) {
++ var cbIndex;
++ runtime.assert(eventListener.hasOwnProperty(eventId), 'tried to unsubscribe from unknown event "' + eventId + '"');
++ cbIndex = eventListener[eventId].indexOf(cb);
++ runtime.assert(cbIndex !== -1, 'tried to unsubscribe unknown callback from event "' + eventId + '"');
++ if(cbIndex !== -1) {
++ eventListener[eventId].splice(cbIndex, 1)
+ }
++ runtime.log('event "' + eventId + '" unsubscribed.')
+ };
- var zip_build_tree = function(desc) {
- var tree = desc.dyn_tree;
- var stree = desc.static_tree;
- var elems = desc.elems;
- var n, m;
- var max_code = -1;
- var node = elems;
- zip_heap_len = 0;
- zip_heap_max = zip_HEAP_SIZE;
- for(n = 0;n < elems;n++) {
- if(tree[n].fc !== 0) {
- zip_heap[++zip_heap_len] = max_code = n;
- zip_depth[n] = 0
- }else {
- tree[n].dl = 0
++ function init() {
++ var i, eventId;
++ for(i = 0;i < eventIds.length;i += 1) {
++ eventId = eventIds[i];
++ runtime.assert(!eventListener.hasOwnProperty(eventId), 'Duplicated event ids: "' + eventId + '" registered more than once.');
++ eventListener[eventId] = []
++ }
++ }
++ init()
++};
++/*
++
++ Copyright (C) 2012 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++core.LoopWatchDog = function LoopWatchDog(timeout, maxChecks) {
++ var startTime = Date.now(), checks = 0;
++ function check() {
++ var t;
++ if(timeout) {
++ t = Date.now();
++ if(t - startTime > timeout) {
++ runtime.log("alert", "watchdog timeout");
++ throw"timeout!";
+ }
+ }
- var xnew;
- while(zip_heap_len < 2) {
- xnew = zip_heap[++zip_heap_len] = max_code < 2 ? ++max_code : 0;
- tree[xnew].fc = 1;
- zip_depth[xnew] = 0;
- zip_opt_len--;
- if(stree !== null) {
- zip_static_len -= stree[xnew].dl
++ if(maxChecks > 0) {
++ checks += 1;
++ if(checks > maxChecks) {
++ runtime.log("alert", "watchdog loop overflow");
++ throw"loop overflow";
+ }
+ }
- desc.max_code = max_code;
- for(n = zip_heap_len >> 1;n >= 1;n--) {
- zip_pqdownheap(tree, n)
++ }
++ this.check = check
++};
++core.PositionIterator = function PositionIterator(root, whatToShow, filter, expandEntityReferences) {
++ var self = this, walker, currentPos, nodeFilter, TEXT_NODE = Node.TEXT_NODE, ELEMENT_NODE = Node.ELEMENT_NODE, FILTER_ACCEPT = NodeFilter.FILTER_ACCEPT, FILTER_REJECT = NodeFilter.FILTER_REJECT;
++ function EmptyTextNodeFilter() {
++ this.acceptNode = function(node) {
++ var text = (node);
++ if(!node || node.nodeType === TEXT_NODE && text.length === 0) {
++ return FILTER_REJECT
++ }
++ return FILTER_ACCEPT
+ }
- do {
- n = zip_heap[zip_SMALLEST];
- zip_heap[zip_SMALLEST] = zip_heap[zip_heap_len--];
- zip_pqdownheap(tree, zip_SMALLEST);
- m = zip_heap[zip_SMALLEST];
- zip_heap[--zip_heap_max] = n;
- zip_heap[--zip_heap_max] = m;
- tree[node].fc = tree[n].fc + tree[m].fc;
- if(zip_depth[n] > zip_depth[m] + 1) {
- zip_depth[node] = zip_depth[n]
- }else {
- zip_depth[node] = zip_depth[m] + 1
++ }
++ function FilteredEmptyTextNodeFilter(filter) {
++ this.acceptNode = function(node) {
++ var text = (node);
++ if(!node || node.nodeType === TEXT_NODE && text.length === 0) {
++ return FILTER_REJECT
+ }
- tree[n].dl = tree[m].dl = node;
- zip_heap[zip_SMALLEST] = node++;
- zip_pqdownheap(tree, zip_SMALLEST)
- }while(zip_heap_len >= 2);
- zip_heap[--zip_heap_max] = zip_heap[zip_SMALLEST];
- zip_gen_bitlen(desc);
- zip_gen_codes(tree, max_code)
- };
- var zip_scan_tree = function(tree, max_code) {
- var n;
- var prevlen = -1;
- var curlen;
- var nextlen = tree[0].dl;
- var count = 0;
- var max_count = 7;
- var min_count = 4;
- if(nextlen === 0) {
- max_count = 138;
- min_count = 3
++ return filter.acceptNode(node)
+ }
- tree[max_code + 1].dl = 65535;
- for(n = 0;n <= max_code;n++) {
- curlen = nextlen;
- nextlen = tree[n + 1].dl;
- if(++count < max_count && curlen === nextlen) {
- continue
++ }
++ this.nextPosition = function() {
++ var currentNode = walker.currentNode, nodeType = currentNode.nodeType, text = (currentNode);
++ if(currentNode === root) {
++ return false
++ }
++ if(currentPos === 0 && nodeType === ELEMENT_NODE) {
++ if(walker.firstChild() === null) {
++ currentPos = 1
+ }
- if(count < min_count) {
- zip_bl_tree[curlen].fc += count
++ }else {
++ if(nodeType === TEXT_NODE && currentPos + 1 < text.length) {
++ currentPos += 1
+ }else {
- if(curlen !== 0) {
- if(curlen !== prevlen) {
- zip_bl_tree[curlen].fc++
- }
- zip_bl_tree[zip_REP_3_6].fc++
++ if(walker.nextSibling() !== null) {
++ currentPos = 0
+ }else {
- if(count <= 10) {
- zip_bl_tree[zip_REPZ_3_10].fc++
++ if(walker.parentNode()) {
++ currentPos = 1
+ }else {
- zip_bl_tree[zip_REPZ_11_138].fc++
++ return false
+ }
+ }
+ }
- count = 0;
- prevlen = curlen;
- if(nextlen === 0) {
- max_count = 138;
- min_count = 3
++ }
++ return true
++ };
++ function setAtEnd() {
++ var text = (walker.currentNode), type = text.nodeType;
++ if(type === TEXT_NODE) {
++ currentPos = text.length - 1
++ }else {
++ currentPos = type === ELEMENT_NODE ? 1 : 0
++ }
++ }
++ function previousNode() {
++ if(walker.previousSibling() === null) {
++ if(!walker.parentNode() || walker.currentNode === root) {
++ walker.firstChild();
++ return false
++ }
++ currentPos = 0
++ }else {
++ setAtEnd()
++ }
++ return true
++ }
++ this.previousPosition = function() {
++ var moved = true, currentNode = walker.currentNode;
++ if(currentPos === 0) {
++ moved = previousNode()
++ }else {
++ if(currentNode.nodeType === TEXT_NODE) {
++ currentPos -= 1
+ }else {
- if(curlen === nextlen) {
- max_count = 6;
- min_count = 3
++ if(walker.lastChild() !== null) {
++ setAtEnd()
+ }else {
- max_count = 7;
- min_count = 4
++ if(currentNode === root) {
++ moved = false
++ }else {
++ currentPos = 0
++ }
+ }
+ }
+ }
++ return moved
+ };
- var zip_build_bl_tree = function() {
- var max_blindex;
- zip_scan_tree(zip_dyn_ltree, zip_l_desc.max_code);
- zip_scan_tree(zip_dyn_dtree, zip_d_desc.max_code);
- zip_build_tree(zip_bl_desc);
- for(max_blindex = zip_BL_CODES - 1;max_blindex >= 3;max_blindex--) {
- if(zip_bl_tree[zip_bl_order[max_blindex]].dl !== 0) {
- break
- }
++ this.previousNode = previousNode;
++ this.container = function() {
++ var n = (walker.currentNode), t = n.nodeType;
++ if(currentPos === 0 && t !== TEXT_NODE) {
++ n = (n.parentNode)
+ }
- zip_opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
- return max_blindex
++ return n
+ };
- var zip_bi_windup = function() {
- if(zip_bi_valid > 8) {
- zip_put_short(zip_bi_buf)
++ this.rightNode = function() {
++ var n = walker.currentNode, text = (n), nodeType = n.nodeType;
++ if(nodeType === TEXT_NODE && currentPos === text.length) {
++ n = n.nextSibling;
++ while(n && nodeFilter(n) !== FILTER_ACCEPT) {
++ n = n.nextSibling
++ }
+ }else {
- if(zip_bi_valid > 0) {
- zip_put_byte(zip_bi_buf)
++ if(nodeType === ELEMENT_NODE && currentPos === 1) {
++ n = null
+ }
+ }
- zip_bi_buf = 0;
- zip_bi_valid = 0
++ return n
+ };
- var zip_compress_block = function(ltree, dtree) {
- var dist;
- var lc;
- var lx = 0;
- var dx = 0;
- var fx = 0;
- var flag = 0;
- var code;
- var extra;
- if(zip_last_lit !== 0) {
- do {
- if((lx & 7) === 0) {
- flag = zip_flag_buf[fx++]
- }
- lc = zip_l_buf[lx++] & 255;
- if((flag & 1) === 0) {
- zip_SEND_CODE(lc, ltree)
- }else {
- code = zip_length_code[lc];
- zip_SEND_CODE(code + zip_LITERALS + 1, ltree);
- extra = zip_extra_lbits[code];
- if(extra !== 0) {
- lc -= zip_base_length[code];
- zip_send_bits(lc, extra)
- }
- dist = zip_d_buf[dx++];
- code = zip_D_CODE(dist);
- zip_SEND_CODE(code, dtree);
- extra = zip_extra_dbits[code];
- if(extra !== 0) {
- dist -= zip_base_dist[code];
- zip_send_bits(dist, extra)
- }
++ this.leftNode = function() {
++ var n = walker.currentNode;
++ if(currentPos === 0) {
++ n = n.previousSibling;
++ while(n && nodeFilter(n) !== FILTER_ACCEPT) {
++ n = n.previousSibling
++ }
++ }else {
++ if(n.nodeType === ELEMENT_NODE) {
++ n = n.lastChild;
++ while(n && nodeFilter(n) !== FILTER_ACCEPT) {
++ n = n.previousSibling
+ }
- flag >>= 1
- }while(lx < zip_last_lit)
++ }
+ }
- zip_SEND_CODE(zip_END_BLOCK, ltree)
++ return n
+ };
- var zip_send_tree = function(tree, max_code) {
- var n;
- var prevlen = -1;
- var curlen;
- var nextlen = tree[0].dl;
- var count = 0;
- var max_count = 7;
- var min_count = 4;
- if(nextlen === 0) {
- max_count = 138;
- min_count = 3
++ this.getCurrentNode = function() {
++ var n = (walker.currentNode);
++ return n
++ };
++ this.unfilteredDomOffset = function() {
++ if(walker.currentNode.nodeType === TEXT_NODE) {
++ return currentPos
+ }
- for(n = 0;n <= max_code;n++) {
- curlen = nextlen;
- nextlen = tree[n + 1].dl;
- if(++count < max_count && curlen === nextlen) {
- continue
- }
- if(count < min_count) {
- do {
- zip_SEND_CODE(curlen, zip_bl_tree)
- }while(--count !== 0)
- }else {
- if(curlen !== 0) {
- if(curlen !== prevlen) {
- zip_SEND_CODE(curlen, zip_bl_tree);
- count--
- }
- zip_SEND_CODE(zip_REP_3_6, zip_bl_tree);
- zip_send_bits(count - 3, 2)
++ var c = 0, n = walker.currentNode;
++ if(currentPos === 1) {
++ n = n.lastChild
++ }else {
++ n = n.previousSibling
++ }
++ while(n) {
++ c += 1;
++ n = n.previousSibling
++ }
++ return c
++ };
++ this.getPreviousSibling = function() {
++ var currentNode = walker.currentNode, sibling = walker.previousSibling();
++ walker.currentNode = currentNode;
++ return sibling
++ };
++ this.getNextSibling = function() {
++ var currentNode = walker.currentNode, sibling = walker.nextSibling();
++ walker.currentNode = currentNode;
++ return sibling
++ };
++ this.setUnfilteredPosition = function(container, offset) {
++ var filterResult, node, text;
++ runtime.assert(container !== null && container !== undefined, "PositionIterator.setUnfilteredPosition called without container");
++ walker.currentNode = container;
++ if(container.nodeType === TEXT_NODE) {
++ currentPos = offset;
++ text = (container);
++ runtime.assert(offset <= text.length, "Error in setPosition: " + offset + " > " + text.length);
++ runtime.assert(offset >= 0, "Error in setPosition: " + offset + " < 0");
++ if(offset === text.length) {
++ if(walker.nextSibling()) {
++ currentPos = 0
+ }else {
- if(count <= 10) {
- zip_SEND_CODE(zip_REPZ_3_10, zip_bl_tree);
- zip_send_bits(count - 3, 3)
++ if(walker.parentNode()) {
++ currentPos = 1
+ }else {
- zip_SEND_CODE(zip_REPZ_11_138, zip_bl_tree);
- zip_send_bits(count - 11, 7)
++ runtime.assert(false, "Error in setUnfilteredPosition: position not valid.")
+ }
+ }
+ }
- count = 0;
- prevlen = curlen;
- if(nextlen === 0) {
- max_count = 138;
- min_count = 3
- }else {
- if(curlen === nextlen) {
- max_count = 6;
- min_count = 3
- }else {
- max_count = 7;
- min_count = 4
- }
- }
++ return true
+ }
- };
- var zip_send_all_trees = function(lcodes, dcodes, blcodes) {
- var rank;
- zip_send_bits(lcodes - 257, 5);
- zip_send_bits(dcodes - 1, 5);
- zip_send_bits(blcodes - 4, 4);
- for(rank = 0;rank < blcodes;rank++) {
- zip_send_bits(zip_bl_tree[zip_bl_order[rank]].dl, 3)
++ filterResult = nodeFilter(container);
++ node = container.parentNode;
++ while(node && (node !== root && filterResult === FILTER_ACCEPT)) {
++ filterResult = nodeFilter(node);
++ if(filterResult !== FILTER_ACCEPT) {
++ walker.currentNode = node
++ }
++ node = node.parentNode
+ }
- zip_send_tree(zip_dyn_ltree, lcodes - 1);
- zip_send_tree(zip_dyn_dtree, dcodes - 1)
- };
- var zip_init_block = function() {
- var n;
- for(n = 0;n < zip_L_CODES;n++) {
- zip_dyn_ltree[n].fc = 0
++ if(offset < container.childNodes.length && filterResult !== NodeFilter.FILTER_REJECT) {
++ walker.currentNode = (container.childNodes.item(offset));
++ filterResult = nodeFilter(walker.currentNode);
++ currentPos = 0
++ }else {
++ currentPos = 1
+ }
- for(n = 0;n < zip_D_CODES;n++) {
- zip_dyn_dtree[n].fc = 0
++ if(filterResult === NodeFilter.FILTER_REJECT) {
++ currentPos = 1
+ }
- for(n = 0;n < zip_BL_CODES;n++) {
- zip_bl_tree[n].fc = 0
++ if(filterResult !== FILTER_ACCEPT) {
++ return self.nextPosition()
+ }
- zip_dyn_ltree[zip_END_BLOCK].fc = 1;
- zip_opt_len = zip_static_len = 0;
- zip_last_lit = zip_last_dist = zip_last_flags = 0;
- zip_flags = 0;
- zip_flag_bit = 1
++ runtime.assert(nodeFilter(walker.currentNode) === FILTER_ACCEPT, "PositionIterater.setUnfilteredPosition call resulted in an non-visible node being set");
++ return true
+ };
- var zip_flush_block = function(eof) {
- var opt_lenb, static_lenb;
- var max_blindex;
- var stored_len;
- stored_len = zip_strstart - zip_block_start;
- zip_flag_buf[zip_last_flags] = zip_flags;
- zip_build_tree(zip_l_desc);
- zip_build_tree(zip_d_desc);
- max_blindex = zip_build_bl_tree();
- opt_lenb = zip_opt_len + 3 + 7 >> 3;
- static_lenb = zip_static_len + 3 + 7 >> 3;
- if(static_lenb <= opt_lenb) {
- opt_lenb = static_lenb
++ this.moveToEnd = function() {
++ walker.currentNode = root;
++ currentPos = 1
++ };
++ this.moveToEndOfNode = function(node) {
++ var text;
++ if(node.nodeType === TEXT_NODE) {
++ text = (node);
++ self.setUnfilteredPosition(text, text.length)
++ }else {
++ walker.currentNode = node;
++ currentPos = 1
+ }
- if(stored_len + 4 <= opt_lenb && zip_block_start >= 0) {
- var i;
- zip_send_bits((zip_STORED_BLOCK << 1) + eof, 3);
- zip_bi_windup();
- zip_put_short(stored_len);
- zip_put_short(~stored_len);
- for(i = 0;i < stored_len;i++) {
- zip_put_byte(zip_window[zip_block_start + i])
- }
++ };
++ this.getNodeFilter = function() {
++ return nodeFilter
++ };
++ function init() {
++ var f;
++ if(filter) {
++ f = new FilteredEmptyTextNodeFilter(filter)
+ }else {
- if(static_lenb === opt_lenb) {
- zip_send_bits((zip_STATIC_TREES << 1) + eof, 3);
- zip_compress_block(zip_static_ltree, zip_static_dtree)
- }else {
- zip_send_bits((zip_DYN_TREES << 1) + eof, 3);
- zip_send_all_trees(zip_l_desc.max_code + 1, zip_d_desc.max_code + 1, max_blindex + 1);
- zip_compress_block(zip_dyn_ltree, zip_dyn_dtree)
- }
++ f = new EmptyTextNodeFilter
+ }
- zip_init_block();
- if(eof !== 0) {
- zip_bi_windup()
++ nodeFilter = (f.acceptNode);
++ nodeFilter.acceptNode = nodeFilter;
++ whatToShow = whatToShow || 4294967295;
++ runtime.assert(root.nodeType !== Node.TEXT_NODE, "Internet Explorer doesn't allow tree walker roots to be text nodes");
++ walker = root.ownerDocument.createTreeWalker(root, whatToShow, nodeFilter, expandEntityReferences);
++ currentPos = 0;
++ if(walker.firstChild() === null) {
++ currentPos = 1
+ }
- };
- var zip_deflate_fast = function() {
- var flush;
- while(zip_lookahead !== 0 && zip_qhead === null) {
- zip_INSERT_STRING();
- if(zip_hash_head !== zip_NIL && zip_strstart - zip_hash_head <= zip_MAX_DIST) {
- zip_match_length = zip_longest_match(zip_hash_head);
- if(zip_match_length > zip_lookahead) {
- zip_match_length = zip_lookahead
- }
- }
- if(zip_match_length >= zip_MIN_MATCH) {
- flush = zip_ct_tally(zip_strstart - zip_match_start, zip_match_length - zip_MIN_MATCH);
- zip_lookahead -= zip_match_length;
- if(zip_match_length <= zip_max_lazy_match) {
- zip_match_length--;
- do {
- zip_strstart++;
- zip_INSERT_STRING()
- }while(--zip_match_length !== 0);
- zip_strstart++
- }else {
- zip_strstart += zip_match_length;
- zip_match_length = 0;
- zip_ins_h = zip_window[zip_strstart] & 255;
- zip_ins_h = (zip_ins_h << zip_H_SHIFT ^ zip_window[zip_strstart + 1] & 255) & zip_HASH_MASK
- }
- }else {
- flush = zip_ct_tally(0, zip_window[zip_strstart] & 255);
- zip_lookahead--;
- zip_strstart++
- }
- if(flush) {
- zip_flush_block(0);
- zip_block_start = zip_strstart
- }
- while(zip_lookahead < zip_MIN_LOOKAHEAD && !zip_eofile) {
- zip_fill_window()
- }
- }
- };
- var zip_deflate_better = function() {
- var flush;
- while(zip_lookahead !== 0 && zip_qhead === null) {
- zip_INSERT_STRING();
- zip_prev_length = zip_match_length;
- zip_prev_match = zip_match_start;
- zip_match_length = zip_MIN_MATCH - 1;
- if(zip_hash_head !== zip_NIL && (zip_prev_length < zip_max_lazy_match && zip_strstart - zip_hash_head <= zip_MAX_DIST)) {
- zip_match_length = zip_longest_match(zip_hash_head);
- if(zip_match_length > zip_lookahead) {
- zip_match_length = zip_lookahead
- }
- if(zip_match_length === zip_MIN_MATCH && zip_strstart - zip_match_start > zip_TOO_FAR) {
- zip_match_length--
- }
- }
- if(zip_prev_length >= zip_MIN_MATCH && zip_match_length <= zip_prev_length) {
- flush = zip_ct_tally(zip_strstart - 1 - zip_prev_match, zip_prev_length - zip_MIN_MATCH);
- zip_lookahead -= zip_prev_length - 1;
- zip_prev_length -= 2;
- do {
- zip_strstart++;
- zip_INSERT_STRING()
- }while(--zip_prev_length !== 0);
- zip_match_available = 0;
- zip_match_length = zip_MIN_MATCH - 1;
- zip_strstart++;
- if(flush) {
- zip_flush_block(0);
- zip_block_start = zip_strstart
- }
- }else {
- if(zip_match_available !== 0) {
- if(zip_ct_tally(0, zip_window[zip_strstart - 1] & 255)) {
- zip_flush_block(0);
- zip_block_start = zip_strstart
- }
- zip_strstart++;
- zip_lookahead--
- }else {
- zip_match_available = 1;
- zip_strstart++;
- zip_lookahead--
- }
- }
- while(zip_lookahead < zip_MIN_LOOKAHEAD && !zip_eofile) {
- zip_fill_window()
- }
++ }
++ init()
++};
++core.zip_HuftNode = function() {
++ this.e = 0;
++ this.b = 0;
++ this.n = 0;
++ this.t = null
++};
++core.zip_HuftList = function() {
++ this.next = null;
++ this.list = null
++};
++core.RawInflate = function RawInflate() {
++ var zip_WSIZE = 32768;
++ var zip_STORED_BLOCK = 0;
++ var zip_lbits = 9;
++ var zip_dbits = 6;
++ var zip_slide = [];
++ var zip_wp;
++ var zip_fixed_tl = null;
++ var zip_fixed_td;
++ var zip_fixed_bl;
++ var zip_bit_buf;
++ var zip_bit_len;
++ var zip_method;
++ var zip_eof;
++ var zip_copy_leng;
++ var zip_copy_dist;
++ var zip_tl, zip_td;
++ var zip_bl, zip_bd;
++ var zip_inflate_data;
++ var zip_inflate_pos;
++ var zip_MASK_BITS = [0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535];
++ var zip_cplens = [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0];
++ var zip_cplext = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99];
++ var zip_cpdist = [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577];
++ var zip_cpdext = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13];
++ var zip_border = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];
++ function Zip_HuftBuild(b, n, s, d, e, mm) {
++ this.BMAX = 16;
++ this.N_MAX = 288;
++ this.status = 0;
++ this.root = null;
++ this.m = 0;
++ var a, c = new Array(this.BMAX + 1), el, f, g, h, i, j, k, lx = new Array(this.BMAX + 1), p, pidx, q, r = new core.zip_HuftNode, u = new Array(this.BMAX), v = new Array(this.N_MAX), w, x = new Array(this.BMAX + 1), xp, y, z, o, tail;
++ tail = this.root = null;
++ for(i = 0;i < c.length;i++) {
++ c[i] = 0
+ }
- };
- var zip_ct_init = function() {
- var n;
- var bits;
- var length;
- var code;
- var dist;
- if(zip_static_dtree[0].dl !== 0) {
- return
++ for(i = 0;i < lx.length;i++) {
++ lx[i] = 0
+ }
- zip_l_desc.dyn_tree = zip_dyn_ltree;
- zip_l_desc.static_tree = zip_static_ltree;
- zip_l_desc.extra_bits = zip_extra_lbits;
- zip_l_desc.extra_base = zip_LITERALS + 1;
- zip_l_desc.elems = zip_L_CODES;
- zip_l_desc.max_length = zip_MAX_BITS;
- zip_l_desc.max_code = 0;
- zip_d_desc.dyn_tree = zip_dyn_dtree;
- zip_d_desc.static_tree = zip_static_dtree;
- zip_d_desc.extra_bits = zip_extra_dbits;
- zip_d_desc.extra_base = 0;
- zip_d_desc.elems = zip_D_CODES;
- zip_d_desc.max_length = zip_MAX_BITS;
- zip_d_desc.max_code = 0;
- zip_bl_desc.dyn_tree = zip_bl_tree;
- zip_bl_desc.static_tree = null;
- zip_bl_desc.extra_bits = zip_extra_blbits;
- zip_bl_desc.extra_base = 0;
- zip_bl_desc.elems = zip_BL_CODES;
- zip_bl_desc.max_length = zip_MAX_BL_BITS;
- zip_bl_desc.max_code = 0;
- length = 0;
- for(code = 0;code < zip_LENGTH_CODES - 1;code++) {
- zip_base_length[code] = length;
- for(n = 0;n < 1 << zip_extra_lbits[code];n++) {
- zip_length_code[length++] = code
- }
++ for(i = 0;i < u.length;i++) {
++ u[i] = null
+ }
- zip_length_code[length - 1] = code;
- dist = 0;
- for(code = 0;code < 16;code++) {
- zip_base_dist[code] = dist;
- for(n = 0;n < 1 << zip_extra_dbits[code];n++) {
- zip_dist_code[dist++] = code
- }
++ for(i = 0;i < v.length;i++) {
++ v[i] = 0
+ }
- dist >>= 7;
- n = code;
- for(code = n;code < zip_D_CODES;code++) {
- zip_base_dist[code] = dist << 7;
- for(n = 0;n < 1 << zip_extra_dbits[code] - 7;n++) {
- zip_dist_code[256 + dist++] = code
- }
++ for(i = 0;i < x.length;i++) {
++ x[i] = 0
+ }
- for(bits = 0;bits <= zip_MAX_BITS;bits++) {
- zip_bl_count[bits] = 0
++ el = n > 256 ? b[256] : this.BMAX;
++ p = b;
++ pidx = 0;
++ i = n;
++ do {
++ c[p[pidx]]++;
++ pidx++
++ }while(--i > 0);
++ if(c[0] === n) {
++ this.root = null;
++ this.m = 0;
++ this.status = 0;
++ return
+ }
- n = 0;
- while(n <= 143) {
- zip_static_ltree[n++].dl = 8;
- zip_bl_count[8]++
++ for(j = 1;j <= this.BMAX;j++) {
++ if(c[j] !== 0) {
++ break
++ }
+ }
- while(n <= 255) {
- zip_static_ltree[n++].dl = 9;
- zip_bl_count[9]++
++ k = j;
++ if(mm < j) {
++ mm = j
+ }
- while(n <= 279) {
- zip_static_ltree[n++].dl = 7;
- zip_bl_count[7]++
++ for(i = this.BMAX;i !== 0;i--) {
++ if(c[i] !== 0) {
++ break
++ }
+ }
- while(n <= 287) {
- zip_static_ltree[n++].dl = 8;
- zip_bl_count[8]++
++ g = i;
++ if(mm > i) {
++ mm = i
+ }
- zip_gen_codes(zip_static_ltree, zip_L_CODES + 1);
- for(n = 0;n < zip_D_CODES;n++) {
- zip_static_dtree[n].dl = 5;
- zip_static_dtree[n].fc = zip_bi_reverse(n, 5)
++ for(y = 1 << j;j < i;j++, y <<= 1) {
++ y -= c[j];
++ if(y < 0) {
++ this.status = 2;
++ this.m = mm;
++ return
++ }
+ }
- zip_init_block()
- };
- var zip_init_deflate = function() {
- if(zip_eofile) {
++ y -= c[i];
++ if(y < 0) {
++ this.status = 2;
++ this.m = mm;
+ return
+ }
- zip_bi_buf = 0;
- zip_bi_valid = 0;
- zip_ct_init();
- zip_lm_init();
- zip_qhead = null;
- zip_outcnt = 0;
- zip_outoff = 0;
- if(zip_compr_level <= 3) {
- zip_prev_length = zip_MIN_MATCH - 1;
- zip_match_length = 0
- }else {
- zip_match_length = zip_MIN_MATCH - 1;
- zip_match_available = 0
++ c[i] += y;
++ x[1] = j = 0;
++ p = c;
++ pidx = 1;
++ xp = 2;
++ while(--i > 0) {
++ j += p[pidx++];
++ x[xp++] = j
+ }
- zip_complete = false
- };
- var zip_qcopy = function(buff, off, buff_size) {
- var n, i, j, p;
- n = 0;
- while(zip_qhead !== null && n < buff_size) {
- i = buff_size - n;
- if(i > zip_qhead.len) {
- i = zip_qhead.len
- }
- for(j = 0;j < i;j++) {
- buff[off + n + j] = zip_qhead.ptr[zip_qhead.off + j]
- }
- zip_qhead.off += i;
- zip_qhead.len -= i;
- n += i;
- if(zip_qhead.len === 0) {
- p = zip_qhead;
- zip_qhead = zip_qhead.next;
- zip_reuse_queue(p)
- }
- }
- if(n === buff_size) {
- return n
- }
- if(zip_outoff < zip_outcnt) {
- i = buff_size - n;
- if(i > zip_outcnt - zip_outoff) {
- i = zip_outcnt - zip_outoff
- }
- for(j = 0;j < i;j++) {
- buff[off + n + j] = zip_outbuf[zip_outoff + j]
- }
- zip_outoff += i;
- n += i;
- if(zip_outcnt === zip_outoff) {
- zip_outcnt = zip_outoff = 0
- }
- }
- return n
- };
- var zip_deflate_internal = function(buff, off, buff_size) {
- var n;
- if(!zip_initflag) {
- zip_init_deflate();
- zip_initflag = true;
- if(zip_lookahead === 0) {
- zip_complete = true;
- return 0
- }
- }
- n = zip_qcopy(buff, off, buff_size);
- if(n === buff_size) {
- return buff_size
- }
- if(zip_complete) {
- return n
- }
- if(zip_compr_level <= 3) {
- zip_deflate_fast()
- }else {
- zip_deflate_better()
- }
- if(zip_lookahead === 0) {
- if(zip_match_available !== 0) {
- zip_ct_tally(0, zip_window[zip_strstart - 1] & 255)
- }
- zip_flush_block(1);
- zip_complete = true
- }
- return n + zip_qcopy(buff, n + off, buff_size - n)
- };
- var zip_deflate = function(str, level) {
- var i, j;
- zip_deflate_data = str;
- zip_deflate_pos = 0;
- if(String(typeof level) === "undefined") {
- level = zip_DEFAULT_LEVEL
- }
- zip_deflate_start(level);
- var buff = new Array(1024);
- var aout = [], cbuf = [];
- i = zip_deflate_internal(buff, 0, buff.length);
- while(i > 0) {
- cbuf.length = i;
- for(j = 0;j < i;j++) {
- cbuf[j] = String.fromCharCode(buff[j])
- }
- aout[aout.length] = cbuf.join("");
- i = zip_deflate_internal(buff, 0, buff.length)
- }
- zip_deflate_data = "";
- return aout.join("")
- };
- this.deflate = zip_deflate
- };
- core.ByteArray = function ByteArray(data) {
- this.pos = 0;
- this.data = data;
- this.readUInt32LE = function() {
- this.pos += 4;
- var d = this.data, pos = this.pos;
- return d[--pos] << 24 | d[--pos] << 16 | d[--pos] << 8 | d[--pos]
- };
- this.readUInt16LE = function() {
- this.pos += 2;
- var d = this.data, pos = this.pos;
- return d[--pos] << 8 | d[--pos]
- }
- };
- core.ByteArrayWriter = function ByteArrayWriter(encoding) {
- var self = this, length = 0, bufferSize = 1024, data = new Uint8Array(new ArrayBuffer(bufferSize));
- function expand(extraLength) {
- var newData;
- if(extraLength > bufferSize - length) {
- bufferSize = Math.max(2 * bufferSize, length + extraLength);
- newData = new Uint8Array(new ArrayBuffer(bufferSize));
- newData.set(data);
- data = newData
- }
- }
- this.appendByteArrayWriter = function(writer) {
- self.appendByteArray(writer.getByteArray())
- };
- this.appendByteArray = function(array) {
- var l = array.length;
- expand(l);
- data.set(array, length);
- length += l
- };
- this.appendArray = function(array) {
- var l = array.length;
- expand(l);
- data.set(array, length);
- length += l
- };
- this.appendUInt16LE = function(value) {
- self.appendArray([value & 255, value >> 8 & 255])
- };
- this.appendUInt32LE = function(value) {
- self.appendArray([value & 255, value >> 8 & 255, value >> 16 & 255, value >> 24 & 255])
- };
- this.appendString = function(string) {
- self.appendByteArray(runtime.byteArrayFromString(string, encoding))
- };
- this.getLength = function() {
- return length
- };
- this.getByteArray = function() {
- var a = new Uint8Array(new ArrayBuffer(length));
- a.set(data.subarray(0, length));
- return a
- }
- };
- core.RawInflate = function RawInflate() {
- var zip_WSIZE = 32768;
- var zip_STORED_BLOCK = 0;
- var zip_STATIC_TREES = 1;
- var zip_DYN_TREES = 2;
- var zip_lbits = 9;
- var zip_dbits = 6;
- var zip_INBUFSIZ = 32768;
- var zip_INBUF_EXTRA = 64;
- var zip_slide;
- var zip_wp;
- var zip_fixed_tl = null;
- var zip_fixed_td;
- var zip_fixed_bl, fixed_bd;
- var zip_bit_buf;
- var zip_bit_len;
- var zip_method;
- var zip_eof;
- var zip_copy_leng;
- var zip_copy_dist;
- var zip_tl, zip_td;
- var zip_bl, zip_bd;
- var zip_inflate_data;
- var zip_inflate_pos;
- var zip_MASK_BITS = new Array(0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535);
- var zip_cplens = new Array(3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0);
- var zip_cplext = new Array(0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99);
- var zip_cpdist = new Array(1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577);
- var zip_cpdext = new Array(0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13);
- var zip_border = new Array(16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15);
- var zip_HuftList = function() {
- this.next = null;
- this.list = null
- };
- var zip_HuftNode = function() {
- this.e = 0;
- this.b = 0;
- this.n = 0;
- this.t = null
- };
- var zip_HuftBuild = function(b, n, s, d, e, mm) {
- this.BMAX = 16;
- this.N_MAX = 288;
- this.status = 0;
- this.root = null;
- this.m = 0;
- var a;
- var c = new Array(this.BMAX + 1);
- var el;
- var f;
- var g;
- var h;
- var i;
- var j;
- var k;
- var lx = new Array(this.BMAX + 1);
- var p;
- var pidx;
- var q;
- var r = new zip_HuftNode;
- var u = new Array(this.BMAX);
- var v = new Array(this.N_MAX);
- var w;
- var x = new Array(this.BMAX + 1);
- var xp;
- var y;
- var z;
- var o;
- var tail;
- tail = this.root = null;
- for(i = 0;i < c.length;i++) {
- c[i] = 0
- }
- for(i = 0;i < lx.length;i++) {
- lx[i] = 0
- }
- for(i = 0;i < u.length;i++) {
- u[i] = null
- }
- for(i = 0;i < v.length;i++) {
- v[i] = 0
- }
- for(i = 0;i < x.length;i++) {
- x[i] = 0
- }
- el = n > 256 ? b[256] : this.BMAX;
- p = b;
- pidx = 0;
- i = n;
- do {
- c[p[pidx]]++;
- pidx++
- }while(--i > 0);
- if(c[0] == n) {
- this.root = null;
- this.m = 0;
- this.status = 0;
- return
- }
- for(j = 1;j <= this.BMAX;j++) {
- if(c[j] != 0) {
- break
- }
- }
- k = j;
- if(mm < j) {
- mm = j
- }
- for(i = this.BMAX;i != 0;i--) {
- if(c[i] != 0) {
- break
- }
- }
- g = i;
- if(mm > i) {
- mm = i
- }
- for(y = 1 << j;j < i;j++, y <<= 1) {
- if((y -= c[j]) < 0) {
- this.status = 2;
- this.m = mm;
- return
- }
- }
- if((y -= c[i]) < 0) {
- this.status = 2;
- this.m = mm;
- return
- }
- c[i] += y;
- x[1] = j = 0;
- p = c;
- pidx = 1;
- xp = 2;
- while(--i > 0) {
- x[xp++] = j += p[pidx++]
- }
- p = b;
- pidx = 0;
- i = 0;
- do {
- if((j = p[pidx++]) != 0) {
- v[x[j]++] = i
++ p = b;
++ pidx = 0;
++ i = 0;
++ do {
++ j = p[pidx++];
++ if(j !== 0) {
++ v[x[j]++] = i
+ }
+ }while(++i < n);
+ n = x[g];
+ x[0] = i = 0;
+ p = v;
+ pidx = 0;
+ h = -1;
+ w = lx[0] = 0;
+ q = null;
+ z = 0;
- for(;k <= g;k++) {
++ k -= 1;
++ for(k += 1;k <= g;k++) {
+ a = c[k];
+ while(a-- > 0) {
+ while(k > w + lx[1 + h]) {
+ w += lx[1 + h];
+ h++;
- z = (z = g - w) > mm ? mm : z;
- if((f = 1 << (j = k - w)) > a + 1) {
++ z = g - w;
++ z = z > mm ? mm : z;
++ j = k - w;
++ f = 1 << j;
++ if(f > a + 1) {
+ f -= a + 1;
+ xp = k;
+ while(++j < z) {
- if((f <<= 1) <= c[++xp]) {
++ f <<= 1;
++ if(f <= c[++xp]) {
+ break
+ }
+ f -= c[xp]
+ }
+ }
+ if(w + j > el && w < el) {
+ j = el - w
+ }
+ z = 1 << j;
+ lx[1 + h] = j;
+ q = new Array(z);
+ for(o = 0;o < z;o++) {
- q[o] = new zip_HuftNode
++ q[o] = new core.zip_HuftNode
+ }
- if(tail == null) {
- tail = this.root = new zip_HuftList
++ if(tail === null) {
++ tail = this.root = new core.zip_HuftList
+ }else {
- tail = tail.next = new zip_HuftList
++ tail = tail.next = new core.zip_HuftList
+ }
+ tail.next = null;
+ tail.list = q;
+ u[h] = q;
+ if(h > 0) {
+ x[h] = i;
+ r.b = lx[h];
+ r.e = 16 + j;
+ r.t = q;
+ j = (i & (1 << w) - 1) >> w - lx[h];
+ u[h - 1][j].e = r.e;
+ u[h - 1][j].b = r.b;
- u[h - 1][j].n = r.n;
++ u[h - 1][j].n = (r).n;
+ u[h - 1][j].t = r.t
+ }
+ }
+ r.b = k - w;
+ if(pidx >= n) {
+ r.e = 99
+ }else {
+ if(p[pidx] < s) {
+ r.e = p[pidx] < 256 ? 16 : 15;
+ r.n = p[pidx++]
+ }else {
+ r.e = e[p[pidx] - s];
+ r.n = d[p[pidx++] - s]
+ }
+ }
+ f = 1 << k - w;
+ for(j = i >> w;j < z;j += f) {
+ q[j].e = r.e;
+ q[j].b = r.b;
- q[j].n = r.n;
++ q[j].n = (r).n;
+ q[j].t = r.t
+ }
- for(j = 1 << k - 1;(i & j) != 0;j >>= 1) {
++ for(j = 1 << k - 1;(i & j) !== 0;j >>= 1) {
+ i ^= j
+ }
+ i ^= j;
- while((i & (1 << w) - 1) != x[h]) {
++ while((i & (1 << w) - 1) !== x[h]) {
+ w -= lx[h];
+ h--
+ }
+ }
+ }
+ this.m = lx[1];
- this.status = y != 0 && g != 1 ? 1 : 0
- };
- var zip_GET_BYTE = function() {
- if(zip_inflate_data.length == zip_inflate_pos) {
++ this.status = y !== 0 && g !== 1 ? 1 : 0
++ }
++ function zip_GET_BYTE() {
++ if(zip_inflate_data.length === zip_inflate_pos) {
+ return-1
+ }
+ return zip_inflate_data[zip_inflate_pos++]
- };
- var zip_NEEDBITS = function(n) {
++ }
++ function zip_NEEDBITS(n) {
+ while(zip_bit_len < n) {
+ zip_bit_buf |= zip_GET_BYTE() << zip_bit_len;
+ zip_bit_len += 8
+ }
- };
- var zip_GETBITS = function(n) {
++ }
++ function zip_GETBITS(n) {
+ return zip_bit_buf & zip_MASK_BITS[n]
- };
- var zip_DUMPBITS = function(n) {
++ }
++ function zip_DUMPBITS(n) {
+ zip_bit_buf >>= n;
+ zip_bit_len -= n
- };
- var zip_inflate_codes = function(buff, off, size) {
- var e;
- var t;
- var n;
- if(size == 0) {
++ }
++ function zip_inflate_codes(buff, off, size) {
++ var e, t, n;
++ if(size === 0) {
+ return 0
+ }
+ n = 0;
+ for(;;) {
+ zip_NEEDBITS(zip_bl);
+ t = zip_tl.list[zip_GETBITS(zip_bl)];
+ e = t.e;
+ while(e > 16) {
- if(e == 99) {
++ if(e === 99) {
+ return-1
+ }
+ zip_DUMPBITS(t.b);
+ e -= 16;
+ zip_NEEDBITS(e);
+ t = t.t[zip_GETBITS(e)];
+ e = t.e
+ }
+ zip_DUMPBITS(t.b);
- if(e == 16) {
++ if(e === 16) {
+ zip_wp &= zip_WSIZE - 1;
+ buff[off + n++] = zip_slide[zip_wp++] = t.n;
- if(n == size) {
++ if(n === size) {
+ return size
+ }
- continue
- }
- if(e == 15) {
- break
- }
- zip_NEEDBITS(e);
- zip_copy_leng = t.n + zip_GETBITS(e);
- zip_DUMPBITS(e);
- zip_NEEDBITS(zip_bd);
- t = zip_td.list[zip_GETBITS(zip_bd)];
- e = t.e;
- while(e > 16) {
- if(e == 99) {
- return-1
++ }else {
++ if(e === 15) {
++ break
+ }
- zip_DUMPBITS(t.b);
- e -= 16;
+ zip_NEEDBITS(e);
- t = t.t[zip_GETBITS(e)];
- e = t.e
- }
- zip_DUMPBITS(t.b);
- zip_NEEDBITS(e);
- zip_copy_dist = zip_wp - t.n - zip_GETBITS(e);
- zip_DUMPBITS(e);
- while(zip_copy_leng > 0 && n < size) {
- zip_copy_leng--;
- zip_copy_dist &= zip_WSIZE - 1;
- zip_wp &= zip_WSIZE - 1;
- buff[off + n++] = zip_slide[zip_wp++] = zip_slide[zip_copy_dist++]
- }
- if(n == size) {
- return size
++ zip_copy_leng = t.n + zip_GETBITS(e);
++ zip_DUMPBITS(e);
++ zip_NEEDBITS(zip_bd);
++ t = zip_td.list[zip_GETBITS(zip_bd)];
++ e = t.e;
++ while(e > 16) {
++ if(e === 99) {
++ return-1
++ }
++ zip_DUMPBITS(t.b);
++ e -= 16;
++ zip_NEEDBITS(e);
++ t = t.t[zip_GETBITS(e)];
++ e = t.e
++ }
++ zip_DUMPBITS(t.b);
++ zip_NEEDBITS(e);
++ zip_copy_dist = zip_wp - t.n - zip_GETBITS(e);
++ zip_DUMPBITS(e);
++ while(zip_copy_leng > 0 && n < size) {
++ zip_copy_leng--;
++ zip_copy_dist &= zip_WSIZE - 1;
++ zip_wp &= zip_WSIZE - 1;
++ buff[off + n++] = zip_slide[zip_wp++] = zip_slide[zip_copy_dist++]
++ }
++ if(n === size) {
++ return size
++ }
+ }
+ }
+ zip_method = -1;
+ return n
- };
- var zip_inflate_stored = function(buff, off, size) {
++ }
++ function zip_inflate_stored(buff, off, size) {
+ var n;
+ n = zip_bit_len & 7;
+ zip_DUMPBITS(n);
+ zip_NEEDBITS(16);
+ n = zip_GETBITS(16);
+ zip_DUMPBITS(16);
+ zip_NEEDBITS(16);
- if(n != (~zip_bit_buf & 65535)) {
++ if(n !== (~zip_bit_buf & 65535)) {
+ return-1
+ }
+ zip_DUMPBITS(16);
+ zip_copy_leng = n;
+ n = 0;
+ while(zip_copy_leng > 0 && n < size) {
+ zip_copy_leng--;
+ zip_wp &= zip_WSIZE - 1;
+ zip_NEEDBITS(8);
+ buff[off + n++] = zip_slide[zip_wp++] = zip_GETBITS(8);
+ zip_DUMPBITS(8)
+ }
- if(zip_copy_leng == 0) {
++ if(zip_copy_leng === 0) {
+ zip_method = -1
+ }
+ return n
- };
++ }
+ var zip_fixed_bd;
- var zip_inflate_fixed = function(buff, off, size) {
- if(zip_fixed_tl == null) {
++ function zip_inflate_fixed(buff, off, size) {
++ if(zip_fixed_tl === null) {
+ var i;
+ var l = new Array(288);
+ var h;
+ for(i = 0;i < 144;i++) {
+ l[i] = 8
+ }
- for(;i < 256;i++) {
++ for(i = 144;i < 256;i++) {
+ l[i] = 9
+ }
- for(;i < 280;i++) {
++ for(i = 256;i < 280;i++) {
+ l[i] = 7
+ }
- for(;i < 288;i++) {
++ for(i = 280;i < 288;i++) {
+ l[i] = 8
+ }
+ zip_fixed_bl = 7;
- h = new zip_HuftBuild(l, 288, 257, zip_cplens, zip_cplext, zip_fixed_bl);
- if(h.status != 0) {
++ h = new Zip_HuftBuild(l, 288, 257, zip_cplens, zip_cplext, zip_fixed_bl);
++ if(h.status !== 0) {
+ alert("HufBuild error: " + h.status);
+ return-1
+ }
+ zip_fixed_tl = h.root;
+ zip_fixed_bl = h.m;
+ for(i = 0;i < 30;i++) {
+ l[i] = 5
+ }
+ zip_fixed_bd = 5;
- h = new zip_HuftBuild(l, 30, 0, zip_cpdist, zip_cpdext, zip_fixed_bd);
++ h = new Zip_HuftBuild(l, 30, 0, zip_cpdist, zip_cpdext, zip_fixed_bd);
+ if(h.status > 1) {
+ zip_fixed_tl = null;
+ alert("HufBuild error: " + h.status);
+ return-1
+ }
+ zip_fixed_td = h.root;
+ zip_fixed_bd = h.m
+ }
+ zip_tl = zip_fixed_tl;
+ zip_td = zip_fixed_td;
+ zip_bl = zip_fixed_bl;
+ zip_bd = zip_fixed_bd;
+ return zip_inflate_codes(buff, off, size)
- };
- var zip_inflate_dynamic = function(buff, off, size) {
++ }
++ function zip_inflate_dynamic(buff, off, size) {
+ var i;
+ var j;
+ var l;
+ var n;
+ var t;
+ var nb;
+ var nl;
+ var nd;
+ var ll = new Array(286 + 30);
+ var h;
+ for(i = 0;i < ll.length;i++) {
+ ll[i] = 0
+ }
+ zip_NEEDBITS(5);
+ nl = 257 + zip_GETBITS(5);
+ zip_DUMPBITS(5);
+ zip_NEEDBITS(5);
+ nd = 1 + zip_GETBITS(5);
+ zip_DUMPBITS(5);
+ zip_NEEDBITS(4);
+ nb = 4 + zip_GETBITS(4);
+ zip_DUMPBITS(4);
+ if(nl > 286 || nd > 30) {
+ return-1
+ }
+ for(j = 0;j < nb;j++) {
+ zip_NEEDBITS(3);
+ ll[zip_border[j]] = zip_GETBITS(3);
+ zip_DUMPBITS(3)
+ }
- for(;j < 19;j++) {
++ for(j = nb;j < 19;j++) {
+ ll[zip_border[j]] = 0
+ }
+ zip_bl = 7;
- h = new zip_HuftBuild(ll, 19, 19, null, null, zip_bl);
- if(h.status != 0) {
++ h = new Zip_HuftBuild(ll, 19, 19, null, null, zip_bl);
++ if(h.status !== 0) {
+ return-1
+ }
+ zip_tl = h.root;
+ zip_bl = h.m;
+ n = nl + nd;
+ i = l = 0;
+ while(i < n) {
+ zip_NEEDBITS(zip_bl);
+ t = zip_tl.list[zip_GETBITS(zip_bl)];
+ j = t.b;
+ zip_DUMPBITS(j);
+ j = t.n;
+ if(j < 16) {
+ ll[i++] = l = j
+ }else {
- if(j == 16) {
++ if(j === 16) {
+ zip_NEEDBITS(2);
+ j = 3 + zip_GETBITS(2);
+ zip_DUMPBITS(2);
+ if(i + j > n) {
+ return-1
+ }
+ while(j-- > 0) {
+ ll[i++] = l
+ }
+ }else {
- if(j == 17) {
++ if(j === 17) {
+ zip_NEEDBITS(3);
+ j = 3 + zip_GETBITS(3);
+ zip_DUMPBITS(3);
+ if(i + j > n) {
+ return-1
+ }
+ while(j-- > 0) {
+ ll[i++] = 0
+ }
+ l = 0
+ }else {
+ zip_NEEDBITS(7);
+ j = 11 + zip_GETBITS(7);
+ zip_DUMPBITS(7);
+ if(i + j > n) {
+ return-1
+ }
+ while(j-- > 0) {
+ ll[i++] = 0
+ }
+ l = 0
+ }
+ }
+ }
+ }
+ zip_bl = zip_lbits;
- h = new zip_HuftBuild(ll, nl, 257, zip_cplens, zip_cplext, zip_bl);
- if(zip_bl == 0) {
++ h = new Zip_HuftBuild(ll, nl, 257, zip_cplens, zip_cplext, zip_bl);
++ if(zip_bl === 0) {
+ h.status = 1
+ }
- if(h.status != 0) {
++ if(h.status !== 0) {
+ return-1
+ }
+ zip_tl = h.root;
+ zip_bl = h.m;
+ for(i = 0;i < nd;i++) {
+ ll[i] = ll[i + nl]
+ }
+ zip_bd = zip_dbits;
- h = new zip_HuftBuild(ll, nd, 0, zip_cpdist, zip_cpdext, zip_bd);
++ h = new Zip_HuftBuild(ll, nd, 0, zip_cpdist, zip_cpdext, zip_bd);
+ zip_td = h.root;
+ zip_bd = h.m;
- if(zip_bd == 0 && nl > 257) {
++ if(zip_bd === 0 && nl > 257) {
+ return-1
+ }
- if(h.status != 0) {
++ if(h.status !== 0) {
+ return-1
+ }
+ return zip_inflate_codes(buff, off, size)
- };
- var zip_inflate_start = function() {
- var i;
- if(zip_slide == null) {
- zip_slide = new Array(2 * zip_WSIZE)
- }
++ }
++ function zip_inflate_start() {
++ zip_slide.length = 2 * zip_WSIZE;
+ zip_wp = 0;
+ zip_bit_buf = 0;
+ zip_bit_len = 0;
+ zip_method = -1;
+ zip_eof = false;
+ zip_copy_leng = zip_copy_dist = 0;
+ zip_tl = null
- };
- var zip_inflate_internal = function(buff, off, size) {
- var n, i;
- n = 0;
++ }
++ function zip_inflate_internal(buff, off, size) {
++ var n = 0, i;
+ while(n < size) {
- if(zip_eof && zip_method == -1) {
++ if(zip_eof && zip_method === -1) {
+ return n
+ }
+ if(zip_copy_leng > 0) {
- if(zip_method != zip_STORED_BLOCK) {
++ if(zip_method !== zip_STORED_BLOCK) {
+ while(zip_copy_leng > 0 && n < size) {
+ zip_copy_leng--;
+ zip_copy_dist &= zip_WSIZE - 1;
+ zip_wp &= zip_WSIZE - 1;
- buff[off + n++] = zip_slide[zip_wp++] = zip_slide[zip_copy_dist++]
++ buff[off + n] = zip_slide[zip_wp] = zip_slide[zip_copy_dist];
++ n += 1;
++ zip_wp += 1;
++ zip_copy_dist += 1
+ }
+ }else {
+ while(zip_copy_leng > 0 && n < size) {
- zip_copy_leng--;
++ zip_copy_leng -= 1;
+ zip_wp &= zip_WSIZE - 1;
+ zip_NEEDBITS(8);
- buff[off + n++] = zip_slide[zip_wp++] = zip_GETBITS(8);
++ buff[off + n] = zip_slide[zip_wp] = zip_GETBITS(8);
++ n += 1;
++ zip_wp += 1;
+ zip_DUMPBITS(8)
+ }
- if(zip_copy_leng == 0) {
++ if(zip_copy_leng === 0) {
+ zip_method = -1
+ }
+ }
- if(n == size) {
++ if(n === size) {
+ return n
+ }
+ }
- if(zip_method == -1) {
++ if(zip_method === -1) {
+ if(zip_eof) {
+ break
+ }
+ zip_NEEDBITS(1);
- if(zip_GETBITS(1) != 0) {
++ if(zip_GETBITS(1) !== 0) {
+ zip_eof = true
+ }
+ zip_DUMPBITS(1);
+ zip_NEEDBITS(2);
+ zip_method = zip_GETBITS(2);
+ zip_DUMPBITS(2);
+ zip_tl = null;
+ zip_copy_leng = 0
+ }
+ switch(zip_method) {
+ case 0:
+ i = zip_inflate_stored(buff, off + n, size - n);
+ break;
+ case 1:
- if(zip_tl != null) {
++ if(zip_tl !== null) {
+ i = zip_inflate_codes(buff, off + n, size - n)
+ }else {
+ i = zip_inflate_fixed(buff, off + n, size - n)
+ }
+ break;
+ case 2:
- if(zip_tl != null) {
++ if(zip_tl !== null) {
+ i = zip_inflate_codes(buff, off + n, size - n)
+ }else {
+ i = zip_inflate_dynamic(buff, off + n, size - n)
+ }
+ break;
+ default:
+ i = -1;
+ break
+ }
- if(i == -1) {
++ if(i === -1) {
+ if(zip_eof) {
+ return 0
+ }
+ return-1
+ }
+ n += i
+ }
+ return n
- };
- var zip_inflate = function(data, size) {
- var i, j;
++ }
++ function zip_inflate(data, size) {
+ zip_inflate_start();
+ zip_inflate_data = data;
+ zip_inflate_pos = 0;
+ var buff = new Uint8Array(new ArrayBuffer(size));
+ zip_inflate_internal(buff, 0, size);
- zip_inflate_data = null;
++ zip_inflate_data = new Uint8Array(new ArrayBuffer(0));
+ return buff
- };
++ }
+ this.inflate = zip_inflate
+};
- /*
-
- Copyright (C) 2012 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- core.LoopWatchDog = function LoopWatchDog(timeout, maxChecks) {
- var startTime = Date.now(), checks = 0;
- function check() {
- var t;
- if(timeout) {
- t = Date.now();
- if(t - startTime > timeout) {
- runtime.log("alert", "watchdog timeout");
- throw"timeout!";
++core.ScheduledTask = function ScheduledTask(fn, delay) {
++ var timeoutId, scheduled = false, args = [];
++ function cancel() {
++ if(scheduled) {
++ runtime.clearTimeout(timeoutId);
++ scheduled = false
++ }
++ }
++ function execute() {
++ cancel();
++ fn.apply(undefined, args);
++ args = null
++ }
++ this.trigger = function() {
++ args = Array.prototype.slice.call(arguments);
++ if(!scheduled) {
++ scheduled = true;
++ timeoutId = runtime.setTimeout(execute, delay)
++ }
++ };
++ this.triggerImmediate = function() {
++ args = Array.prototype.slice.call(arguments);
++ execute()
++ };
++ this.processRequests = function() {
++ if(scheduled) {
++ execute()
++ }
++ };
++ this.cancel = cancel;
++ this.destroy = function(callback) {
++ cancel();
++ callback()
++ }
++};
++core.NamedFunction;
++core.NamedAsyncFunction;
++core.UnitTest = function UnitTest() {
++};
++core.UnitTest.prototype.setUp = function() {
++};
++core.UnitTest.prototype.tearDown = function() {
++};
++core.UnitTest.prototype.description = function() {
++};
++core.UnitTest.prototype.tests = function() {
++};
++core.UnitTest.prototype.asyncTests = function() {
++};
++core.UnitTest.provideTestAreaDiv = function() {
++ var maindoc = runtime.getWindow().document, testarea = maindoc.getElementById("testarea");
++ runtime.assert(!testarea, 'Unclean test environment, found a div with id "testarea".');
++ testarea = maindoc.createElement("div");
++ testarea.setAttribute("id", "testarea");
++ maindoc.body.appendChild(testarea);
++ return(testarea)
++};
++core.UnitTest.cleanupTestAreaDiv = function() {
++ var maindoc = runtime.getWindow().document, testarea = maindoc.getElementById("testarea");
++ runtime.assert(!!testarea && testarea.parentNode === maindoc.body, 'Test environment broken, found no div with id "testarea" below body.');
++ maindoc.body.removeChild(testarea)
++};
++core.UnitTest.createOdtDocument = function(xml, namespaceMap) {
++ var xmlDoc = "<?xml version='1.0' encoding='UTF-8'?>";
++ xmlDoc += "<office:document";
++ Object.keys(namespaceMap).forEach(function(key) {
++ xmlDoc += " xmlns:" + key + '="' + namespaceMap[key] + '"'
++ });
++ xmlDoc += ">";
++ xmlDoc += xml;
++ xmlDoc += "</office:document>";
++ return runtime.parseXML(xmlDoc)
++};
++core.UnitTestRunner = function UnitTestRunner() {
++ var failedTests = 0, areObjectsEqual;
++ function debug(msg) {
++ runtime.log(msg)
++ }
++ function testFailed(msg) {
++ failedTests += 1;
++ runtime.log("fail", msg)
++ }
++ function testPassed(msg) {
++ runtime.log("pass", msg)
++ }
++ function areArraysEqual(a, b) {
++ var i;
++ try {
++ if(a.length !== b.length) {
++ testFailed("array of length " + a.length + " should be " + b.length + " long");
++ return false
++ }
++ for(i = 0;i < a.length;i += 1) {
++ if(a[i] !== b[i]) {
++ testFailed(a[i] + " should be " + b[i] + " at array index " + i);
++ return false
++ }
+ }
++ }catch(ex) {
++ return false
+ }
- if(maxChecks > 0) {
- checks += 1;
- if(checks > maxChecks) {
- runtime.log("alert", "watchdog loop overflow");
- throw"loop overflow";
++ return true
++ }
++ function areAttributesEqual(a, b, skipReverseCheck) {
++ var aatts = a.attributes, n = aatts.length, i, att, v;
++ for(i = 0;i < n;i += 1) {
++ att = (aatts.item(i));
++ if(att.prefix !== "xmlns" && att.namespaceURI !== "urn:webodf:names:steps") {
++ v = b.getAttributeNS(att.namespaceURI, att.localName);
++ if(!b.hasAttributeNS(att.namespaceURI, att.localName)) {
++ testFailed("Attribute " + att.localName + " with value " + att.value + " was not present");
++ return false
++ }
++ if(v !== att.value) {
++ testFailed("Attribute " + att.localName + " was " + v + " should be " + att.value);
++ return false
++ }
+ }
+ }
++ return skipReverseCheck ? true : areAttributesEqual(b, a, true)
+ }
- this.check = check
- };
- core.Utils = function Utils() {
- function hashString(value) {
- var hash = 0, i, l;
- for(i = 0, l = value.length;i < l;i += 1) {
- hash = (hash << 5) - hash + value.charCodeAt(i);
- hash |= 0
++ function areNodesEqual(a, b) {
++ var an, bn, atype = a.nodeType, btype = b.nodeType;
++ if(atype !== btype) {
++ testFailed("Nodetype '" + atype + "' should be '" + btype + "'");
++ return false
+ }
- return hash
++ if(atype === Node.TEXT_NODE) {
++ if((a).data === (b).data) {
++ return true
++ }
++ testFailed("Textnode data '" + (a).data + "' should be '" + (b).data + "'");
++ return false
++ }
++ runtime.assert(atype === Node.ELEMENT_NODE, "Only textnodes and elements supported.");
++ if(a.namespaceURI !== b.namespaceURI) {
++ testFailed("namespace '" + a.namespaceURI + "' should be '" + b.namespaceURI + "'");
++ return false
++ }
++ if(a.localName !== b.localName) {
++ testFailed("localName '" + a.localName + "' should be '" + b.localName + "'");
++ return false
++ }
++ if(!areAttributesEqual((a), (b), false)) {
++ return false
++ }
++ an = a.firstChild;
++ bn = b.firstChild;
++ while(an) {
++ if(!bn) {
++ testFailed("Nodetype '" + an.nodeType + "' is unexpected here.");
++ return false
++ }
++ if(!areNodesEqual(an, bn)) {
++ return false
++ }
++ an = an.nextSibling;
++ bn = bn.nextSibling
++ }
++ if(bn) {
++ testFailed("Nodetype '" + bn.nodeType + "' is missing here.");
++ return false
++ }
++ return true
+ }
- this.hashString = hashString;
- function mergeObjects(destination, source) {
- if(source && Array.isArray(source)) {
- destination = (destination || []).concat(source.map(function(obj) {
- return mergeObjects({}, obj)
- }))
- }else {
- if(source && typeof source === "object") {
- destination = destination || {};
- Object.keys(source).forEach(function(p) {
- destination[p] = mergeObjects(destination[p], source[p])
- })
- }else {
- destination = source
++ function isResultCorrect(actual, expected) {
++ if(expected === 0) {
++ return actual === expected && 1 / actual === 1 / expected
++ }
++ if(actual === expected) {
++ return true
++ }
++ if(typeof expected === "number" && isNaN(expected)) {
++ return typeof actual === "number" && isNaN(actual)
++ }
++ if(Object.prototype.toString.call(expected) === Object.prototype.toString.call([])) {
++ return areArraysEqual((actual), (expected))
++ }
++ if(typeof expected === "object" && typeof actual === "object") {
++ if((expected).constructor === Element || (expected).constructor === Node) {
++ return areNodesEqual((expected), (actual))
+ }
++ return areObjectsEqual((expected), (actual))
+ }
- return destination
++ return false
+ }
- this.mergeObjects = mergeObjects
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- (function() {
- var browserQuirks;
- function getBrowserQuirks() {
- var range, directBoundingRect, rangeBoundingRect, testContainer, testElement, detectedQuirks, window, document;
- if(browserQuirks === undefined) {
- window = runtime.getWindow();
- document = window && window.document;
- browserQuirks = {rangeBCRIgnoresElementBCR:false, unscaledRangeClientRects:false};
- if(document) {
- testContainer = document.createElement("div");
- testContainer.style.position = "absolute";
- testContainer.style.left = "-99999px";
- testContainer.style.transform = "scale(2)";
- testContainer.style["-webkit-transform"] = "scale(2)";
- testElement = document.createElement("div");
- testContainer.appendChild(testElement);
- document.body.appendChild(testContainer);
- range = document.createRange();
- range.selectNode(testElement);
- browserQuirks.rangeBCRIgnoresElementBCR = range.getClientRects().length === 0;
- testElement.appendChild(document.createTextNode("Rect transform test"));
- directBoundingRect = testElement.getBoundingClientRect();
- rangeBoundingRect = range.getBoundingClientRect();
- browserQuirks.unscaledRangeClientRects = Math.abs(directBoundingRect.height - rangeBoundingRect.height) > 2;
- range.detach();
- document.body.removeChild(testContainer);
- detectedQuirks = Object.keys(browserQuirks).map(function(quirk) {
- return quirk + ":" + String(browserQuirks[quirk])
- }).join(", ");
- runtime.log("Detected browser quirks - " + detectedQuirks)
- }
++ function stringify(v) {
++ if(v === 0 && 1 / v < 0) {
++ return"-0"
+ }
- return browserQuirks
++ return String(v)
+ }
- core.DomUtils = function DomUtils() {
- var sharedRange = null;
- function getSharedRange(doc) {
- var range;
- if(sharedRange) {
- range = sharedRange
++ function shouldBe(t, a, b) {
++ if(typeof a !== "string" || typeof b !== "string") {
++ debug("WARN: shouldBe() expects string arguments")
++ }
++ var exception, av, bv;
++ try {
++ av = eval(a)
++ }catch(e) {
++ exception = e
++ }
++ bv = eval(b);
++ if(exception) {
++ testFailed(a + " should be " + bv + ". Threw exception " + exception)
++ }else {
++ if(isResultCorrect(av, bv)) {
++ testPassed(a + " is " + b)
+ }else {
- sharedRange = range = (doc.createRange())
++ if(String(typeof av) === String(typeof bv)) {
++ testFailed(a + " should be " + bv + ". Was " + stringify(av) + ".")
++ }else {
++ testFailed(a + " should be " + bv + " (of type " + typeof bv + "). Was " + av + " (of type " + typeof av + ").")
++ }
+ }
- return range
+ }
- function findStablePoint(container, offset) {
- var c = container;
- if(offset < c.childNodes.length) {
- c = c.childNodes.item(offset);
- offset = 0;
- while(c.firstChild) {
- c = c.firstChild
- }
++ }
++ function shouldBeNonNull(t, a) {
++ var exception, av;
++ try {
++ av = eval(a)
++ }catch(e) {
++ exception = e
++ }
++ if(exception) {
++ testFailed(a + " should be non-null. Threw exception " + exception)
++ }else {
++ if(av !== null) {
++ testPassed(a + " is non-null.")
+ }else {
- while(c.lastChild) {
- c = c.lastChild;
- offset = c.nodeType === Node.TEXT_NODE ? c.textContent.length : c.childNodes.length
- }
++ testFailed(a + " should be non-null. Was " + av)
+ }
- return{container:c, offset:offset}
+ }
- function splitBoundaries(range) {
- var modifiedNodes = [], end, splitStart, node, text;
- if(range.startContainer.nodeType === Node.TEXT_NODE || range.endContainer.nodeType === Node.TEXT_NODE) {
- end = range.endContainer && findStablePoint(range.endContainer, range.endOffset);
- range.setEnd(end.container, end.offset);
- node = range.endContainer;
- if(range.endOffset !== 0 && node.nodeType === Node.TEXT_NODE) {
- text = (node);
- if(range.endOffset !== text.length) {
- modifiedNodes.push(text.splitText(range.endOffset));
- modifiedNodes.push(text)
- }
- }
- node = range.startContainer;
- if(range.startOffset !== 0 && node.nodeType === Node.TEXT_NODE) {
- text = (node);
- if(range.startOffset !== text.length) {
- splitStart = text.splitText(range.startOffset);
- modifiedNodes.push(text);
- modifiedNodes.push(splitStart);
- range.setStart(splitStart, 0)
- }
- }
++ }
++ function shouldBeNull(t, a) {
++ shouldBe(t, a, "null")
++ }
++ areObjectsEqual = function(a, b) {
++ var akeys = Object.keys(a), bkeys = Object.keys(b);
++ akeys.sort();
++ bkeys.sort();
++ return areArraysEqual(akeys, bkeys) && Object.keys(a).every(function(key) {
++ var aval = a[key], bval = b[key];
++ if(!isResultCorrect(aval, bval)) {
++ testFailed(aval + " should be " + bval + " for key " + key);
++ return false
+ }
- return modifiedNodes
++ return true
++ })
++ };
++ this.areNodesEqual = areNodesEqual;
++ this.shouldBeNull = shouldBeNull;
++ this.shouldBeNonNull = shouldBeNonNull;
++ this.shouldBe = shouldBe;
++ this.countFailedTests = function() {
++ return failedTests
++ };
++ this.name = function(functions) {
++ var i, fname, nf = [], l = functions.length;
++ nf.length = l;
++ for(i = 0;i < l;i += 1) {
++ fname = Runtime.getFunctionName(functions[i]) || "";
++ if(fname === "") {
++ throw"Found a function without a name.";
++ }
++ nf[i] = {f:functions[i], name:fname}
+ }
- this.splitBoundaries = splitBoundaries;
- function containsRange(container, insideRange) {
- return container.compareBoundaryPoints(Range.START_TO_START, insideRange) <= 0 && container.compareBoundaryPoints(Range.END_TO_END, insideRange) >= 0
++ return nf
++ }
++};
++core.UnitTester = function UnitTester() {
++ var failedTests = 0, results = {};
++ function link(text, code) {
++ return"<span style='color:blue;cursor:pointer' onclick='" + code + "'>" + text + "</span>"
++ }
++ this.runTests = function(TestClass, callback, testNames) {
++ var testName = Runtime.getFunctionName(TestClass) || "", tname, runner = new core.UnitTestRunner, test = new TestClass(runner), testResults = {}, i, t, tests, lastFailCount, inBrowser = runtime.type() === "BrowserRuntime";
++ if(results.hasOwnProperty(testName)) {
++ runtime.log("Test " + testName + " has already run.");
++ return
+ }
- this.containsRange = containsRange;
- function rangesIntersect(range1, range2) {
- return range1.compareBoundaryPoints(Range.END_TO_START, range2) <= 0 && range1.compareBoundaryPoints(Range.START_TO_END, range2) >= 0
++ if(inBrowser) {
++ runtime.log("<span>Running " + link(testName, 'runSuite("' + testName + '");') + ": " + test.description() + "</span>")
++ }else {
++ runtime.log("Running " + testName + ": " + test.description)
+ }
- this.rangesIntersect = rangesIntersect;
- function getNodesInRange(range, nodeFilter) {
- var document = range.startContainer.ownerDocument, elements = [], rangeRoot = range.commonAncestorContainer, root = (rangeRoot.nodeType === Node.TEXT_NODE ? rangeRoot.parentNode : rangeRoot), n, filterResult, treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_ALL, nodeFilter, false);
- treeWalker.currentNode = range.startContainer;
- n = range.startContainer;
- while(n) {
- filterResult = nodeFilter(n);
- if(filterResult === NodeFilter.FILTER_ACCEPT) {
- elements.push(n)
- }else {
- if(filterResult === NodeFilter.FILTER_REJECT) {
- break
- }
- }
- n = n.parentNode
- }
- elements.reverse();
- n = treeWalker.nextNode();
- while(n) {
- elements.push(n);
- n = treeWalker.nextNode()
++ tests = test.tests();
++ for(i = 0;i < tests.length;i += 1) {
++ t = tests[i].f;
++ tname = tests[i].name;
++ if(testNames.length && testNames.indexOf(tname) === -1) {
++ continue
+ }
- return elements
- }
- this.getNodesInRange = getNodesInRange;
- function mergeTextNodes(node, nextNode) {
- var mergedNode = null, text, nextText;
- if(node.nodeType === Node.TEXT_NODE) {
- text = (node);
- if(text.length === 0) {
- text.parentNode.removeChild(text);
- if(nextNode.nodeType === Node.TEXT_NODE) {
- mergedNode = nextNode
- }
- }else {
- if(nextNode.nodeType === Node.TEXT_NODE) {
- nextText = (nextNode);
- text.appendData(nextText.data);
- nextNode.parentNode.removeChild(nextNode)
- }
- mergedNode = node
- }
++ if(inBrowser) {
++ runtime.log("<span>Running " + link(tname, 'runTest("' + testName + '","' + tname + '")') + "</span>")
++ }else {
++ runtime.log("Running " + tname)
+ }
- return mergedNode
++ lastFailCount = runner.countFailedTests();
++ test.setUp();
++ t();
++ test.tearDown();
++ testResults[tname] = lastFailCount === runner.countFailedTests()
+ }
- function normalizeTextNodes(node) {
- if(node && node.nextSibling) {
- node = mergeTextNodes(node, node.nextSibling)
- }
- if(node && node.previousSibling) {
- mergeTextNodes(node.previousSibling, node)
++ function runAsyncTests(todo) {
++ if(todo.length === 0) {
++ results[testName] = testResults;
++ failedTests += runner.countFailedTests();
++ callback();
++ return
+ }
++ t = todo[0].f;
++ var fname = todo[0].name;
++ runtime.log("Running " + fname);
++ lastFailCount = runner.countFailedTests();
++ test.setUp();
++ t(function() {
++ test.tearDown();
++ testResults[fname] = lastFailCount === runner.countFailedTests();
++ runAsyncTests(todo.slice(1))
++ })
+ }
- this.normalizeTextNodes = normalizeTextNodes;
- function rangeContainsNode(limits, node) {
- var range = node.ownerDocument.createRange(), nodeRange = node.ownerDocument.createRange(), result;
- range.setStart(limits.startContainer, limits.startOffset);
- range.setEnd(limits.endContainer, limits.endOffset);
- nodeRange.selectNodeContents(node);
- result = containsRange(range, nodeRange);
- range.detach();
- nodeRange.detach();
- return result
- }
- this.rangeContainsNode = rangeContainsNode;
- function mergeIntoParent(targetNode) {
- var parent = targetNode.parentNode;
- while(targetNode.firstChild) {
- parent.insertBefore(targetNode.firstChild, targetNode)
- }
- parent.removeChild(targetNode);
- return parent
++ runAsyncTests(test.asyncTests())
++ };
++ this.countFailedTests = function() {
++ return failedTests
++ };
++ this.results = function() {
++ return results
++ }
++};
++core.Utils = function Utils() {
++ function hashString(value) {
++ var hash = 0, i, l;
++ for(i = 0, l = value.length;i < l;i += 1) {
++ hash = (hash << 5) - hash + value.charCodeAt(i);
++ hash |= 0
+ }
- this.mergeIntoParent = mergeIntoParent;
- function removeUnwantedNodes(targetNode, shouldRemove) {
- var parent = targetNode.parentNode, node = targetNode.firstChild, next;
- while(node) {
- next = node.nextSibling;
- removeUnwantedNodes(node, shouldRemove);
- node = next
++ return hash
++ }
++ this.hashString = hashString;
++ var mergeObjects;
++ function mergeItems(destination, source) {
++ if(source && Array.isArray(source)) {
++ destination = destination || [];
++ if(!Array.isArray(destination)) {
++ throw"Destination is not an array.";
+ }
- if(shouldRemove(targetNode)) {
- parent = mergeIntoParent(targetNode)
++ destination = (destination).concat((source).map(function(obj) {
++ return mergeItems(null, obj)
++ }))
++ }else {
++ if(source && typeof source === "object") {
++ destination = destination || {};
++ if(typeof destination !== "object") {
++ throw"Destination is not an object.";
++ }
++ Object.keys((source)).forEach(function(p) {
++ destination[p] = mergeItems(destination[p], source[p])
++ })
++ }else {
++ destination = source
+ }
- return parent
- }
- this.removeUnwantedNodes = removeUnwantedNodes;
- function getElementsByTagNameNS(node, namespace, tagName) {
- return Array.prototype.slice.call(node.getElementsByTagNameNS(namespace, tagName))
- }
- this.getElementsByTagNameNS = getElementsByTagNameNS;
- function rangeIntersectsNode(range, node) {
- var nodeRange = node.ownerDocument.createRange(), result;
- nodeRange.selectNodeContents(node);
- result = rangesIntersect(range, nodeRange);
- nodeRange.detach();
- return result
- }
- this.rangeIntersectsNode = rangeIntersectsNode;
- function containsNode(parent, descendant) {
- return parent === descendant || (parent).contains((descendant))
- }
- this.containsNode = containsNode;
- function containsNodeForBrokenWebKit(parent, descendant) {
- return parent === descendant || Boolean(parent.compareDocumentPosition(descendant) & Node.DOCUMENT_POSITION_CONTAINED_BY)
+ }
- function getPositionInContainingNode(node, container) {
- var offset = 0, n;
- while(node.parentNode !== container) {
- runtime.assert(node.parentNode !== null, "parent is null");
- node = (node.parentNode)
- }
- n = container.firstChild;
- while(n !== node) {
- offset += 1;
- n = n.nextSibling
- }
- return offset
++ return destination
++ }
++ mergeObjects = function(destination, source) {
++ Object.keys(source).forEach(function(p) {
++ destination[p] = mergeItems(destination[p], source[p])
++ });
++ return destination
++ };
++ this.mergeObjects = mergeObjects
++};
++/*
++
++ WebODF
++ Copyright (c) 2010 Jos van den Oever
++ Licensed under the ... License:
++
++ Project home: http://www.webodf.org/
++*/
++runtime.loadClass("core.RawInflate");
++runtime.loadClass("core.ByteArray");
++runtime.loadClass("core.ByteArrayWriter");
++runtime.loadClass("core.Base64");
++core.Zip = function Zip(url, entriesReadCallback) {
++ var entries, filesize, nEntries, inflate = (new core.RawInflate).inflate, zip = this, base64 = new core.Base64;
++ function crc32(data) {
++ var table = [0, 1996959894, 3993919788, 2567524794, 124634137, 1886057615, 3915621685, 2657392035, 249268274, 2044508324, 3772115230, 2547177864, 162941995, 2125561021, 3887607047, 2428444049, 498536548, 1789927666, 4089016648, 2227061214, 450548861, 1843258603, 4107580753, 2211677639, 325883990, 1684777152, 4251122042, 2321926636, 335633487, 1661365465, 4195302755, 2366115317, 997073096, 1281953886, 3579855332, 2724688242, 1006888145, 1258607687, 3524101629, 2768942443, 901097722, [...]
++ 3686517206, 2898065728, 853044451, 1172266101, 3705015759, 2882616665, 651767980, 1373503546, 3369554304, 3218104598, 565507253, 1454621731, 3485111705, 3099436303, 671266974, 1594198024, 3322730930, 2970347812, 795835527, 1483230225, 3244367275, 3060149565, 1994146192, 31158534, 2563907772, 4023717930, 1907459465, 112637215, 2680153253, 3904427059, 2013776290, 251722036, 2517215374, 3775830040, 2137656763, 141376813, 2439277719, 3865271297, 1802195444, 476864866, 2238001368, 406650 [...]
++ 453092731, 2181625025, 4111451223, 1706088902, 314042704, 2344532202, 4240017532, 1658658271, 366619977, 2362670323, 4224994405, 1303535960, 984961486, 2747007092, 3569037538, 1256170817, 1037604311, 2765210733, 3554079995, 1131014506, 879679996, 2909243462, 3663771856, 1141124467, 855842277, 2852801631, 3708648649, 1342533948, 654459306, 3188396048, 3373015174, 1466479909, 544179635, 3110523913, 3462522015, 1591671054, 702138776, 2966460450, 3352799412, 1504918807, 783551873, 30826 [...]
++ 3988292384, 2596254646, 62317068, 1957810842, 3939845945, 2647816111, 81470997, 1943803523, 3814918930, 2489596804, 225274430, 2053790376, 3826175755, 2466906013, 167816743, 2097651377, 4027552580, 2265490386, 503444072, 1762050814, 4150417245, 2154129355, 426522225, 1852507879, 4275313526, 2312317920, 282753626, 1742555852, 4189708143, 2394877945, 397917763, 1622183637, 3604390888, 2714866558, 953729732, 1340076626, 3518719985, 2797360999, 1068828381, 1219638859, 3624741850, 293667 [...]
++ 1090812512, 3747672003, 2825379669, 829329135, 1181335161, 3412177804, 3160834842, 628085408, 1382605366, 3423369109, 3138078467, 570562233, 1426400815, 3317316542, 2998733608, 733239954, 1555261956, 3268935591, 3050360625, 752459403, 1541320221, 2607071920, 3965973030, 1969922972, 40735498, 2617837225, 3943577151, 1913087877, 83908371, 2512341634, 3803740692, 2075208622, 213261112, 2463272603, 3855990285, 2094854071, 198958881, 2262029012, 4057260610, 1759359992, 534414190, 2176718 [...]
++ 1873836001, 414664567, 2282248934, 4279200368, 1711684554, 285281116, 2405801727, 4167216745, 1634467795, 376229701, 2685067896, 3608007406, 1308918612, 956543938, 2808555105, 3495958263, 1231636301, 1047427035, 2932959818, 3654703836, 1088359270, 936918E3, 2847714899, 3736837829, 1202900863, 817233897, 3183342108, 3401237130, 1404277552, 615818150, 3134207493, 3453421203, 1423857449, 601450431, 3009837614, 3294710456, 1567103746, 711928724, 3020668471, 3272380065, 1510334235, 75516 [...]
++ 0, i, iTop = data.length, x = 0, y = 0;
++ crc = crc ^ -1;
++ for(i = 0;i < iTop;i += 1) {
++ y = (crc ^ data[i]) & 255;
++ x = table[y];
++ crc = crc >>> 8 ^ x
+ }
- function comparePoints(c1, o1, c2, o2) {
- if(c1 === c2) {
- return o2 - o1
++ return crc ^ -1
++ }
++ function dosTime2Date(dostime) {
++ var year = (dostime >> 25 & 127) + 1980, month = (dostime >> 21 & 15) - 1, mday = dostime >> 16 & 31, hour = dostime >> 11 & 15, min = dostime >> 5 & 63, sec = (dostime & 31) << 1, d = new Date(year, month, mday, hour, min, sec);
++ return d
++ }
++ function date2DosTime(date) {
++ var y = date.getFullYear();
++ return y < 1980 ? 0 : y - 1980 << 25 | date.getMonth() + 1 << 21 | date.getDate() << 16 | date.getHours() << 11 | date.getMinutes() << 5 | date.getSeconds() >> 1
++ }
++ function ZipEntry(url, stream) {
++ var sig, namelen, extralen, commentlen, compressionMethod, compressedSize, uncompressedSize, offset, entry = this;
++ function handleEntryData(data, callback) {
++ var estream = new core.ByteArray(data), esig = estream.readUInt32LE(), filenamelen, eextralen;
++ if(esig !== 67324752) {
++ callback("File entry signature is wrong." + esig.toString() + " " + data.length.toString(), null);
++ return
+ }
- var comparison = c1.compareDocumentPosition(c2);
- if(comparison === 2) {
- comparison = -1
- }else {
- if(comparison === 4) {
- comparison = 1
- }else {
- if(comparison === 10) {
- o1 = getPositionInContainingNode(c1, c2);
- comparison = o1 < o2 ? 1 : -1
- }else {
- o2 = getPositionInContainingNode(c2, c1);
- comparison = o2 < o1 ? -1 : 1
- }
++ estream.pos += 22;
++ filenamelen = estream.readUInt16LE();
++ eextralen = estream.readUInt16LE();
++ estream.pos += filenamelen + eextralen;
++ if(compressionMethod) {
++ data = data.subarray(estream.pos, estream.pos + compressedSize);
++ if(compressedSize !== data.length) {
++ callback("The amount of compressed bytes read was " + data.length.toString() + " instead of " + compressedSize.toString() + " for " + entry.filename + " in " + url + ".", null);
++ return
+ }
++ data = inflate(data, uncompressedSize)
++ }else {
++ data = data.subarray(estream.pos, estream.pos + uncompressedSize)
+ }
- return comparison
- }
- this.comparePoints = comparePoints;
- function adaptRangeDifferenceToZoomLevel(inputNumber, zoomLevel) {
- if(getBrowserQuirks().unscaledRangeClientRects) {
- return inputNumber
++ if(uncompressedSize !== data.length) {
++ callback("The amount of bytes read was " + data.length.toString() + " instead of " + uncompressedSize.toString() + " for " + entry.filename + " in " + url + ".", null);
++ return
+ }
- return inputNumber / zoomLevel
++ entry.data = data;
++ callback(null, data)
+ }
- this.adaptRangeDifferenceToZoomLevel = adaptRangeDifferenceToZoomLevel;
- function getBoundingClientRect(node) {
- var doc = (node.ownerDocument), quirks = getBrowserQuirks(), range, element;
- if(quirks.unscaledRangeClientRects === false || quirks.rangeBCRIgnoresElementBCR) {
- if(node.nodeType === Node.ELEMENT_NODE) {
- element = (node);
- return element.getBoundingClientRect()
- }
++ function load(callback) {
++ if(entry.data !== null) {
++ callback(null, entry.data);
++ return
+ }
- range = getSharedRange(doc);
- range.selectNode(node);
- return range.getBoundingClientRect()
- }
- this.getBoundingClientRect = getBoundingClientRect;
- function mapKeyValObjOntoNode(node, properties, nsResolver) {
- Object.keys(properties).forEach(function(key) {
- var parts = key.split(":"), prefix = parts[0], localName = parts[1], ns = nsResolver(prefix), value = properties[key], element;
- if(ns) {
- element = node.getElementsByTagNameNS(ns, localName)[0];
- if(!element) {
- element = node.ownerDocument.createElementNS(ns, key);
- node.appendChild(element)
- }
- element.textContent = value
++ var size = compressedSize + 34 + namelen + extralen + 256;
++ if(size + offset > filesize) {
++ size = filesize - offset
++ }
++ runtime.read(url, offset, size, function(err, data) {
++ if(err || data === null) {
++ callback(err, data)
+ }else {
- runtime.log("Key ignored: " + key)
++ handleEntryData(data, callback)
+ }
+ })
+ }
- this.mapKeyValObjOntoNode = mapKeyValObjOntoNode;
- function removeKeyElementsFromNode(node, propertyNames, nsResolver) {
- propertyNames.forEach(function(propertyName) {
- var parts = propertyName.split(":"), prefix = parts[0], localName = parts[1], ns = nsResolver(prefix), element;
- if(ns) {
- element = node.getElementsByTagNameNS(ns, localName)[0];
- if(element) {
- element.parentNode.removeChild(element)
- }else {
- runtime.log("Element for " + propertyName + " not found.")
- }
- }else {
- runtime.log("Property Name ignored: " + propertyName)
- }
- })
++ this.load = load;
++ function set(filename, data, compressed, date) {
++ entry.filename = filename;
++ entry.data = data;
++ entry.compressed = compressed;
++ entry.date = date
+ }
- this.removeKeyElementsFromNode = removeKeyElementsFromNode;
- function getKeyValRepresentationOfNode(node, prefixResolver) {
- var properties = {}, currentSibling = node.firstElementChild, prefix;
- while(currentSibling) {
- prefix = prefixResolver(currentSibling.namespaceURI);
- if(prefix) {
- properties[prefix + ":" + currentSibling.localName] = currentSibling.textContent
- }
- currentSibling = currentSibling.nextElementSibling
- }
- return properties
++ this.set = set;
++ this.error = null;
++ if(!stream) {
++ return
+ }
- this.getKeyValRepresentationOfNode = getKeyValRepresentationOfNode;
- function mapObjOntoNode(node, properties, nsResolver) {
- Object.keys(properties).forEach(function(key) {
- var parts = key.split(":"), prefix = parts[0], localName = parts[1], ns = nsResolver(prefix), value = properties[key], element;
- if(typeof value === "object" && Object.keys(value).length) {
- element = node.getElementsByTagNameNS(ns, localName)[0] || node.ownerDocument.createElementNS(ns, key);
- node.appendChild(element);
- mapObjOntoNode(element, value, nsResolver)
- }else {
- if(ns) {
- node.setAttributeNS(ns, key, value)
- }
- }
- })
++ sig = stream.readUInt32LE();
++ if(sig !== 33639248) {
++ this.error = "Central directory entry has wrong signature at position " + (stream.pos - 4).toString() + ' for file "' + url + '": ' + stream.data.length.toString();
++ return
+ }
- this.mapObjOntoNode = mapObjOntoNode;
- function init(self) {
- var appVersion, webKitOrSafari, ie, window = runtime.getWindow();
- if(window === null) {
++ stream.pos += 6;
++ compressionMethod = stream.readUInt16LE();
++ this.date = dosTime2Date(stream.readUInt32LE());
++ stream.readUInt32LE();
++ compressedSize = stream.readUInt32LE();
++ uncompressedSize = stream.readUInt32LE();
++ namelen = stream.readUInt16LE();
++ extralen = stream.readUInt16LE();
++ commentlen = stream.readUInt16LE();
++ stream.pos += 8;
++ offset = stream.readUInt32LE();
++ this.filename = runtime.byteArrayToString(stream.data.subarray(stream.pos, stream.pos + namelen), "utf8");
++ this.data = null;
++ stream.pos += namelen + extralen + commentlen
++ }
++ function handleCentralDirectory(data, callback) {
++ var stream = new core.ByteArray(data), i, e;
++ entries = [];
++ for(i = 0;i < nEntries;i += 1) {
++ e = new ZipEntry(url, stream);
++ if(e.error) {
++ callback(e.error, zip);
+ return
+ }
- appVersion = window.navigator.appVersion.toLowerCase();
- webKitOrSafari = appVersion.indexOf("chrome") === -1 && (appVersion.indexOf("applewebkit") !== -1 || appVersion.indexOf("safari") !== -1);
- ie = appVersion.indexOf("msie");
- if(webKitOrSafari || ie) {
- self.containsNode = containsNodeForBrokenWebKit
++ entries[entries.length] = e
++ }
++ callback(null, zip)
++ }
++ function handleCentralDirectoryEnd(data, callback) {
++ if(data.length !== 22) {
++ callback("Central directory length should be 22.", zip);
++ return
++ }
++ var stream = new core.ByteArray(data), sig, disk, cddisk, diskNEntries, cdsSize, cdsOffset;
++ sig = stream.readUInt32LE();
++ if(sig !== 101010256) {
++ callback("Central directory signature is wrong: " + sig.toString(), zip);
++ return
++ }
++ disk = stream.readUInt16LE();
++ if(disk !== 0) {
++ callback("Zip files with non-zero disk numbers are not supported.", zip);
++ return
++ }
++ cddisk = stream.readUInt16LE();
++ if(cddisk !== 0) {
++ callback("Zip files with non-zero disk numbers are not supported.", zip);
++ return
++ }
++ diskNEntries = stream.readUInt16LE();
++ nEntries = stream.readUInt16LE();
++ if(diskNEntries !== nEntries) {
++ callback("Number of entries is inconsistent.", zip);
++ return
++ }
++ cdsSize = stream.readUInt32LE();
++ cdsOffset = stream.readUInt16LE();
++ cdsOffset = filesize - 22 - cdsSize;
++ runtime.read(url, cdsOffset, filesize - cdsOffset, function(err, data) {
++ if(err || data === null) {
++ callback(err, zip)
++ }else {
++ handleCentralDirectory(data, callback)
++ }
++ })
++ }
++ function load(filename, callback) {
++ var entry = null, e, i;
++ for(i = 0;i < entries.length;i += 1) {
++ e = entries[i];
++ if(e.filename === filename) {
++ entry = e;
++ break
+ }
+ }
- init(this)
- };
- return core.DomUtils
- })();
- runtime.loadClass("core.DomUtils");
- core.Cursor = function Cursor(document, memberId) {
- var cursorns = "urn:webodf:names:cursor", cursorNode = document.createElementNS(cursorns, "cursor"), anchorNode = document.createElementNS(cursorns, "anchor"), forwardSelection, recentlyModifiedNodes = [], selectedRange = null, isCollapsed, domUtils = new core.DomUtils;
- function putIntoTextNode(node, container, offset) {
- runtime.assert(Boolean(container), "putCursorIntoTextNode: invalid container");
- var parent = container.parentNode;
- runtime.assert(Boolean(parent), "putCursorIntoTextNode: container without parent");
- runtime.assert(offset >= 0 && offset <= container.length, "putCursorIntoTextNode: offset is out of bounds");
- if(offset === 0) {
- parent.insertBefore(node, container)
- }else {
- if(offset === container.length) {
- parent.insertBefore(node, container.nextSibling)
++ if(entry) {
++ if(entry.data) {
++ callback(null, entry.data)
+ }else {
- container.splitText(offset);
- parent.insertBefore(node, container.nextSibling)
++ entry.load(callback)
+ }
++ }else {
++ callback(filename + " not found.", null)
+ }
+ }
- function removeNode(node) {
- if(node.parentNode) {
- recentlyModifiedNodes.push(node.previousSibling);
- recentlyModifiedNodes.push(node.nextSibling);
- node.parentNode.removeChild(node)
- }
++ function loadAsString(filename, callback) {
++ load(filename, function(err, data) {
++ if(err || data === null) {
++ return callback(err, null)
++ }
++ var d = runtime.byteArrayToString(data, "utf8");
++ callback(null, d)
++ })
+ }
- function putNode(node, container, offset) {
- if(container.nodeType === Node.TEXT_NODE) {
- putIntoTextNode(node, (container), offset)
- }else {
- if(container.nodeType === Node.ELEMENT_NODE) {
- container.insertBefore(node, container.childNodes.item(offset))
++ function loadContentXmlAsFragments(filename, handler) {
++ zip.loadAsString(filename, function(err, data) {
++ if(err) {
++ return handler.rootElementReady(err)
+ }
- }
- recentlyModifiedNodes.push(node.previousSibling);
- recentlyModifiedNodes.push(node.nextSibling)
++ handler.rootElementReady(null, data, true)
++ })
+ }
- function getStartNode() {
- return forwardSelection ? anchorNode : cursorNode
++ function loadAsDataURL(filename, mimetype, callback) {
++ load(filename, function(err, data) {
++ if(err || !data) {
++ return callback(err, null)
++ }
++ var p = data, chunksize = 45E3, i = 0, dataurl;
++ if(!mimetype) {
++ if(p[1] === 80 && (p[2] === 78 && p[3] === 71)) {
++ mimetype = "image/png"
++ }else {
++ if(p[0] === 255 && (p[1] === 216 && p[2] === 255)) {
++ mimetype = "image/jpeg"
++ }else {
++ if(p[0] === 71 && (p[1] === 73 && p[2] === 70)) {
++ mimetype = "image/gif"
++ }else {
++ mimetype = ""
++ }
++ }
++ }
++ }
++ dataurl = "data:" + mimetype + ";base64,";
++ while(i < data.length) {
++ dataurl += base64.convertUTF8ArrayToBase64(p.subarray(i, Math.min(i + chunksize, p.length)));
++ i += chunksize
++ }
++ callback(null, dataurl)
++ })
+ }
- function getEndNode() {
- return forwardSelection ? cursorNode : anchorNode
++ function loadAsDOM(filename, callback) {
++ zip.loadAsString(filename, function(err, xmldata) {
++ if(err || xmldata === null) {
++ callback(err, null);
++ return
++ }
++ var parser = new DOMParser, dom = parser.parseFromString(xmldata, "text/xml");
++ callback(null, dom)
++ })
+ }
- this.getNode = function() {
- return cursorNode
- };
- this.getAnchorNode = function() {
- return anchorNode.parentNode ? anchorNode : cursorNode
- };
- this.getSelectedRange = function() {
- if(isCollapsed) {
- selectedRange.setStartBefore(cursorNode);
- selectedRange.collapse(true)
- }else {
- selectedRange.setStartAfter(getStartNode());
- selectedRange.setEndBefore(getEndNode())
++ function save(filename, data, compressed, date) {
++ var i, entry;
++ for(i = 0;i < entries.length;i += 1) {
++ entry = entries[i];
++ if(entry.filename === filename) {
++ entry.set(filename, data, compressed, date);
++ return
++ }
+ }
- return selectedRange
- };
- this.setSelectedRange = function(range, isForwardSelection) {
- if(selectedRange && selectedRange !== range) {
- selectedRange.detach()
++ entry = new ZipEntry(url);
++ entry.set(filename, data, compressed, date);
++ entries.push(entry)
++ }
++ function remove(filename) {
++ var i, entry;
++ for(i = 0;i < entries.length;i += 1) {
++ entry = entries[i];
++ if(entry.filename === filename) {
++ entries.splice(i, 1);
++ return true
++ }
+ }
- selectedRange = range;
- forwardSelection = isForwardSelection !== false;
- isCollapsed = range.collapsed;
- if(range.collapsed) {
- removeNode(anchorNode);
- removeNode(cursorNode);
- putNode(cursorNode, (range.startContainer), range.startOffset)
- }else {
- removeNode(anchorNode);
- removeNode(cursorNode);
- putNode(getEndNode(), (range.endContainer), range.endOffset);
- putNode(getStartNode(), (range.startContainer), range.startOffset)
++ return false
++ }
++ function writeEntry(entry) {
++ var data = new core.ByteArrayWriter("utf8"), length = 0;
++ data.appendArray([80, 75, 3, 4, 20, 0, 0, 0, 0, 0]);
++ if(entry.data) {
++ length = entry.data.length
+ }
- recentlyModifiedNodes.forEach(domUtils.normalizeTextNodes);
- recentlyModifiedNodes.length = 0
++ data.appendUInt32LE(date2DosTime(entry.date));
++ data.appendUInt32LE(entry.data ? crc32(entry.data) : 0);
++ data.appendUInt32LE(length);
++ data.appendUInt32LE(length);
++ data.appendUInt16LE(entry.filename.length);
++ data.appendUInt16LE(0);
++ data.appendString(entry.filename);
++ if(entry.data) {
++ data.appendByteArray(entry.data)
++ }
++ return data
++ }
++ function writeCODEntry(entry, offset) {
++ var data = new core.ByteArrayWriter("utf8"), length = 0;
++ data.appendArray([80, 75, 1, 2, 20, 0, 20, 0, 0, 0, 0, 0]);
++ if(entry.data) {
++ length = entry.data.length
++ }
++ data.appendUInt32LE(date2DosTime(entry.date));
++ data.appendUInt32LE(entry.data ? crc32(entry.data) : 0);
++ data.appendUInt32LE(length);
++ data.appendUInt32LE(length);
++ data.appendUInt16LE(entry.filename.length);
++ data.appendArray([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
++ data.appendUInt32LE(offset);
++ data.appendString(entry.filename);
++ return data
++ }
++ function loadAllEntries(position, callback) {
++ if(position === entries.length) {
++ callback(null);
++ return
++ }
++ var entry = entries[position];
++ if(entry.data !== null) {
++ loadAllEntries(position + 1, callback);
++ return
++ }
++ entry.load(function(err) {
++ if(err) {
++ callback(err);
++ return
++ }
++ loadAllEntries(position + 1, callback)
++ })
++ }
++ function createByteArray(successCallback, errorCallback) {
++ loadAllEntries(0, function(err) {
++ if(err) {
++ errorCallback(err);
++ return
++ }
++ var i, e, codoffset, codsize, data = new core.ByteArrayWriter("utf8"), offsets = [0];
++ for(i = 0;i < entries.length;i += 1) {
++ data.appendByteArrayWriter(writeEntry(entries[i]));
++ offsets.push(data.getLength())
++ }
++ codoffset = data.getLength();
++ for(i = 0;i < entries.length;i += 1) {
++ e = entries[i];
++ data.appendByteArrayWriter(writeCODEntry(e, offsets[i]))
++ }
++ codsize = data.getLength() - codoffset;
++ data.appendArray([80, 75, 5, 6, 0, 0, 0, 0]);
++ data.appendUInt16LE(entries.length);
++ data.appendUInt16LE(entries.length);
++ data.appendUInt32LE(codsize);
++ data.appendUInt32LE(codoffset);
++ data.appendArray([0, 0]);
++ successCallback(data.getByteArray())
++ })
++ }
++ function writeAs(newurl, callback) {
++ createByteArray(function(data) {
++ runtime.writeFile(newurl, data, callback)
++ }, callback)
++ }
++ function write(callback) {
++ writeAs(url, callback)
++ }
++ this.load = load;
++ this.save = save;
++ this.remove = remove;
++ this.write = write;
++ this.writeAs = writeAs;
++ this.createByteArray = createByteArray;
++ this.loadContentXmlAsFragments = loadContentXmlAsFragments;
++ this.loadAsString = loadAsString;
++ this.loadAsDOM = loadAsDOM;
++ this.loadAsDataURL = loadAsDataURL;
++ this.getEntries = function() {
++ return entries.slice()
+ };
- this.hasForwardSelection = function() {
- return forwardSelection
++ filesize = -1;
++ if(entriesReadCallback === null) {
++ entries = [];
++ return
++ }
++ runtime.getFileSize(url, function(size) {
++ filesize = size;
++ if(filesize < 0) {
++ entriesReadCallback("File '" + url + "' cannot be read.", zip)
++ }else {
++ runtime.read(url, filesize - 22, 22, function(err, data) {
++ if(err || (entriesReadCallback === null || data === null)) {
++ entriesReadCallback(err, zip)
++ }else {
++ handleCentralDirectoryEnd(data, entriesReadCallback)
++ }
++ })
++ }
++ })
++};
++gui.Avatar = function Avatar(parentElement, avatarInitiallyVisible) {
++ var self = this, handle, image, pendingImageUrl, displayShown = "block", displayHidden = "none";
++ this.setColor = function(color) {
++ image.style.borderColor = color
+ };
- this.remove = function() {
- removeNode(cursorNode);
- recentlyModifiedNodes.forEach(domUtils.normalizeTextNodes);
- recentlyModifiedNodes.length = 0
++ this.setImageUrl = function(url) {
++ if(self.isVisible()) {
++ image.src = url
++ }else {
++ pendingImageUrl = url
++ }
++ };
++ this.isVisible = function() {
++ return handle.style.display === displayShown
++ };
++ this.show = function() {
++ if(pendingImageUrl) {
++ image.src = pendingImageUrl;
++ pendingImageUrl = undefined
++ }
++ handle.style.display = displayShown
++ };
++ this.hide = function() {
++ handle.style.display = displayHidden
++ };
++ this.markAsFocussed = function(isFocussed) {
++ handle.className = isFocussed ? "active" : ""
++ };
++ this.destroy = function(callback) {
++ parentElement.removeChild(handle);
++ callback()
+ };
+ function init() {
- cursorNode.setAttributeNS(cursorns, "memberId", memberId);
- anchorNode.setAttributeNS(cursorns, "memberId", memberId)
++ var document = (parentElement.ownerDocument), htmlns = document.documentElement.namespaceURI;
++ handle = (document.createElementNS(htmlns, "div"));
++ image = (document.createElementNS(htmlns, "img"));
++ image.width = 64;
++ image.height = 64;
++ handle.appendChild(image);
++ handle.style.width = "64px";
++ handle.style.height = "70px";
++ handle.style.position = "absolute";
++ handle.style.top = "-80px";
++ handle.style.left = "-34px";
++ handle.style.display = avatarInitiallyVisible ? displayShown : displayHidden;
++ parentElement.appendChild(handle)
++ }
++ init()
++};
++gui.EditInfoHandle = function EditInfoHandle(parentElement) {
++ var edits = [], handle, document = (parentElement.ownerDocument), htmlns = document.documentElement.namespaceURI, editinfons = "urn:webodf:names:editinfo";
++ function renderEdits() {
++ var i, infoDiv, colorSpan, authorSpan, timeSpan;
++ handle.innerHTML = "";
++ for(i = 0;i < edits.length;i += 1) {
++ infoDiv = document.createElementNS(htmlns, "div");
++ infoDiv.className = "editInfo";
++ colorSpan = document.createElementNS(htmlns, "span");
++ colorSpan.className = "editInfoColor";
++ colorSpan.setAttributeNS(editinfons, "editinfo:memberid", edits[i].memberid);
++ authorSpan = document.createElementNS(htmlns, "span");
++ authorSpan.className = "editInfoAuthor";
++ authorSpan.setAttributeNS(editinfons, "editinfo:memberid", edits[i].memberid);
++ timeSpan = document.createElementNS(htmlns, "span");
++ timeSpan.className = "editInfoTime";
++ timeSpan.setAttributeNS(editinfons, "editinfo:memberid", edits[i].memberid);
++ timeSpan.innerHTML = edits[i].time;
++ infoDiv.appendChild(colorSpan);
++ infoDiv.appendChild(authorSpan);
++ infoDiv.appendChild(timeSpan);
++ handle.appendChild(infoDiv)
++ }
++ }
++ this.setEdits = function(editArray) {
++ edits = editArray;
++ renderEdits()
++ };
++ this.show = function() {
++ handle.style.display = "block"
++ };
++ this.hide = function() {
++ handle.style.display = "none"
++ };
++ this.destroy = function(callback) {
++ parentElement.removeChild(handle);
++ callback()
++ };
++ function init() {
++ handle = (document.createElementNS(htmlns, "div"));
++ handle.setAttribute("class", "editInfoHandle");
++ handle.style.display = "none";
++ parentElement.appendChild(handle)
+ }
+ init()
+};
+/*
+
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- core.EventNotifier = function EventNotifier(eventIds) {
- var eventListener = {};
- this.emit = function(eventId, args) {
- var i, subscribers;
- runtime.assert(eventListener.hasOwnProperty(eventId), 'unknown event fired "' + eventId + '"');
- subscribers = eventListener[eventId];
- for(i = 0;i < subscribers.length;i += 1) {
- subscribers[i](args)
++gui.KeyboardHandler = function KeyboardHandler() {
++ var modifier = gui.KeyboardHandler.Modifier, defaultBinding = null, bindings = {};
++ function getModifiers(e) {
++ var modifiers = modifier.None;
++ if(e.metaKey) {
++ modifiers |= modifier.Meta
+ }
- };
- this.subscribe = function(eventId, cb) {
- runtime.assert(eventListener.hasOwnProperty(eventId), 'tried to subscribe to unknown event "' + eventId + '"');
- eventListener[eventId].push(cb);
- runtime.log('event "' + eventId + '" subscribed.')
- };
- this.unsubscribe = function(eventId, cb) {
- var cbIndex;
- runtime.assert(eventListener.hasOwnProperty(eventId), 'tried to unsubscribe from unknown event "' + eventId + '"');
- cbIndex = eventListener[eventId].indexOf(cb);
- runtime.assert(cbIndex !== -1, 'tried to unsubscribe unknown callback from event "' + eventId + '"');
- if(cbIndex !== -1) {
- eventListener[eventId].splice(cbIndex, 1)
++ if(e.ctrlKey) {
++ modifiers |= modifier.Ctrl
+ }
- runtime.log('event "' + eventId + '" unsubscribed.')
- };
- function init() {
- var i, eventId;
- for(i = 0;i < eventIds.length;i += 1) {
- eventId = eventIds[i];
- runtime.assert(!eventListener.hasOwnProperty(eventId), 'Duplicated event ids: "' + eventId + '" registered more than once.');
- eventListener[eventId] = []
++ if(e.altKey) {
++ modifiers |= modifier.Alt
++ }
++ if(e.shiftKey) {
++ modifiers |= modifier.Shift
++ }
++ return modifiers
++ }
++ function getKeyCombo(keyCode, modifiers) {
++ if(!modifiers) {
++ modifiers = modifier.None
++ }
++ return keyCode + ":" + modifiers
++ }
++ this.setDefault = function(callback) {
++ defaultBinding = callback
++ };
++ this.bind = function(keyCode, modifiers, callback) {
++ var keyCombo = getKeyCombo(keyCode, modifiers);
++ runtime.assert(bindings.hasOwnProperty(keyCombo) === false, "tried to overwrite the callback handler of key combo: " + keyCombo);
++ bindings[keyCombo] = callback
++ };
++ this.unbind = function(keyCode, modifiers) {
++ var keyCombo = getKeyCombo(keyCode, modifiers);
++ delete bindings[keyCombo]
++ };
++ this.reset = function() {
++ defaultBinding = null;
++ bindings = {}
++ };
++ this.handleEvent = function(e) {
++ var keyCombo = getKeyCombo(e.keyCode, getModifiers(e)), callback = bindings[keyCombo], handled = false;
++ if(callback) {
++ handled = callback()
++ }else {
++ if(defaultBinding !== null) {
++ handled = defaultBinding(e)
++ }
++ }
++ if(handled) {
++ if(e.preventDefault) {
++ e.preventDefault()
++ }else {
++ e.returnValue = false
++ }
+ }
+ }
- init()
- };
- core.UnitTest = function UnitTest() {
- };
- core.UnitTest.prototype.setUp = function() {
- };
- core.UnitTest.prototype.tearDown = function() {
- };
- core.UnitTest.prototype.description = function() {
- };
- core.UnitTest.prototype.tests = function() {
- };
- core.UnitTest.prototype.asyncTests = function() {
+};
- core.UnitTest.provideTestAreaDiv = function() {
- var maindoc = runtime.getWindow().document, testarea = maindoc.getElementById("testarea");
- runtime.assert(!testarea, 'Unclean test environment, found a div with id "testarea".');
- testarea = maindoc.createElement("div");
- testarea.setAttribute("id", "testarea");
- maindoc.body.appendChild(testarea);
- return testarea
++gui.KeyboardHandler.Modifier = {None:0, Meta:1, Ctrl:2, Alt:4, CtrlAlt:6, Shift:8, MetaShift:9, CtrlShift:10, AltShift:12};
++gui.KeyboardHandler.KeyCode = {Backspace:8, Tab:9, Clear:12, Enter:13, End:35, Home:36, Left:37, Up:38, Right:39, Down:40, Delete:46, A:65, B:66, C:67, D:68, E:69, F:70, G:71, H:72, I:73, J:74, K:75, L:76, M:77, N:78, O:79, P:80, Q:81, R:82, S:83, T:84, U:85, V:86, W:87, X:88, Y:89, Z:90};
++(function() {
++ return gui.KeyboardHandler
++})();
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++odf.Namespaces = {namespaceMap:{db:"urn:oasis:names:tc:opendocument:xmlns:database:1.0", dc:"http://purl.org/dc/elements/1.1/", dr3d:"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0", draw:"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0", chart:"urn:oasis:names:tc:opendocument:xmlns:chart:1.0", fo:"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0", form:"urn:oasis:names:tc:opendocument:xmlns:form:1.0", meta:"urn:oasis:names:tc:opendocument:xmlns:meta:1.0", number:"urn:oasis [...]
++office:"urn:oasis:names:tc:opendocument:xmlns:office:1.0", presentation:"urn:oasis:names:tc:opendocument:xmlns:presentation:1.0", style:"urn:oasis:names:tc:opendocument:xmlns:style:1.0", svg:"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0", table:"urn:oasis:names:tc:opendocument:xmlns:table:1.0", text:"urn:oasis:names:tc:opendocument:xmlns:text:1.0", xlink:"http://www.w3.org/1999/xlink", xml:"http://www.w3.org/XML/1998/namespace"}, prefixMap:{}, dbns:"urn:oasis:names:tc:opendo [...]
++dcns:"http://purl.org/dc/elements/1.1/", dr3dns:"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0", drawns:"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0", chartns:"urn:oasis:names:tc:opendocument:xmlns:chart:1.0", fons:"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0", formns:"urn:oasis:names:tc:opendocument:xmlns:form:1.0", numberns:"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0", officens:"urn:oasis:names:tc:opendocument:xmlns:office:1.0", presentationns:"urn:oasi [...]
++stylens:"urn:oasis:names:tc:opendocument:xmlns:style:1.0", svgns:"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0", tablens:"urn:oasis:names:tc:opendocument:xmlns:table:1.0", textns:"urn:oasis:names:tc:opendocument:xmlns:text:1.0", xlinkns:"http://www.w3.org/1999/xlink", xmlns:"http://www.w3.org/XML/1998/namespace"};
++(function() {
++ var map = odf.Namespaces.namespaceMap, pmap = odf.Namespaces.prefixMap, prefix;
++ for(prefix in map) {
++ if(map.hasOwnProperty(prefix)) {
++ pmap[map[prefix]] = prefix
++ }
++ }
++})();
++odf.Namespaces.forEachPrefix = function forEachPrefix(cb) {
++ var ns = odf.Namespaces.namespaceMap, prefix;
++ for(prefix in ns) {
++ if(ns.hasOwnProperty(prefix)) {
++ cb(prefix, ns[prefix])
++ }
++ }
+};
- core.UnitTest.cleanupTestAreaDiv = function() {
- var maindoc = runtime.getWindow().document, testarea = maindoc.getElementById("testarea");
- runtime.assert(!!testarea && testarea.parentNode === maindoc.body, 'Test environment broken, found no div with id "testarea" below body.');
- maindoc.body.removeChild(testarea)
++odf.Namespaces.lookupNamespaceURI = function lookupNamespaceURI(prefix) {
++ var r = null;
++ if(odf.Namespaces.namespaceMap.hasOwnProperty(prefix)) {
++ r = (odf.Namespaces.namespaceMap[prefix])
++ }
++ return r
+};
- core.UnitTest.createOdtDocument = function(xml, namespaceMap) {
- var xmlDoc = "<?xml version='1.0' encoding='UTF-8'?>";
- xmlDoc += "<office:document";
- Object.keys(namespaceMap).forEach(function(key) {
- xmlDoc += " xmlns:" + key + '="' + namespaceMap[key] + '"'
- });
- xmlDoc += ">";
- xmlDoc += xml;
- xmlDoc += "</office:document>";
- return runtime.parseXML(xmlDoc)
++odf.Namespaces.lookupPrefix = function lookupPrefix(namespaceURI) {
++ var map = odf.Namespaces.prefixMap;
++ return map.hasOwnProperty(namespaceURI) ? map[namespaceURI] : null
+};
- core.UnitTestRunner = function UnitTestRunner() {
- var failedTests = 0, areObjectsEqual;
- function debug(msg) {
- runtime.log(msg)
++odf.Namespaces.lookupNamespaceURI.lookupNamespaceURI = odf.Namespaces.lookupNamespaceURI;
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++runtime.loadClass("core.DomUtils");
++runtime.loadClass("odf.Namespaces");
++odf.OdfUtils = function OdfUtils() {
++ var textns = odf.Namespaces.textns, drawns = odf.Namespaces.drawns, whitespaceOnly = /^\s*$/, domUtils = new core.DomUtils;
++ function isImage(e) {
++ var name = e && e.localName;
++ return name === "image" && e.namespaceURI === drawns
+ }
- function testFailed(msg) {
- failedTests += 1;
- runtime.log("fail", msg)
++ this.isImage = isImage;
++ function isCharacterFrame(e) {
++ return e !== null && (e.nodeType === Node.ELEMENT_NODE && (e.localName === "frame" && (e.namespaceURI === drawns && (e).getAttributeNS(textns, "anchor-type") === "as-char")))
+ }
- function testPassed(msg) {
- runtime.log("pass", msg)
++ this.isCharacterFrame = isCharacterFrame;
++ this.isTextSpan = function(e) {
++ var name = e && e.localName;
++ return name === "span" && e.namespaceURI === textns
++ };
++ function isParagraph(e) {
++ var name = e && e.localName;
++ return(name === "p" || name === "h") && e.namespaceURI === textns
+ }
- function areArraysEqual(a, b) {
- var i;
- try {
- if(a.length !== b.length) {
- testFailed("array of length " + a.length + " should be " + b.length + " long");
- return false
- }
- for(i = 0;i < a.length;i += 1) {
- if(a[i] !== b[i]) {
- testFailed(a[i] + " should be " + b[i] + " at array index " + i);
- return false
- }
- }
- }catch(ex) {
- return false
++ this.isParagraph = isParagraph;
++ function getParagraphElement(node) {
++ while(node && !isParagraph(node)) {
++ node = node.parentNode
+ }
- return true
++ return node
+ }
- function areAttributesEqual(a, b, skipReverseCheck) {
- var aatts = a.attributes, n = aatts.length, i, att, v;
- for(i = 0;i < n;i += 1) {
- att = aatts.item(i);
- if(att.prefix !== "xmlns" && att.namespaceURI !== "urn:webodf:names:steps") {
- v = b.getAttributeNS(att.namespaceURI, att.localName);
- if(!b.hasAttributeNS(att.namespaceURI, att.localName)) {
- testFailed("Attribute " + att.localName + " with value " + att.value + " was not present");
- return false
- }
- if(v !== att.value) {
- testFailed("Attribute " + att.localName + " was " + v + " should be " + att.value);
- return false
- }
++ this.getParagraphElement = getParagraphElement;
++ this.isWithinTrackedChanges = function(node, container) {
++ while(node && node !== container) {
++ if(node.namespaceURI === textns && node.localName === "tracked-changes") {
++ return true
+ }
++ node = node.parentNode
+ }
- return skipReverseCheck ? true : areAttributesEqual(b, a, true)
++ return false
++ };
++ this.isListItem = function(e) {
++ var name = e && e.localName;
++ return name === "list-item" && e.namespaceURI === textns
++ };
++ this.isLineBreak = function(e) {
++ var name = e && e.localName;
++ return name === "line-break" && e.namespaceURI === textns
++ };
++ function isODFWhitespace(text) {
++ return/^[ \t\r\n]+$/.test(text)
+ }
- function areNodesEqual(a, b) {
- if(a.nodeType !== b.nodeType) {
- testFailed("Nodetype '" + a.nodeType + "' should be '" + b.nodeType + "'");
++ this.isODFWhitespace = isODFWhitespace;
++ function isGroupingElement(n) {
++ if(n === null || n.nodeType !== Node.ELEMENT_NODE) {
+ return false
+ }
- if(a.nodeType === Node.TEXT_NODE) {
- if(a.data === b.data) {
- return true
++ var e = (n), localName = e.localName;
++ return/^(span|p|h|a|meta)$/.test(localName) && e.namespaceURI === textns || localName === "span" && e.className === "annotationHighlight"
++ }
++ this.isGroupingElement = isGroupingElement;
++ function isCharacterElement(e) {
++ var n = e && e.localName, ns, r = false;
++ if(n) {
++ ns = e.namespaceURI;
++ if(ns === textns) {
++ r = n === "s" || (n === "tab" || n === "line-break")
++ }else {
++ r = isCharacterFrame(e)
+ }
- testFailed("Textnode data '" + a.data + "' should be '" + b.data + "'");
- return false
- }
- runtime.assert(a.nodeType === Node.ELEMENT_NODE, "Only textnodes and elements supported.");
- if(a.namespaceURI !== b.namespaceURI) {
- testFailed("namespace '" + a.namespaceURI + "' should be '" + b.namespaceURI + "'");
- return false
+ }
- if(a.localName !== b.localName) {
- testFailed("localName '" + a.localName + "' should be '" + b.localName + "'");
- return false
- }
- if(!areAttributesEqual((a), (b), false)) {
- return false
- }
- var an = a.firstChild, bn = b.firstChild;
- while(an) {
- if(!bn) {
- testFailed("Nodetype '" + an.nodeType + "' is unexpected here.");
- return false
- }
- if(!areNodesEqual(an, bn)) {
- return false
++ return r
++ }
++ this.isCharacterElement = isCharacterElement;
++ function isSpaceElement(e) {
++ var n = e && e.localName, ns, r = false;
++ if(n) {
++ ns = e.namespaceURI;
++ if(ns === textns) {
++ r = n === "s"
+ }
- an = an.nextSibling;
- bn = bn.nextSibling
- }
- if(bn) {
- testFailed("Nodetype '" + bn.nodeType + "' is missing here.");
- return false
+ }
- return true
++ return r
+ }
- function isResultCorrect(actual, expected) {
- if(expected === 0) {
- return actual === expected && 1 / actual === 1 / expected
- }
- if(actual === expected) {
- return true
- }
- if(typeof expected === "number" && isNaN(expected)) {
- return typeof actual === "number" && isNaN(actual)
- }
- if(Object.prototype.toString.call(expected) === Object.prototype.toString.call([])) {
- return areArraysEqual((actual), (expected))
- }
- if(typeof expected === "object" && typeof actual === "object") {
- if(expected.constructor === Element || expected.constructor === Node) {
- return areNodesEqual((expected), (actual))
- }
- return areObjectsEqual(expected, actual)
++ this.isSpaceElement = isSpaceElement;
++ function firstChild(node) {
++ while(node.firstChild !== null && isGroupingElement(node)) {
++ node = node.firstChild
+ }
- return false
++ return node
+ }
- function stringify(v) {
- if(v === 0 && 1 / v < 0) {
- return"-0"
++ this.firstChild = firstChild;
++ function lastChild(node) {
++ while(node.lastChild !== null && isGroupingElement(node)) {
++ node = node.lastChild
+ }
- return String(v)
++ return node
+ }
- function shouldBe(t, a, b) {
- if(typeof a !== "string" || typeof b !== "string") {
- debug("WARN: shouldBe() expects string arguments")
++ this.lastChild = lastChild;
++ function previousNode(node) {
++ while(!isParagraph(node) && node.previousSibling === null) {
++ node = (node.parentNode)
+ }
- var exception, av, bv;
- try {
- av = eval(a)
- }catch(e) {
- exception = e
++ return isParagraph(node) ? null : lastChild((node.previousSibling))
++ }
++ this.previousNode = previousNode;
++ function nextNode(node) {
++ while(!isParagraph(node) && node.nextSibling === null) {
++ node = (node.parentNode)
+ }
- bv = eval(b);
- if(exception) {
- testFailed(a + " should be " + bv + ". Threw exception " + exception)
- }else {
- if(isResultCorrect(av, bv)) {
- testPassed(a + " is " + b)
++ return isParagraph(node) ? null : firstChild((node.nextSibling))
++ }
++ this.nextNode = nextNode;
++ function scanLeftForNonSpace(node) {
++ var r = false, text;
++ while(node) {
++ if(node.nodeType === Node.TEXT_NODE) {
++ text = (node);
++ if(text.length === 0) {
++ node = previousNode(text)
++ }else {
++ return!isODFWhitespace(text.data.substr(text.length - 1, 1))
++ }
+ }else {
- if(String(typeof av) === String(typeof bv)) {
- testFailed(a + " should be " + bv + ". Was " + stringify(av) + ".")
++ if(isCharacterElement(node)) {
++ r = isSpaceElement(node) === false;
++ node = null
+ }else {
- testFailed(a + " should be " + bv + " (of type " + typeof bv + "). Was " + av + " (of type " + typeof av + ").")
++ node = previousNode(node)
+ }
+ }
+ }
++ return r
+ }
- function shouldBeNonNull(t, a) {
- var exception, av;
- try {
- av = eval(a)
- }catch(e) {
- exception = e
++ this.scanLeftForNonSpace = scanLeftForNonSpace;
++ function lookLeftForCharacter(node) {
++ var text, r = 0, tl = 0;
++ if(node.nodeType === Node.TEXT_NODE) {
++ tl = (node).length
+ }
- if(exception) {
- testFailed(a + " should be non-null. Threw exception " + exception)
- }else {
- if(av !== null) {
- testPassed(a + " is non-null.")
++ if(tl > 0) {
++ text = (node).data;
++ if(!isODFWhitespace(text.substr(tl - 1, 1))) {
++ r = 1
+ }else {
- testFailed(a + " should be non-null. Was " + av)
++ if(tl === 1) {
++ r = scanLeftForNonSpace(previousNode(node)) ? 2 : 0
++ }else {
++ r = isODFWhitespace(text.substr(tl - 2, 1)) ? 0 : 2
++ }
+ }
- }
- }
- function shouldBeNull(t, a) {
- shouldBe(t, a, "null")
- }
- areObjectsEqual = function(a, b) {
- var akeys = Object.keys(a), bkeys = Object.keys(b);
- akeys.sort();
- bkeys.sort();
- return areArraysEqual(akeys, bkeys) && Object.keys(a).every(function(key) {
- var aval = a[key], bval = b[key];
- if(!isResultCorrect(aval, bval)) {
- testFailed(aval + " should be " + bval + " for key " + key);
- return false
++ }else {
++ if(isCharacterElement(node)) {
++ r = 1
+ }
- return true
- })
- };
- this.areNodesEqual = areNodesEqual;
- this.shouldBeNull = shouldBeNull;
- this.shouldBeNonNull = shouldBeNonNull;
- this.shouldBe = shouldBe;
- this.countFailedTests = function() {
- return failedTests
- }
- };
- core.UnitTester = function UnitTester() {
- var failedTests = 0, results = {};
- function link(text, code) {
- return"<span style='color:blue;cursor:pointer' onclick='" + code + "'>" + text + "</span>"
++ }
++ return r
+ }
- this.runTests = function(TestClass, callback, testNames) {
- var testName = Runtime.getFunctionName(TestClass) || "", tname, runner = new core.UnitTestRunner, test = new TestClass(runner), testResults = {}, i, t, tests, lastFailCount, testNameString = "testName", inBrowser = runtime.type() === "BrowserRuntime";
- if(results.hasOwnProperty(testName)) {
- runtime.log("Test " + testName + " has already run.");
- return
++ this.lookLeftForCharacter = lookLeftForCharacter;
++ function lookRightForCharacter(node) {
++ var r = false, l = 0;
++ if(node && node.nodeType === Node.TEXT_NODE) {
++ l = (node).length
+ }
- if(inBrowser) {
- runtime.log("<span>Running " + link(testName, 'runSuite("' + testName + '");') + ": " + test.description() + "</span>")
++ if(l > 0) {
++ r = !isODFWhitespace((node).data.substr(0, 1))
+ }else {
- runtime.log("Running " + testName + ": " + test.description)
- }
- tests = test.tests();
- for(i = 0;i < tests.length;i += 1) {
- t = tests[i];
- tname = Runtime.getFunctionName(t) || t[testNameString];
- if(testNames.length && testNames.indexOf(tname) === -1) {
- continue
++ if(isCharacterElement(node)) {
++ r = true
+ }
- if(inBrowser) {
- runtime.log("<span>Running " + link(tname, 'runTest("' + testName + '","' + tname + '")') + "</span>")
++ }
++ return r
++ }
++ this.lookRightForCharacter = lookRightForCharacter;
++ function scanLeftForAnyCharacter(node) {
++ var r = false, l;
++ node = node && lastChild(node);
++ while(node) {
++ if(node.nodeType === Node.TEXT_NODE) {
++ l = (node).length
+ }else {
- runtime.log("Running " + tname)
++ l = 0
+ }
- lastFailCount = runner.countFailedTests();
- test.setUp();
- t();
- test.tearDown();
- testResults[tname] = lastFailCount === runner.countFailedTests()
- }
- function runAsyncTests(todo) {
- if(todo.length === 0) {
- results[testName] = testResults;
- failedTests += runner.countFailedTests();
- callback();
- return
++ if(l > 0 && !isODFWhitespace((node).data)) {
++ r = true;
++ break
+ }
- t = todo[0];
- var fname = Runtime.getFunctionName(t);
- runtime.log("Running " + fname);
- lastFailCount = runner.countFailedTests();
- test.setUp();
- t(function() {
- test.tearDown();
- testResults[fname] = lastFailCount === runner.countFailedTests();
- runAsyncTests(todo.slice(1))
- })
++ if(isCharacterElement(node)) {
++ r = true;
++ break
++ }
++ node = previousNode(node)
+ }
- runAsyncTests(test.asyncTests())
- };
- this.countFailedTests = function() {
- return failedTests
- };
- this.results = function() {
- return results
++ return r
+ }
- };
- core.PositionIterator = function PositionIterator(root, whatToShow, filter, expandEntityReferences) {
- var self = this, walker, currentPos, nodeFilter, TEXT_NODE = Node.TEXT_NODE, ELEMENT_NODE = Node.ELEMENT_NODE, FILTER_ACCEPT = NodeFilter.FILTER_ACCEPT, FILTER_REJECT = NodeFilter.FILTER_REJECT;
- function EmptyTextNodeFilter() {
- this.acceptNode = function(node) {
- var text = (node);
- if(!node || node.nodeType === TEXT_NODE && text.length === 0) {
- return FILTER_REJECT
++ this.scanLeftForAnyCharacter = scanLeftForAnyCharacter;
++ function scanRightForAnyCharacter(node) {
++ var r = false, l;
++ node = node && firstChild(node);
++ while(node) {
++ if(node.nodeType === Node.TEXT_NODE) {
++ l = (node).length
++ }else {
++ l = 0
+ }
- return FILTER_ACCEPT
++ if(l > 0 && !isODFWhitespace((node).data)) {
++ r = true;
++ break
++ }
++ if(isCharacterElement(node)) {
++ r = true;
++ break
++ }
++ node = nextNode(node)
+ }
++ return r
+ }
- function FilteredEmptyTextNodeFilter(filter) {
- this.acceptNode = function(node) {
- var text = (node);
- if(!node || node.nodeType === TEXT_NODE && text.length === 0) {
- return FILTER_REJECT
- }
- return filter.acceptNode(node)
++ this.scanRightForAnyCharacter = scanRightForAnyCharacter;
++ function isTrailingWhitespace(textnode, offset) {
++ if(!isODFWhitespace(textnode.data.substr(offset))) {
++ return false
+ }
++ return!scanRightForAnyCharacter(nextNode(textnode))
+ }
- this.nextPosition = function() {
- var currentNode = walker.currentNode, nodeType = currentNode.nodeType, text = (currentNode);
- if(currentNode === root) {
++ this.isTrailingWhitespace = isTrailingWhitespace;
++ function isSignificantWhitespace(textNode, offset) {
++ var text = textNode.data, result;
++ if(!isODFWhitespace(text[offset])) {
+ return false
+ }
- if(currentPos === 0 && nodeType === ELEMENT_NODE) {
- if(walker.firstChild() === null) {
- currentPos = 1
++ if(isCharacterElement(textNode.parentNode)) {
++ return false
++ }
++ if(offset > 0) {
++ if(!isODFWhitespace(text[offset - 1])) {
++ result = true
+ }
+ }else {
- if(nodeType === TEXT_NODE && currentPos + 1 < text.length) {
- currentPos += 1
- }else {
- if(walker.nextSibling() !== null) {
- currentPos = 0
- }else {
- if(walker.parentNode()) {
- currentPos = 1
- }else {
- return false
- }
- }
++ if(scanLeftForNonSpace(previousNode(textNode))) {
++ result = true
+ }
+ }
- return true
++ if(result === true) {
++ return isTrailingWhitespace(textNode, offset) ? false : true
++ }
++ return false
++ }
++ this.isSignificantWhitespace = isSignificantWhitespace;
++ this.isDowngradableSpaceElement = function(node) {
++ if(node.namespaceURI === textns && node.localName === "s") {
++ return scanLeftForNonSpace(previousNode(node)) && scanRightForAnyCharacter(nextNode(node))
++ }
++ return false
+ };
- function setAtEnd() {
- var text = (walker.currentNode), type = text.nodeType;
- if(type === TEXT_NODE) {
- currentPos = text.length - 1
- }else {
- currentPos = type === ELEMENT_NODE ? 1 : 0
++ function getFirstNonWhitespaceChild(node) {
++ var child = node && node.firstChild;
++ while(child && (child.nodeType === Node.TEXT_NODE && whitespaceOnly.test(child.nodeValue))) {
++ child = child.nextSibling
+ }
++ return child
+ }
- function previousNode() {
- if(walker.previousSibling() === null) {
- if(!walker.parentNode() || walker.currentNode === root) {
- walker.firstChild();
- return false
++ this.getFirstNonWhitespaceChild = getFirstNonWhitespaceChild;
++ function parseLength(length) {
++ var re = /(-?[0-9]*[0-9][0-9]*(\.[0-9]*)?|0+\.[0-9]*[1-9][0-9]*|\.[0-9]*[1-9][0-9]*)((cm)|(mm)|(in)|(pt)|(pc)|(px)|(%))/, m = re.exec(length);
++ if(!m) {
++ return null
++ }
++ return{value:parseFloat(m[1]), unit:m[3]}
++ }
++ this.parseLength = parseLength;
++ function parsePositiveLength(length) {
++ var result = parseLength(length);
++ if(result && (result.value <= 0 || result.unit === "%")) {
++ return null
++ }
++ return result
++ }
++ function parseNonNegativeLength(length) {
++ var result = parseLength(length);
++ if(result && (result.value < 0 || result.unit === "%")) {
++ return null
++ }
++ return result
++ }
++ this.parseNonNegativeLength = parseNonNegativeLength;
++ function parsePercentage(length) {
++ var result = parseLength(length);
++ if(result && result.unit !== "%") {
++ return null
++ }
++ return result
++ }
++ function parseFoFontSize(fontSize) {
++ return parsePositiveLength(fontSize) || parsePercentage(fontSize)
++ }
++ this.parseFoFontSize = parseFoFontSize;
++ function parseFoLineHeight(lineHeight) {
++ return parseNonNegativeLength(lineHeight) || parsePercentage(lineHeight)
++ }
++ this.parseFoLineHeight = parseFoLineHeight;
++ function item(a, i) {
++ return a[i]
++ }
++ function getImpactedParagraphs(range) {
++ var i, l, e, outerContainer = (range.commonAncestorContainer), impactedParagraphs = [], filtered = [];
++ if(outerContainer.nodeType === Node.ELEMENT_NODE) {
++ impactedParagraphs = domUtils.getElementsByTagNameNS(outerContainer, textns, "p").concat(domUtils.getElementsByTagNameNS(outerContainer, textns, "h"))
++ }
++ while(outerContainer && !isParagraph(outerContainer)) {
++ outerContainer = outerContainer.parentNode
++ }
++ if(outerContainer) {
++ impactedParagraphs.push(outerContainer)
++ }
++ l = impactedParagraphs.length;
++ for(i = 0;i < l;i += 1) {
++ e = item(impactedParagraphs, i);
++ if(domUtils.rangeIntersectsNode(range, e)) {
++ filtered.push(e)
+ }
- currentPos = 0
- }else {
- setAtEnd()
++ }
++ return filtered
++ }
++ this.getImpactedParagraphs = getImpactedParagraphs;
++ function isAcceptedNode(node) {
++ switch(node.namespaceURI) {
++ case odf.Namespaces.drawns:
++ ;
++ case odf.Namespaces.svgns:
++ ;
++ case odf.Namespaces.dr3dns:
++ return false;
++ case odf.Namespaces.textns:
++ switch(node.localName) {
++ case "note-body":
++ ;
++ case "ruby-text":
++ return false
++ }
++ break;
++ case odf.Namespaces.officens:
++ switch(node.localName) {
++ case "annotation":
++ ;
++ case "binary-data":
++ ;
++ case "event-listeners":
++ return false
++ }
++ break;
++ default:
++ switch(node.localName) {
++ case "editinfo":
++ return false
++ }
++ break
+ }
+ return true
+ }
- this.previousPosition = function() {
- var moved = true, currentNode = walker.currentNode;
- if(currentPos === 0) {
- moved = previousNode()
- }else {
- if(currentNode.nodeType === TEXT_NODE) {
- currentPos -= 1
++ function isSignificantTextContent(textNode) {
++ return Boolean(getParagraphElement(textNode) && (!isODFWhitespace(textNode.textContent) || isSignificantWhitespace(textNode, 0)))
++ }
++ function includeNode(range, nodeRange, includePartial) {
++ return includePartial && domUtils.rangesIntersect(range, nodeRange) || domUtils.containsRange(range, nodeRange)
++ }
++ function getTextNodes(range, includePartial) {
++ var document = range.startContainer.ownerDocument, nodeRange = document.createRange(), textNodes;
++ function nodeFilter(node) {
++ nodeRange.selectNodeContents(node);
++ if(node.nodeType === Node.TEXT_NODE) {
++ if(includeNode(range, nodeRange, includePartial)) {
++ return isSignificantTextContent((node)) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT
++ }
+ }else {
- if(walker.lastChild() !== null) {
- setAtEnd()
- }else {
- if(currentNode === root) {
- moved = false
- }else {
- currentPos = 0
++ if(domUtils.rangesIntersect(range, nodeRange)) {
++ if(isAcceptedNode(node)) {
++ return NodeFilter.FILTER_SKIP
+ }
+ }
+ }
++ return NodeFilter.FILTER_REJECT
+ }
- return moved
- };
- this.previousNode = previousNode;
- this.container = function() {
- var n = (walker.currentNode), t = n.nodeType;
- if(currentPos === 0 && t !== TEXT_NODE) {
- n = (n.parentNode)
- }
- return n
- };
- this.rightNode = function() {
- var n = walker.currentNode, text = (n), nodeType = n.nodeType;
- if(nodeType === TEXT_NODE && currentPos === text.length) {
- n = n.nextSibling;
- while(n && nodeFilter(n) !== FILTER_ACCEPT) {
- n = n.nextSibling
++ textNodes = domUtils.getNodesInRange(range, nodeFilter);
++ nodeRange.detach();
++ return textNodes
++ }
++ this.getTextNodes = getTextNodes;
++ this.getTextElements = function(range, includePartial, includeInsignificantWhitespace) {
++ var document = range.startContainer.ownerDocument, nodeRange = document.createRange(), elements;
++ function nodeFilter(node) {
++ nodeRange.selectNodeContents(node);
++ if(isCharacterElement(node.parentNode)) {
++ return NodeFilter.FILTER_REJECT
+ }
- }else {
- if(nodeType === ELEMENT_NODE && currentPos === 1) {
- n = null
++ if(node.nodeType === Node.TEXT_NODE) {
++ if(includeNode(range, nodeRange, includePartial)) {
++ if(includeInsignificantWhitespace || isSignificantTextContent((node))) {
++ return NodeFilter.FILTER_ACCEPT
++ }
++ }
++ }else {
++ if(isCharacterElement(node)) {
++ if(includeNode(range, nodeRange, includePartial)) {
++ return NodeFilter.FILTER_ACCEPT
++ }
++ }else {
++ if(isAcceptedNode(node) || isGroupingElement(node)) {
++ return NodeFilter.FILTER_SKIP
++ }
++ }
+ }
++ return NodeFilter.FILTER_REJECT
+ }
- return n
++ elements = domUtils.getNodesInRange(range, nodeFilter);
++ nodeRange.detach();
++ return elements
+ };
- this.leftNode = function() {
- var n = walker.currentNode;
- if(currentPos === 0) {
- n = n.previousSibling;
- while(n && nodeFilter(n) !== FILTER_ACCEPT) {
- n = n.previousSibling
- }
- }else {
- if(n.nodeType === ELEMENT_NODE) {
- n = n.lastChild;
- while(n && nodeFilter(n) !== FILTER_ACCEPT) {
- n = n.previousSibling
++ this.getParagraphElements = function(range) {
++ var document = range.startContainer.ownerDocument, nodeRange = document.createRange(), elements;
++ function nodeFilter(node) {
++ nodeRange.selectNodeContents(node);
++ if(isParagraph(node)) {
++ if(domUtils.rangesIntersect(range, nodeRange)) {
++ return NodeFilter.FILTER_ACCEPT
++ }
++ }else {
++ if(isAcceptedNode(node) || isGroupingElement(node)) {
++ return NodeFilter.FILTER_SKIP
+ }
+ }
++ return NodeFilter.FILTER_REJECT
+ }
- return n
- };
- this.getCurrentNode = function() {
- var n = (walker.currentNode);
- return n
++ elements = domUtils.getNodesInRange(range, nodeFilter);
++ nodeRange.detach();
++ return elements
+ };
- this.unfilteredDomOffset = function() {
- if(walker.currentNode.nodeType === TEXT_NODE) {
- return currentPos
- }
- var c = 0, n = walker.currentNode;
- if(currentPos === 1) {
- n = n.lastChild
- }else {
- n = n.previousSibling
- }
- while(n) {
- c += 1;
- n = n.previousSibling
- }
- return c
- };
- this.getPreviousSibling = function() {
- var currentNode = walker.currentNode, sibling = walker.previousSibling();
- walker.currentNode = currentNode;
- return sibling
- };
- this.getNextSibling = function() {
- var currentNode = walker.currentNode, sibling = walker.nextSibling();
- walker.currentNode = currentNode;
- return sibling
- };
- this.setUnfilteredPosition = function(container, offset) {
- var filterResult, node, text;
- runtime.assert(container !== null && container !== undefined, "PositionIterator.setUnfilteredPosition called without container");
- walker.currentNode = container;
- if(container.nodeType === TEXT_NODE) {
- currentPos = offset;
- text = (container);
- runtime.assert(offset <= text.length, "Error in setPosition: " + offset + " > " + text.length);
- runtime.assert(offset >= 0, "Error in setPosition: " + offset + " < 0");
- if(offset === text.length) {
- if(walker.nextSibling()) {
- currentPos = 0
- }else {
- if(walker.parentNode()) {
- currentPos = 1
- }else {
- runtime.assert(false, "Error in setUnfilteredPosition: position not valid.")
- }
- }
- }
- return true
- }
- filterResult = nodeFilter(container);
- node = container.parentNode;
- while(node && (node !== root && filterResult === FILTER_ACCEPT)) {
- filterResult = nodeFilter(node);
- if(filterResult !== FILTER_ACCEPT) {
- walker.currentNode = node
++ this.getImageElements = function(range) {
++ var document = range.startContainer.ownerDocument, nodeRange = document.createRange(), elements;
++ function nodeFilter(node) {
++ nodeRange.selectNodeContents(node);
++ if(isImage(node) && domUtils.containsRange(range, nodeRange)) {
++ return NodeFilter.FILTER_ACCEPT
+ }
- node = node.parentNode
- }
- if(offset < container.childNodes.length && filterResult !== NodeFilter.FILTER_REJECT) {
- walker.currentNode = (container.childNodes.item(offset));
- filterResult = nodeFilter(walker.currentNode);
- currentPos = 0
- }else {
- currentPos = 1
- }
- if(filterResult === NodeFilter.FILTER_REJECT) {
- currentPos = 1
- }
- if(filterResult !== FILTER_ACCEPT) {
- return self.nextPosition()
- }
- runtime.assert(nodeFilter(walker.currentNode) === FILTER_ACCEPT, "PositionIterater.setUnfilteredPosition call resulted in an non-visible node being set");
- return true
- };
- this.moveToEnd = function() {
- walker.currentNode = root;
- currentPos = 1
- };
- this.moveToEndOfNode = function(node) {
- var text;
- if(node.nodeType === TEXT_NODE) {
- text = (node);
- self.setUnfilteredPosition(text, text.length)
- }else {
- walker.currentNode = node;
- currentPos = 1
- }
- };
- this.getNodeFilter = function() {
- return nodeFilter
- };
- function init() {
- var f;
- if(filter) {
- f = new FilteredEmptyTextNodeFilter(filter)
- }else {
- f = new EmptyTextNodeFilter
- }
- nodeFilter = (f.acceptNode);
- nodeFilter.acceptNode = nodeFilter;
- whatToShow = whatToShow || 4294967295;
- runtime.assert(root.nodeType !== Node.TEXT_NODE, "Internet Explorer doesn't allow tree walker roots to be text nodes");
- walker = root.ownerDocument.createTreeWalker(root, whatToShow, nodeFilter, expandEntityReferences);
- currentPos = 0;
- if(walker.firstChild() === null) {
- currentPos = 1
++ return NodeFilter.FILTER_SKIP
+ }
++ elements = domUtils.getNodesInRange(range, nodeFilter);
++ nodeRange.detach();
++ return elements
+ }
- init()
+};
- runtime.loadClass("core.PositionIterator");
- core.PositionFilter = function PositionFilter() {
++/*
++
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++ops.Server = function Server() {
+};
- core.PositionFilter.FilterResult = {FILTER_ACCEPT:1, FILTER_REJECT:2, FILTER_SKIP:3};
- core.PositionFilter.prototype.acceptPosition = function(point) {
++ops.Server.prototype.connect = function(timeout, cb) {
+};
- (function() {
- return core.PositionFilter
- })();
- runtime.loadClass("core.PositionFilter");
- core.PositionFilterChain = function PositionFilterChain() {
- var filterChain = {}, FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT, FILTER_REJECT = core.PositionFilter.FilterResult.FILTER_REJECT;
- this.acceptPosition = function(iterator) {
- var filterName;
- for(filterName in filterChain) {
- if(filterChain.hasOwnProperty(filterName)) {
- if(filterChain[filterName].acceptPosition(iterator) === FILTER_REJECT) {
- return FILTER_REJECT
++ops.Server.prototype.networkStatus = function() {
++};
++ops.Server.prototype.login = function(login, password, successCb, failCb) {
++};
++ops.Server.prototype.joinSession = function(userId, sessionId, successCb, failCb) {
++};
++ops.Server.prototype.leaveSession = function(sessionId, memberId, successCb, failCb) {
++};
++ops.Server.prototype.getGenesisUrl = function(sessionId) {
++};
++xmldom.LSSerializerFilter = function LSSerializerFilter() {
++};
++xmldom.LSSerializerFilter.prototype.acceptNode = function(node) {
++};
++xmldom.XPathIterator = function XPathIterator() {
++};
++xmldom.XPathIterator.prototype.next = function() {
++};
++xmldom.XPathIterator.prototype.reset = function() {
++};
++xmldom.XPathAtom;
++function createXPathSingleton() {
++ var createXPathPathIterator, parsePredicates;
++ function isSmallestPositive(a, b, c) {
++ return a !== -1 && ((a < b || b === -1) && (a < c || c === -1))
++ }
++ function parseXPathStep(xpath, pos, end, steps) {
++ var location = "", predicates = [], brapos = xpath.indexOf("[", pos), slapos = xpath.indexOf("/", pos), eqpos = xpath.indexOf("=", pos);
++ if(isSmallestPositive(slapos, brapos, eqpos)) {
++ location = xpath.substring(pos, slapos);
++ pos = slapos + 1
++ }else {
++ if(isSmallestPositive(brapos, slapos, eqpos)) {
++ location = xpath.substring(pos, brapos);
++ pos = parsePredicates(xpath, brapos, predicates)
++ }else {
++ if(isSmallestPositive(eqpos, slapos, brapos)) {
++ location = xpath.substring(pos, eqpos);
++ pos = eqpos
++ }else {
++ location = xpath.substring(pos, end);
++ pos = end
+ }
+ }
+ }
- return FILTER_ACCEPT
- };
- this.addFilter = function(filterName, filterInstance) {
- filterChain[filterName] = filterInstance
- };
- this.removeFilter = function(filterName) {
- delete filterChain[filterName]
- }
- };
- core.ScheduledTask = function ScheduledTask(fn, delay) {
- var timeoutId, scheduled = false;
- function execute() {
- fn();
- scheduled = false
++ steps.push({location:location, predicates:predicates});
++ return pos
+ }
- function cancel() {
- if(scheduled) {
- runtime.clearTimeout(timeoutId);
- scheduled = false
++ function parseXPath(xpath) {
++ var steps = [], p = 0, end = xpath.length, value;
++ while(p < end) {
++ p = parseXPathStep(xpath, p, end, steps);
++ if(p < end && xpath[p] === "=") {
++ value = xpath.substring(p + 1, end);
++ if(value.length > 2 && (value[0] === "'" || value[0] === '"')) {
++ value = value.slice(1, value.length - 1)
++ }else {
++ try {
++ value = parseInt(value, 10)
++ }catch(ignore) {
++ }
++ }
++ p = end
++ }
+ }
++ return{steps:steps, value:value}
+ }
- this.trigger = function() {
- if(!scheduled) {
- timeoutId = runtime.setTimeout(execute, delay)
++ parsePredicates = function parsePredicates(xpath, start, predicates) {
++ var pos = start, l = xpath.length, depth = 0;
++ while(pos < l) {
++ if(xpath[pos] === "]") {
++ depth -= 1;
++ if(depth <= 0) {
++ predicates.push(parseXPath(xpath.substring(start, pos)))
++ }
++ }else {
++ if(xpath[pos] === "[") {
++ if(depth <= 0) {
++ start = pos + 1
++ }
++ depth += 1
++ }
++ }
++ pos += 1
+ }
++ return pos
+ };
- this.triggerImmediate = function() {
- cancel();
- execute()
- };
- this.processRequests = function() {
- if(scheduled) {
- cancel();
- execute()
++ function XPathNodeIterator() {
++ var node = null, done = false;
++ this.setNode = function setNode(n) {
++ node = n
++ };
++ this.reset = function() {
++ done = false
++ };
++ this.next = function next() {
++ var val = done ? null : node;
++ done = true;
++ return val
+ }
- };
- this.cancel = cancel;
- this.destroy = function(callback) {
- cancel();
- callback()
+ }
- };
- core.Async = function Async() {
- this.forEach = function(items, f, callback) {
- var i, l = items.length, itemsDone = 0;
- function end(err) {
- if(itemsDone !== l) {
- if(err) {
- itemsDone = l;
- callback(err)
- }else {
- itemsDone += 1;
- if(itemsDone === l) {
- callback(null)
- }
++ function AttributeIterator(it, namespace, localName) {
++ this.reset = function reset() {
++ it.reset()
++ };
++ this.next = function next() {
++ var node = it.next();
++ while(node) {
++ if(node.nodeType === Node.ELEMENT_NODE) {
++ node = (node).getAttributeNodeNS(namespace, localName)
++ }
++ if(node) {
++ return node
+ }
++ node = it.next()
+ }
++ return node
+ }
- for(i = 0;i < l;i += 1) {
- f(items[i], end)
- }
- };
- this.destroyAll = function(items, callback) {
- function destroy(itemIndex, err) {
- if(err) {
- callback(err)
- }else {
- if(itemIndex < items.length) {
- items[itemIndex](function(err) {
- destroy(itemIndex + 1, err)
- })
++ }
++ function AllChildElementIterator(it, recurse) {
++ var root = it.next(), node = null;
++ this.reset = function reset() {
++ it.reset();
++ root = it.next();
++ node = null
++ };
++ this.next = function next() {
++ while(root) {
++ if(node) {
++ if(recurse && node.firstChild) {
++ node = node.firstChild
++ }else {
++ while(!node.nextSibling && node !== root) {
++ node = node.parentNode
++ }
++ if(node === root) {
++ root = it.next()
++ }else {
++ node = node.nextSibling
++ }
++ }
+ }else {
- callback()
++ do {
++ node = root.firstChild;
++ if(!node) {
++ root = it.next()
++ }
++ }while(root && !node)
++ }
++ if(node && node.nodeType === Node.ELEMENT_NODE) {
++ return node
+ }
+ }
++ return null
+ }
- destroy(0, undefined)
+ }
- };
- /*
-
- WebODF
- Copyright (c) 2010 Jos van den Oever
- Licensed under the ... License:
-
- Project home: http://www.webodf.org/
- */
- runtime.loadClass("core.RawInflate");
- runtime.loadClass("core.ByteArray");
- runtime.loadClass("core.ByteArrayWriter");
- runtime.loadClass("core.Base64");
- core.Zip = function Zip(url, entriesReadCallback) {
- var entries, filesize, nEntries, inflate = (new core.RawInflate).inflate, zip = this, base64 = new core.Base64;
- function crc32(data) {
- var table = [0, 1996959894, 3993919788, 2567524794, 124634137, 1886057615, 3915621685, 2657392035, 249268274, 2044508324, 3772115230, 2547177864, 162941995, 2125561021, 3887607047, 2428444049, 498536548, 1789927666, 4089016648, 2227061214, 450548861, 1843258603, 4107580753, 2211677639, 325883990, 1684777152, 4251122042, 2321926636, 335633487, 1661365465, 4195302755, 2366115317, 997073096, 1281953886, 3579855332, 2724688242, 1006888145, 1258607687, 3524101629, 2768942443, 901097722, [...]
- 3686517206, 2898065728, 853044451, 1172266101, 3705015759, 2882616665, 651767980, 1373503546, 3369554304, 3218104598, 565507253, 1454621731, 3485111705, 3099436303, 671266974, 1594198024, 3322730930, 2970347812, 795835527, 1483230225, 3244367275, 3060149565, 1994146192, 31158534, 2563907772, 4023717930, 1907459465, 112637215, 2680153253, 3904427059, 2013776290, 251722036, 2517215374, 3775830040, 2137656763, 141376813, 2439277719, 3865271297, 1802195444, 476864866, 2238001368, 406650 [...]
- 453092731, 2181625025, 4111451223, 1706088902, 314042704, 2344532202, 4240017532, 1658658271, 366619977, 2362670323, 4224994405, 1303535960, 984961486, 2747007092, 3569037538, 1256170817, 1037604311, 2765210733, 3554079995, 1131014506, 879679996, 2909243462, 3663771856, 1141124467, 855842277, 2852801631, 3708648649, 1342533948, 654459306, 3188396048, 3373015174, 1466479909, 544179635, 3110523913, 3462522015, 1591671054, 702138776, 2966460450, 3352799412, 1504918807, 783551873, 30826 [...]
- 3988292384, 2596254646, 62317068, 1957810842, 3939845945, 2647816111, 81470997, 1943803523, 3814918930, 2489596804, 225274430, 2053790376, 3826175755, 2466906013, 167816743, 2097651377, 4027552580, 2265490386, 503444072, 1762050814, 4150417245, 2154129355, 426522225, 1852507879, 4275313526, 2312317920, 282753626, 1742555852, 4189708143, 2394877945, 397917763, 1622183637, 3604390888, 2714866558, 953729732, 1340076626, 3518719985, 2797360999, 1068828381, 1219638859, 3624741850, 293667 [...]
- 1090812512, 3747672003, 2825379669, 829329135, 1181335161, 3412177804, 3160834842, 628085408, 1382605366, 3423369109, 3138078467, 570562233, 1426400815, 3317316542, 2998733608, 733239954, 1555261956, 3268935591, 3050360625, 752459403, 1541320221, 2607071920, 3965973030, 1969922972, 40735498, 2617837225, 3943577151, 1913087877, 83908371, 2512341634, 3803740692, 2075208622, 213261112, 2463272603, 3855990285, 2094854071, 198958881, 2262029012, 4057260610, 1759359992, 534414190, 2176718 [...]
- 1873836001, 414664567, 2282248934, 4279200368, 1711684554, 285281116, 2405801727, 4167216745, 1634467795, 376229701, 2685067896, 3608007406, 1308918612, 956543938, 2808555105, 3495958263, 1231636301, 1047427035, 2932959818, 3654703836, 1088359270, 936918E3, 2847714899, 3736837829, 1202900863, 817233897, 3183342108, 3401237130, 1404277552, 615818150, 3134207493, 3453421203, 1423857449, 601450431, 3009837614, 3294710456, 1567103746, 711928724, 3020668471, 3272380065, 1510334235, 75516 [...]
- 0, i, iTop = data.length, x = 0, y = 0;
- crc = crc ^ -1;
- for(i = 0;i < iTop;i += 1) {
- y = (crc ^ data[i]) & 255;
- x = table[y];
- crc = crc >>> 8 ^ x
++ function ConditionIterator(it, condition) {
++ this.reset = function reset() {
++ it.reset()
++ };
++ this.next = function next() {
++ var n = it.next();
++ while(n && !condition(n)) {
++ n = it.next()
++ }
++ return n
+ }
- return crc ^ -1
+ }
- function dosTime2Date(dostime) {
- var year = (dostime >> 25 & 127) + 1980, month = (dostime >> 21 & 15) - 1, mday = dostime >> 16 & 31, hour = dostime >> 11 & 15, min = dostime >> 5 & 63, sec = (dostime & 31) << 1, d = new Date(year, month, mday, hour, min, sec);
- return d
++ function createNodenameFilter(it, name, namespaceResolver) {
++ var s = name.split(":", 2), namespace = namespaceResolver(s[0]), localName = s[1];
++ return new ConditionIterator(it, function(node) {
++ return node.localName === localName && node.namespaceURI === namespace
++ })
+ }
- function date2DosTime(date) {
- var y = date.getFullYear();
- return y < 1980 ? 0 : y - 1980 << 25 | date.getMonth() + 1 << 21 | date.getDate() << 16 | date.getHours() << 11 | date.getMinutes() << 5 | date.getSeconds() >> 1
++ function createPredicateFilteredIterator(it, p, namespaceResolver) {
++ var nit = new XPathNodeIterator, pit = createXPathPathIterator(nit, p, namespaceResolver), value = p.value;
++ if(value === undefined) {
++ return new ConditionIterator(it, function(node) {
++ nit.setNode(node);
++ pit.reset();
++ return pit.next() !== null
++ })
++ }
++ return new ConditionIterator(it, function(node) {
++ nit.setNode(node);
++ pit.reset();
++ var n = pit.next();
++ return n ? n.nodeValue === value : false
++ })
+ }
- function ZipEntry(url, stream) {
- var sig, namelen, extralen, commentlen, compressionMethod, compressedSize, uncompressedSize, offset, entry = this;
- function handleEntryData(data, callback) {
- var estream = new core.ByteArray(data), esig = estream.readUInt32LE(), filenamelen, eextralen;
- if(esig !== 67324752) {
- callback("File entry signature is wrong." + esig.toString() + " " + data.length.toString(), null);
- return
- }
- estream.pos += 22;
- filenamelen = estream.readUInt16LE();
- eextralen = estream.readUInt16LE();
- estream.pos += filenamelen + eextralen;
- if(compressionMethod) {
- data = data.subarray(estream.pos, estream.pos + compressedSize);
- if(compressedSize !== data.length) {
- callback("The amount of compressed bytes read was " + data.length.toString() + " instead of " + compressedSize.toString() + " for " + entry.filename + " in " + url + ".", null);
- return
- }
- data = inflate(data, uncompressedSize)
++ function item(p, i) {
++ return p[i]
++ }
++ createXPathPathIterator = function createXPathPathIterator(it, xpath, namespaceResolver) {
++ var i, j, step, location, s, p, ns;
++ for(i = 0;i < xpath.steps.length;i += 1) {
++ step = xpath.steps[i];
++ location = step.location;
++ if(location === "") {
++ it = new AllChildElementIterator(it, false)
+ }else {
- data = data.subarray(estream.pos, estream.pos + uncompressedSize)
++ if(location[0] === "@") {
++ s = location.substr(1).split(":", 2);
++ ns = namespaceResolver(s[0]);
++ if(!ns) {
++ throw"No namespace associated with the prefix " + s[0];
++ }
++ it = new AttributeIterator(it, ns, s[1])
++ }else {
++ if(location !== ".") {
++ it = new AllChildElementIterator(it, false);
++ if(location.indexOf(":") !== -1) {
++ it = createNodenameFilter(it, location, namespaceResolver)
++ }
++ }
++ }
+ }
- if(uncompressedSize !== data.length) {
- callback("The amount of bytes read was " + data.length.toString() + " instead of " + uncompressedSize.toString() + " for " + entry.filename + " in " + url + ".", null);
- return
++ for(j = 0;j < step.predicates.length;j += 1) {
++ p = item(step.predicates, j);
++ it = createPredicateFilteredIterator(it, p, namespaceResolver)
+ }
- entry.data = data;
- callback(null, data)
+ }
- function load(callback) {
- if(entry.data !== undefined) {
- callback(null, entry.data);
- return
- }
- var size = compressedSize + 34 + namelen + extralen + 256;
- if(size + offset > filesize) {
- size = filesize - offset
- }
- runtime.read(url, offset, size, function(err, data) {
- if(err || data === null) {
- callback(err, data)
- }else {
- handleEntryData(data, callback)
- }
- })
++ return it
++ };
++ function fallback(node, xpath, namespaceResolver) {
++ var it = new XPathNodeIterator, i, nodelist, parsedXPath;
++ it.setNode(node);
++ parsedXPath = parseXPath(xpath);
++ it = createXPathPathIterator(it, parsedXPath, namespaceResolver);
++ nodelist = [];
++ i = it.next();
++ while(i) {
++ nodelist.push(i);
++ i = it.next()
+ }
- this.load = load;
- function set(filename, data, compressed, date) {
- entry.filename = filename;
- entry.data = data;
- entry.compressed = compressed;
- entry.date = date
++ return nodelist
++ }
++ function getODFElementsWithXPath(node, xpath, namespaceResolver) {
++ var doc = node.ownerDocument, nodes, elements = [], n = null;
++ if(!doc || typeof doc.evaluate !== "function") {
++ elements = fallback(node, xpath, namespaceResolver)
++ }else {
++ nodes = doc.evaluate(xpath, node, namespaceResolver, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null);
++ n = nodes.iterateNext();
++ while(n !== null) {
++ if(n.nodeType === Node.ELEMENT_NODE) {
++ elements.push(n)
++ }
++ n = nodes.iterateNext()
++ }
+ }
- this.set = set;
- this.error = null;
- if(!stream) {
- return
- }
- sig = stream.readUInt32LE();
- if(sig !== 33639248) {
- this.error = "Central directory entry has wrong signature at position " + (stream.pos - 4).toString() + ' for file "' + url + '": ' + stream.data.length.toString();
- return
- }
- stream.pos += 6;
- compressionMethod = stream.readUInt16LE();
- this.date = dosTime2Date(stream.readUInt32LE());
- stream.readUInt32LE();
- compressedSize = stream.readUInt32LE();
- uncompressedSize = stream.readUInt32LE();
- namelen = stream.readUInt16LE();
- extralen = stream.readUInt16LE();
- commentlen = stream.readUInt16LE();
- stream.pos += 8;
- offset = stream.readUInt32LE();
- this.filename = runtime.byteArrayToString(stream.data.subarray(stream.pos, stream.pos + namelen), "utf8");
- stream.pos += namelen + extralen + commentlen
++ return elements
+ }
- function handleCentralDirectory(data, callback) {
- var stream = new core.ByteArray(data), i, e;
- entries = [];
- for(i = 0;i < nEntries;i += 1) {
- e = new ZipEntry(url, stream);
- if(e.error) {
- callback(e.error, zip);
- return
++ return{getODFElementsWithXPath:getODFElementsWithXPath}
++}
++xmldom.XPath = createXPathSingleton();
++runtime.loadClass("core.DomUtils");
++core.Cursor = function Cursor(document, memberId) {
++ var cursorns = "urn:webodf:names:cursor", cursorNode = document.createElementNS(cursorns, "cursor"), anchorNode = document.createElementNS(cursorns, "anchor"), forwardSelection, recentlyModifiedNodes = [], selectedRange = (document.createRange()), isCollapsed, domUtils = new core.DomUtils;
++ function putIntoTextNode(node, container, offset) {
++ runtime.assert(Boolean(container), "putCursorIntoTextNode: invalid container");
++ var parent = container.parentNode;
++ runtime.assert(Boolean(parent), "putCursorIntoTextNode: container without parent");
++ runtime.assert(offset >= 0 && offset <= container.length, "putCursorIntoTextNode: offset is out of bounds");
++ if(offset === 0) {
++ parent.insertBefore(node, container)
++ }else {
++ if(offset === container.length) {
++ parent.insertBefore(node, container.nextSibling)
++ }else {
++ container.splitText(offset);
++ parent.insertBefore(node, container.nextSibling)
+ }
- entries[entries.length] = e
+ }
- callback(null, zip)
+ }
- function handleCentralDirectoryEnd(data, callback) {
- if(data.length !== 22) {
- callback("Central directory length should be 22.", zip);
- return
- }
- var stream = new core.ByteArray(data), sig, disk, cddisk, diskNEntries, cdsSize, cdsOffset;
- sig = stream.readUInt32LE();
- if(sig !== 101010256) {
- callback("Central directory signature is wrong: " + sig.toString(), zip);
- return
- }
- disk = stream.readUInt16LE();
- if(disk !== 0) {
- callback("Zip files with non-zero disk numbers are not supported.", zip);
- return
- }
- cddisk = stream.readUInt16LE();
- if(cddisk !== 0) {
- callback("Zip files with non-zero disk numbers are not supported.", zip);
- return
- }
- diskNEntries = stream.readUInt16LE();
- nEntries = stream.readUInt16LE();
- if(diskNEntries !== nEntries) {
- callback("Number of entries is inconsistent.", zip);
- return
++ function removeNode(node) {
++ if(node.parentNode) {
++ recentlyModifiedNodes.push(node.previousSibling);
++ recentlyModifiedNodes.push(node.nextSibling);
++ node.parentNode.removeChild(node)
+ }
- cdsSize = stream.readUInt32LE();
- cdsOffset = stream.readUInt16LE();
- cdsOffset = filesize - 22 - cdsSize;
- runtime.read(url, cdsOffset, filesize - cdsOffset, function(err, data) {
- if(err || data === null) {
- callback(err, zip)
- }else {
- handleCentralDirectory(data, callback)
- }
- })
+ }
- function load(filename, callback) {
- var entry = null, e, i;
- for(i = 0;i < entries.length;i += 1) {
- e = entries[i];
- if(e.filename === filename) {
- entry = e;
- break
- }
- }
- if(entry) {
- if(entry.data) {
- callback(null, entry.data)
- }else {
- entry.load(callback)
- }
++ function putNode(node, container, offset) {
++ if(container.nodeType === Node.TEXT_NODE) {
++ putIntoTextNode(node, (container), offset)
+ }else {
- callback(filename + " not found.", null)
- }
- }
- function loadAsString(filename, callback) {
- load(filename, function(err, data) {
- if(err || data === null) {
- return callback(err, null)
- }
- var d = runtime.byteArrayToString(data, "utf8");
- callback(null, d)
- })
- }
- function loadContentXmlAsFragments(filename, handler) {
- zip.loadAsString(filename, function(err, data) {
- if(err) {
- return handler.rootElementReady(err)
- }
- handler.rootElementReady(null, data, true)
- })
- }
- function loadAsDataURL(filename, mimetype, callback) {
- load(filename, function(err, data) {
- if(err || !data) {
- return callback(err, null)
- }
- var p = data, chunksize = 45E3, i = 0, dataurl;
- if(!mimetype) {
- if(p[1] === 80 && (p[2] === 78 && p[3] === 71)) {
- mimetype = "image/png"
- }else {
- if(p[0] === 255 && (p[1] === 216 && p[2] === 255)) {
- mimetype = "image/jpeg"
- }else {
- if(p[0] === 71 && (p[1] === 73 && p[2] === 70)) {
- mimetype = "image/gif"
- }else {
- mimetype = ""
- }
- }
- }
- }
- dataurl = "data:" + mimetype + ";base64,";
- while(i < data.length) {
- dataurl += base64.convertUTF8ArrayToBase64(p.subarray(i, Math.min(i + chunksize, p.length)));
- i += chunksize
++ if(container.nodeType === Node.ELEMENT_NODE) {
++ container.insertBefore(node, container.childNodes.item(offset))
+ }
- callback(null, dataurl)
- })
++ }
++ recentlyModifiedNodes.push(node.previousSibling);
++ recentlyModifiedNodes.push(node.nextSibling)
+ }
- function loadAsDOM(filename, callback) {
- zip.loadAsString(filename, function(err, xmldata) {
- if(err || xmldata === null) {
- callback(err, null);
- return
- }
- var parser = new DOMParser, dom = parser.parseFromString(xmldata, "text/xml");
- callback(null, dom)
- })
++ function getStartNode() {
++ return forwardSelection ? anchorNode : cursorNode
+ }
- function save(filename, data, compressed, date) {
- var i, entry;
- for(i = 0;i < entries.length;i += 1) {
- entry = entries[i];
- if(entry.filename === filename) {
- entry.set(filename, data, compressed, date);
- return
- }
- }
- entry = new ZipEntry(url);
- entry.set(filename, data, compressed, date);
- entries.push(entry)
++ function getEndNode() {
++ return forwardSelection ? cursorNode : anchorNode
+ }
- function remove(filename) {
- var i, entry;
- for(i = 0;i < entries.length;i += 1) {
- entry = entries[i];
- if(entry.filename === filename) {
- entries.splice(i, 1);
- return true
- }
++ this.getNode = function() {
++ return cursorNode
++ };
++ this.getAnchorNode = function() {
++ return anchorNode.parentNode ? anchorNode : cursorNode
++ };
++ this.getSelectedRange = function() {
++ if(isCollapsed) {
++ selectedRange.setStartBefore(cursorNode);
++ selectedRange.collapse(true)
++ }else {
++ selectedRange.setStartAfter(getStartNode());
++ selectedRange.setEndBefore(getEndNode())
+ }
- return false
- }
- function writeEntry(entry) {
- var data = new core.ByteArrayWriter("utf8"), length = 0;
- data.appendArray([80, 75, 3, 4, 20, 0, 0, 0, 0, 0]);
- if(entry.data) {
- length = entry.data.length
++ return selectedRange
++ };
++ this.setSelectedRange = function(range, isForwardSelection) {
++ if(selectedRange && selectedRange !== range) {
++ selectedRange.detach()
+ }
- data.appendUInt32LE(date2DosTime(entry.date));
- data.appendUInt32LE(crc32(entry.data));
- data.appendUInt32LE(length);
- data.appendUInt32LE(length);
- data.appendUInt16LE(entry.filename.length);
- data.appendUInt16LE(0);
- data.appendString(entry.filename);
- if(entry.data) {
- data.appendByteArray(entry.data)
++ selectedRange = range;
++ forwardSelection = isForwardSelection !== false;
++ isCollapsed = range.collapsed;
++ if(range.collapsed) {
++ removeNode(anchorNode);
++ removeNode(cursorNode);
++ putNode(cursorNode, (range.startContainer), range.startOffset)
++ }else {
++ removeNode(anchorNode);
++ removeNode(cursorNode);
++ putNode(getEndNode(), (range.endContainer), range.endOffset);
++ putNode(getStartNode(), (range.startContainer), range.startOffset)
+ }
- return data
++ recentlyModifiedNodes.forEach(domUtils.normalizeTextNodes);
++ recentlyModifiedNodes.length = 0
++ };
++ this.hasForwardSelection = function() {
++ return forwardSelection
++ };
++ this.remove = function() {
++ removeNode(cursorNode);
++ recentlyModifiedNodes.forEach(domUtils.normalizeTextNodes);
++ recentlyModifiedNodes.length = 0
++ };
++ function init() {
++ cursorNode.setAttributeNS(cursorns, "memberId", memberId);
++ anchorNode.setAttributeNS(cursorns, "memberId", memberId)
+ }
- function writeCODEntry(entry, offset) {
- var data = new core.ByteArrayWriter("utf8"), length = 0;
- data.appendArray([80, 75, 1, 2, 20, 0, 20, 0, 0, 0, 0, 0]);
- if(entry.data) {
- length = entry.data.length
++ init()
++};
++runtime.loadClass("core.PositionIterator");
++core.PositionFilter = function PositionFilter() {
++};
++core.PositionFilter.FilterResult = {FILTER_ACCEPT:1, FILTER_REJECT:2, FILTER_SKIP:3};
++core.PositionFilter.prototype.acceptPosition = function(point) {
++};
++(function() {
++ return core.PositionFilter
++})();
++runtime.loadClass("core.PositionFilter");
++core.PositionFilterChain = function PositionFilterChain() {
++ var filterChain = {}, FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT, FILTER_REJECT = core.PositionFilter.FilterResult.FILTER_REJECT;
++ this.acceptPosition = function(iterator) {
++ var filterName;
++ for(filterName in filterChain) {
++ if(filterChain.hasOwnProperty(filterName)) {
++ if(filterChain[filterName].acceptPosition(iterator) === FILTER_REJECT) {
++ return FILTER_REJECT
++ }
++ }
+ }
- data.appendUInt32LE(date2DosTime(entry.date));
- data.appendUInt32LE(crc32(entry.data));
- data.appendUInt32LE(length);
- data.appendUInt32LE(length);
- data.appendUInt16LE(entry.filename.length);
- data.appendArray([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
- data.appendUInt32LE(offset);
- data.appendString(entry.filename);
- return data
++ return FILTER_ACCEPT
++ };
++ this.addFilter = function(filterName, filterInstance) {
++ filterChain[filterName] = filterInstance
++ };
++ this.removeFilter = function(filterName) {
++ delete filterChain[filterName]
+ }
- function loadAllEntries(position, callback) {
- if(position === entries.length) {
- callback(null);
- return
++};
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++gui.AnnotatableCanvas = function AnnotatableCanvas() {
++};
++gui.AnnotatableCanvas.prototype.refreshSize = function() {
++};
++gui.AnnotatableCanvas.prototype.getZoomLevel = function() {
++};
++gui.AnnotatableCanvas.prototype.getSizer = function() {
++};
++gui.AnnotationViewManager = function AnnotationViewManager(canvas, odfFragment, annotationsPane) {
++ var annotations = [], doc = odfFragment.ownerDocument, odfUtils = new odf.OdfUtils, CONNECTOR_MARGIN = 30, NOTE_MARGIN = 20, window = runtime.getWindow();
++ runtime.assert(Boolean(window), "Expected to be run in an environment which has a global window, like a browser.");
++ function wrapAnnotation(annotation) {
++ var annotationWrapper = doc.createElement("div"), annotationNote = doc.createElement("div"), connectorHorizontal = doc.createElement("div"), connectorAngular = doc.createElement("div"), removeButton = doc.createElement("div"), annotationNode = annotation.node;
++ annotationWrapper.className = "annotationWrapper";
++ annotationNode.parentNode.insertBefore(annotationWrapper, annotationNode);
++ annotationNote.className = "annotationNote";
++ annotationNote.appendChild(annotationNode);
++ removeButton.className = "annotationRemoveButton";
++ annotationNote.appendChild(removeButton);
++ connectorHorizontal.className = "annotationConnector horizontal";
++ connectorAngular.className = "annotationConnector angular";
++ annotationWrapper.appendChild(annotationNote);
++ annotationWrapper.appendChild(connectorHorizontal);
++ annotationWrapper.appendChild(connectorAngular)
++ }
++ function unwrapAnnotation(annotation) {
++ var annotationNode = annotation.node, annotationWrapper = annotationNode.parentNode.parentNode;
++ if(annotationWrapper.localName === "div") {
++ annotationWrapper.parentNode.insertBefore(annotationNode, annotationWrapper);
++ annotationWrapper.parentNode.removeChild(annotationWrapper)
+ }
- var entry = entries[position];
- if(entry.data !== undefined) {
- loadAllEntries(position + 1, callback);
- return
++ }
++ function highlightAnnotation(annotation) {
++ var annotationNode = annotation.node, annotationEnd = annotation.end, range = doc.createRange(), textNodes;
++ if(annotationEnd) {
++ range.setStart(annotationNode, annotationNode.childNodes.length);
++ range.setEnd(annotationEnd, 0);
++ textNodes = odfUtils.getTextNodes(range, false);
++ textNodes.forEach(function(n) {
++ var container = doc.createElement("span"), v = annotationNode.getAttributeNS(odf.Namespaces.officens, "name");
++ container.className = "annotationHighlight";
++ container.setAttribute("annotation", v);
++ n.parentNode.insertBefore(container, n);
++ container.appendChild(n)
++ })
+ }
- entry.load(function(err) {
- if(err) {
- callback(err);
- return
- }
- loadAllEntries(position + 1, callback)
- })
++ range.detach()
+ }
- function createByteArray(successCallback, errorCallback) {
- loadAllEntries(0, function(err) {
- if(err) {
- errorCallback(err);
- return
- }
- var data = new core.ByteArrayWriter("utf8"), i, e, codoffset, codsize, offsets = [0];
- for(i = 0;i < entries.length;i += 1) {
- data.appendByteArrayWriter(writeEntry(entries[i]));
- offsets.push(data.getLength())
- }
- codoffset = data.getLength();
- for(i = 0;i < entries.length;i += 1) {
- e = entries[i];
- data.appendByteArrayWriter(writeCODEntry(e, offsets[i]))
++ function unhighlightAnnotation(annotation) {
++ var annotationName = annotation.node.getAttributeNS(odf.Namespaces.officens, "name"), highlightSpans = doc.querySelectorAll('span.annotationHighlight[annotation="' + annotationName + '"]'), i, container;
++ for(i = 0;i < highlightSpans.length;i += 1) {
++ container = highlightSpans.item(i);
++ while(container.firstChild) {
++ container.parentNode.insertBefore(container.firstChild, container)
+ }
- codsize = data.getLength() - codoffset;
- data.appendArray([80, 75, 5, 6, 0, 0, 0, 0]);
- data.appendUInt16LE(entries.length);
- data.appendUInt16LE(entries.length);
- data.appendUInt32LE(codsize);
- data.appendUInt32LE(codoffset);
- data.appendArray([0, 0]);
- successCallback(data.getByteArray())
- })
- }
- function writeAs(newurl, callback) {
- createByteArray(function(data) {
- runtime.writeFile(newurl, data, callback)
- }, callback)
++ container.parentNode.removeChild(container)
++ }
+ }
- function write(callback) {
- writeAs(url, callback)
++ function lineDistance(point1, point2) {
++ var xs = 0, ys = 0;
++ xs = point2.x - point1.x;
++ xs = xs * xs;
++ ys = point2.y - point1.y;
++ ys = ys * ys;
++ return Math.sqrt(xs + ys)
+ }
- this.load = load;
- this.save = save;
- this.remove = remove;
- this.write = write;
- this.writeAs = writeAs;
- this.createByteArray = createByteArray;
- this.loadContentXmlAsFragments = loadContentXmlAsFragments;
- this.loadAsString = loadAsString;
- this.loadAsDOM = loadAsDOM;
- this.loadAsDataURL = loadAsDataURL;
- this.getEntries = function() {
- return entries.slice()
- };
- filesize = -1;
- if(entriesReadCallback === null) {
- entries = [];
- return
++ function renderAnnotation(annotation) {
++ var annotationNote = annotation.node.parentElement, connectorHorizontal = annotationNote.nextElementSibling, connectorAngular = connectorHorizontal.nextElementSibling, annotationWrapper = annotationNote.parentElement, connectorAngle = 0, previousAnnotation = annotations[annotations.indexOf(annotation) - 1], previousRect, zoomLevel = canvas.getZoomLevel();
++ annotationNote.style.left = (annotationsPane.getBoundingClientRect().left - annotationWrapper.getBoundingClientRect().left) / zoomLevel + "px";
++ annotationNote.style.width = annotationsPane.getBoundingClientRect().width / zoomLevel + "px";
++ connectorHorizontal.style.width = parseFloat(annotationNote.style.left) - CONNECTOR_MARGIN + "px";
++ if(previousAnnotation) {
++ previousRect = previousAnnotation.node.parentElement.getBoundingClientRect();
++ if((annotationWrapper.getBoundingClientRect().top - previousRect.bottom) / zoomLevel <= NOTE_MARGIN) {
++ annotationNote.style.top = Math.abs(annotationWrapper.getBoundingClientRect().top - previousRect.bottom) / zoomLevel + NOTE_MARGIN + "px"
++ }else {
++ annotationNote.style.top = "0px"
++ }
++ }
++ connectorAngular.style.left = connectorHorizontal.getBoundingClientRect().width / zoomLevel + "px";
++ connectorAngular.style.width = lineDistance({x:connectorAngular.getBoundingClientRect().left / zoomLevel, y:connectorAngular.getBoundingClientRect().top / zoomLevel}, {x:annotationNote.getBoundingClientRect().left / zoomLevel, y:annotationNote.getBoundingClientRect().top / zoomLevel}) + "px";
++ connectorAngle = Math.asin((annotationNote.getBoundingClientRect().top - connectorAngular.getBoundingClientRect().top) / (zoomLevel * parseFloat(connectorAngular.style.width)));
++ connectorAngular.style.transform = "rotate(" + connectorAngle + "rad)";
++ connectorAngular.style.MozTransform = "rotate(" + connectorAngle + "rad)";
++ connectorAngular.style.WebkitTransform = "rotate(" + connectorAngle + "rad)";
++ connectorAngular.style.msTransform = "rotate(" + connectorAngle + "rad)"
+ }
- runtime.getFileSize(url, function(size) {
- filesize = size;
- if(filesize < 0) {
- entriesReadCallback("File '" + url + "' cannot be read.", zip)
++ function showAnnotationsPane(show) {
++ var sizer = canvas.getSizer();
++ if(show) {
++ annotationsPane.style.display = "inline-block";
++ sizer.style.paddingRight = window.getComputedStyle(annotationsPane).width
+ }else {
- runtime.read(url, filesize - 22, 22, function(err, data) {
- if(err || (entriesReadCallback === null || data === null)) {
- entriesReadCallback(err, zip)
- }else {
- handleCentralDirectoryEnd(data, entriesReadCallback)
- }
- })
++ annotationsPane.style.display = "none";
++ sizer.style.paddingRight = 0
+ }
- })
- };
- core.CSSUnits = function CSSUnits() {
- var self = this, sizemap = {"in":1, "cm":2.54, "mm":25.4, "pt":72, "pc":12};
- this.convert = function(value, oldUnit, newUnit) {
- return value * sizemap[newUnit] / sizemap[oldUnit]
- };
- this.convertMeasure = function(measure, newUnit) {
- var value, oldUnit, newMeasure;
- if(measure && newUnit) {
- value = parseFloat(measure);
- oldUnit = measure.replace(value.toString(), "");
- newMeasure = self.convert(value, oldUnit, newUnit).toString()
- }else {
- newMeasure = ""
++ canvas.refreshSize()
++ }
++ function sortAnnotations() {
++ annotations.sort(function(a, b) {
++ if(a.node.compareDocumentPosition(b.node) === Node.DOCUMENT_POSITION_FOLLOWING) {
++ return-1
++ }
++ return 1
++ })
++ }
++ function rerenderAnnotations() {
++ var i;
++ for(i = 0;i < annotations.length;i += 1) {
++ renderAnnotation(annotations[i])
+ }
- return newMeasure
- };
- this.getUnits = function(measure) {
- return measure.substr(measure.length - 2, measure.length)
+ }
- };
- xmldom.LSSerializerFilter = function LSSerializerFilter() {
- };
- if(typeof Object.create !== "function") {
- Object["create"] = function(o) {
- var F = function() {
- };
- F.prototype = o;
- return new F
++ this.rerenderAnnotations = rerenderAnnotations;
++ function addAnnotation(annotation) {
++ showAnnotationsPane(true);
++ annotations.push({node:annotation.node, end:annotation.end});
++ sortAnnotations();
++ wrapAnnotation(annotation);
++ if(annotation.end) {
++ highlightAnnotation(annotation)
++ }
++ rerenderAnnotations()
+ }
- }
- xmldom.LSSerializer = function LSSerializer() {
- var self = this;
- function Namespaces(nsmap) {
- function invertMap(map) {
- var m = {}, i;
- for(i in map) {
- if(map.hasOwnProperty(i)) {
- m[map[i]] = i
- }
- }
- return m
++ this.addAnnotation = addAnnotation;
++ function forgetAnnotation(annotation) {
++ var index = annotations.indexOf(annotation);
++ unwrapAnnotation(annotation);
++ unhighlightAnnotation(annotation);
++ if(index !== -1) {
++ annotations.splice(index, 1)
+ }
- var current = nsmap || {}, currentrev = invertMap(nsmap), levels = [current], levelsrev = [currentrev], level = 0;
- this.push = function() {
- level += 1;
- current = levels[level] = Object.create(current);
- currentrev = levelsrev[level] = Object.create(currentrev)
- };
- this.pop = function() {
- levels[level] = undefined;
- levelsrev[level] = undefined;
- level -= 1;
- current = levels[level];
- currentrev = levelsrev[level]
- };
- this.getLocalNamespaceDefinitions = function() {
- return currentrev
- };
- this.getQName = function(node) {
- var ns = node.namespaceURI, i = 0, p;
- if(!ns) {
- return node.localName
- }
- p = currentrev[ns];
- if(p) {
- return p + ":" + node.localName
- }
- do {
- if(p || !node.prefix) {
- p = "ns" + i;
- i += 1
- }else {
- p = node.prefix
- }
- if(current[p] === ns) {
- break
- }
- if(!current[p]) {
- current[p] = ns;
- currentrev[ns] = p;
- break
- }
- p = null
- }while(p === null);
- return p + ":" + node.localName
++ if(annotations.length === 0) {
++ showAnnotationsPane(false)
+ }
+ }
- function escapeContent(value) {
- return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/'/g, "'").replace(/"/g, """)
++ function forgetAnnotations() {
++ while(annotations.length) {
++ forgetAnnotation(annotations[0])
++ }
+ }
- function serializeAttribute(qname, attr) {
- var escapedValue = typeof attr.value === "string" ? escapeContent(attr.value) : attr.value, s = qname + '="' + escapedValue + '"';
- return s
++ this.forgetAnnotations = forgetAnnotations
++};
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++runtime.loadClass("core.Cursor");
++runtime.loadClass("core.DomUtils");
++runtime.loadClass("core.PositionIterator");
++runtime.loadClass("core.PositionFilter");
++runtime.loadClass("core.LoopWatchDog");
++runtime.loadClass("odf.OdfUtils");
++gui.SelectionMover = function SelectionMover(cursor, rootNode) {
++ var odfUtils = new odf.OdfUtils, domUtils = new core.DomUtils, positionIterator, cachedXOffset, timeoutHandle, FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT;
++ function getIteratorAtCursor() {
++ positionIterator.setUnfilteredPosition(cursor.getNode(), 0);
++ return positionIterator
+ }
- function startElement(ns, qname, element) {
- var s = "", atts = (element.attributes), length, i, attr, attstr = "", accept, prefix, nsmap;
- s += "<" + qname;
- length = atts.length;
- for(i = 0;i < length;i += 1) {
- attr = (atts.item(i));
- if(attr.namespaceURI !== "http://www.w3.org/2000/xmlns/") {
- accept = self.filter ? self.filter.acceptNode(attr) : NodeFilter.FILTER_ACCEPT;
- if(accept === NodeFilter.FILTER_ACCEPT) {
- attstr += " " + serializeAttribute(ns.getQName(attr), attr)
- }
- }
++ function getMaximumNodePosition(node) {
++ return node.nodeType === Node.TEXT_NODE ? node.textContent.length : node.childNodes.length
++ }
++ function getClientRect(clientRectangles, useRightEdge) {
++ var rectangle, simplifiedRectangle = null;
++ if(clientRectangles && clientRectangles.length > 0) {
++ rectangle = useRightEdge ? clientRectangles.item(clientRectangles.length - 1) : clientRectangles.item(0)
+ }
- nsmap = ns.getLocalNamespaceDefinitions();
- for(i in nsmap) {
- if(nsmap.hasOwnProperty(i)) {
- prefix = nsmap[i];
- if(!prefix) {
- s += ' xmlns="' + i + '"'
++ if(rectangle) {
++ simplifiedRectangle = {top:rectangle.top, left:useRightEdge ? rectangle.right : rectangle.left, bottom:rectangle.bottom}
++ }
++ return simplifiedRectangle
++ }
++ function getVisibleRect(container, offset, range, useRightEdge) {
++ var rectangle, nodeType = container.nodeType;
++ range.setStart(container, offset);
++ range.collapse(!useRightEdge);
++ rectangle = getClientRect(range.getClientRects(), useRightEdge === true);
++ if(!rectangle && offset > 0) {
++ range.setStart(container, offset - 1);
++ range.setEnd(container, offset);
++ rectangle = getClientRect(range.getClientRects(), true)
++ }
++ if(!rectangle) {
++ if(nodeType === Node.ELEMENT_NODE && (offset > 0 && (container).childNodes.length >= offset)) {
++ rectangle = getVisibleRect(container, offset - 1, range, true)
++ }else {
++ if(container.nodeType === Node.TEXT_NODE && offset > 0) {
++ rectangle = getVisibleRect(container, offset - 1, range, true)
+ }else {
- if(prefix !== "xmlns") {
- s += " xmlns:" + nsmap[i] + '="' + i + '"'
++ if(container.previousSibling) {
++ rectangle = getVisibleRect(container.previousSibling, getMaximumNodePosition(container.previousSibling), range, true)
++ }else {
++ if(container.parentNode && container.parentNode !== rootNode) {
++ rectangle = getVisibleRect(container.parentNode, 0, range, false)
++ }else {
++ range.selectNode(rootNode);
++ rectangle = getClientRect(range.getClientRects(), false)
++ }
+ }
+ }
+ }
+ }
- s += attstr + ">";
- return s
++ runtime.assert(Boolean(rectangle), "No visible rectangle found");
++ return(rectangle)
+ }
- function serializeNode(ns, node) {
- var s = "", accept = self.filter ? self.filter.acceptNode(node) : NodeFilter.FILTER_ACCEPT, child, qname;
- if(accept === NodeFilter.FILTER_ACCEPT && node.nodeType === Node.ELEMENT_NODE) {
- ns.push();
- qname = ns.getQName(node);
- s += startElement(ns, qname, node)
++ function doMove(positions, extend, move) {
++ var left = positions, iterator = getIteratorAtCursor(), initialRect, range = (rootNode.ownerDocument.createRange()), selectionRange = cursor.getSelectedRange().cloneRange(), newRect, horizontalMovement, o, c, isForwardSelection;
++ initialRect = getVisibleRect(iterator.container(), iterator.unfilteredDomOffset(), range);
++ while(left > 0 && move()) {
++ left -= 1
+ }
- if(accept === NodeFilter.FILTER_ACCEPT || accept === NodeFilter.FILTER_SKIP) {
- child = node.firstChild;
- while(child) {
- s += serializeNode(ns, child);
- child = child.nextSibling
- }
- if(node.nodeValue) {
- s += escapeContent(node.nodeValue)
++ if(extend) {
++ c = iterator.container();
++ o = iterator.unfilteredDomOffset();
++ if(domUtils.comparePoints((selectionRange.startContainer), selectionRange.startOffset, c, o) === -1) {
++ selectionRange.setStart(c, o);
++ isForwardSelection = false
++ }else {
++ selectionRange.setEnd(c, o)
+ }
++ }else {
++ selectionRange.setStart(iterator.container(), iterator.unfilteredDomOffset());
++ selectionRange.collapse(true)
+ }
- if(qname) {
- s += "</" + qname + ">";
- ns.pop()
- }
- return s
- }
- this.filter = null;
- this.writeToString = function(node, nsmap) {
- if(!node) {
- return""
++ cursor.setSelectedRange(selectionRange, isForwardSelection);
++ iterator = getIteratorAtCursor();
++ newRect = getVisibleRect(iterator.container(), iterator.unfilteredDomOffset(), range);
++ horizontalMovement = newRect.top === initialRect.top ? true : false;
++ if(horizontalMovement || cachedXOffset === undefined) {
++ cachedXOffset = newRect.left
+ }
- var ns = new Namespaces(nsmap);
- return serializeNode(ns, node)
++ runtime.clearTimeout(timeoutHandle);
++ timeoutHandle = runtime.setTimeout(function() {
++ cachedXOffset = undefined
++ }, 2E3);
++ range.detach();
++ return positions - left
+ }
- };
- xmldom.RelaxNGParser = function RelaxNGParser() {
- var self = this, rngns = "http://relaxng.org/ns/structure/1.0", xmlnsns = "http://www.w3.org/2000/xmlns/", start, nsmap = {"http://www.w3.org/XML/1998/namespace":"xml"}, parse;
- function RelaxNGParseError(error, context) {
- this.message = function() {
- if(context) {
- error += context.nodeType === 1 ? " Element " : " Node ";
- error += context.nodeName;
- if(context.nodeValue) {
- error += " with value '" + context.nodeValue + "'"
- }
- error += "."
++ this.movePointForward = function(positions, extend) {
++ return doMove(positions, extend || false, positionIterator.nextPosition)
++ };
++ this.movePointBackward = function(positions, extend) {
++ return doMove(positions, extend || false, positionIterator.previousPosition)
++ };
++ function isPositionWalkable(filter) {
++ var iterator = getIteratorAtCursor();
++ if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
++ iterator.setUnfilteredPosition(cursor.getAnchorNode(), 0);
++ if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
++ return true
+ }
- return error
+ }
++ return false
+ }
- function splitToDuos(e) {
- if(e.e.length <= 2) {
- return e
++ function countSteps(iterator, steps, filter) {
++ var watch = new core.LoopWatchDog(1E4), positions = 0, positionsCount = 0, increment = steps >= 0 ? 1 : -1, delegate = (steps >= 0 ? iterator.nextPosition : iterator.previousPosition);
++ while(steps !== 0 && delegate()) {
++ watch.check();
++ positionsCount += increment;
++ if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
++ steps -= increment;
++ positions += positionsCount;
++ positionsCount = 0
++ }
+ }
- var o = {name:e.name, e:e.e.slice(0, 2)};
- return splitToDuos({name:e.name, e:[o].concat(e.e.slice(2))})
++ return positions
+ }
- function splitQName(name) {
- var r = name.split(":", 2), prefix = "", i;
- if(r.length === 1) {
- r = ["", r[0]]
- }else {
- prefix = r[0]
- }
- for(i in nsmap) {
- if(nsmap[i] === prefix) {
- r[0] = i
++ function convertForwardStepsBetweenFilters(stepsFilter1, filter1, filter2) {
++ var iterator = getIteratorAtCursor(), watch = new core.LoopWatchDog(1E4), pendingStepsFilter2 = 0, stepsFilter2 = 0;
++ while(stepsFilter1 > 0 && iterator.nextPosition()) {
++ watch.check();
++ if(filter2.acceptPosition(iterator) === FILTER_ACCEPT) {
++ pendingStepsFilter2 += 1;
++ if(filter1.acceptPosition(iterator) === FILTER_ACCEPT) {
++ stepsFilter2 += pendingStepsFilter2;
++ pendingStepsFilter2 = 0;
++ stepsFilter1 -= 1
++ }
+ }
+ }
- return r
++ return stepsFilter2
+ }
- function splitQNames(def) {
- var i, l = def.names ? def.names.length : 0, name, localnames = [], namespaces = [];
- for(i = 0;i < l;i += 1) {
- name = splitQName(def.names[i]);
- namespaces[i] = name[0];
- localnames[i] = name[1]
++ function convertBackwardStepsBetweenFilters(stepsFilter1, filter1, filter2) {
++ var iterator = getIteratorAtCursor(), watch = new core.LoopWatchDog(1E4), pendingStepsFilter2 = 0, stepsFilter2 = 0;
++ while(stepsFilter1 > 0 && iterator.previousPosition()) {
++ watch.check();
++ if(filter2.acceptPosition(iterator) === FILTER_ACCEPT) {
++ pendingStepsFilter2 += 1;
++ if(filter1.acceptPosition(iterator) === FILTER_ACCEPT) {
++ stepsFilter2 += pendingStepsFilter2;
++ pendingStepsFilter2 = 0;
++ stepsFilter1 -= 1
++ }
++ }
+ }
- def.localnames = localnames;
- def.namespaces = namespaces
++ return stepsFilter2
+ }
- function trim(str) {
- str = str.replace(/^\s\s*/, "");
- var ws = /\s/, i = str.length - 1;
- while(ws.test(str.charAt(i))) {
- i -= 1
- }
- return str.slice(0, i + 1)
++ function countStepsPublic(steps, filter) {
++ var iterator = getIteratorAtCursor();
++ return countSteps(iterator, steps, filter)
+ }
- function copyAttributes(atts, name, names) {
- var a = {}, i, att;
- for(i = 0;i < atts.length;i += 1) {
- att = atts.item(i);
- if(!att.namespaceURI) {
- if(att.localName === "name" && (name === "element" || name === "attribute")) {
- names.push(att.value)
- }
- if(att.localName === "name" || (att.localName === "combine" || att.localName === "type")) {
- att.value = trim(att.value)
- }
- a[att.localName] = att.value
- }else {
- if(att.namespaceURI === xmlnsns) {
- nsmap[att.value] = att.localName
- }
++ function countPositionsToClosestStep(container, offset, filter) {
++ var iterator = getIteratorAtCursor(), paragraphNode = odfUtils.getParagraphElement(iterator.getCurrentNode()), count = 0;
++ iterator.setUnfilteredPosition(container, offset);
++ if(filter.acceptPosition(iterator) !== FILTER_ACCEPT) {
++ count = countSteps(iterator, -1, filter);
++ if(count === 0 || paragraphNode && paragraphNode !== odfUtils.getParagraphElement(iterator.getCurrentNode())) {
++ iterator.setUnfilteredPosition(container, offset);
++ count = countSteps(iterator, 1, filter)
+ }
+ }
- return a
++ return count
+ }
- function parseChildren(c, e, elements, names) {
- var text = "", ce;
- while(c) {
- if(c.nodeType === Node.ELEMENT_NODE && c.namespaceURI === rngns) {
- ce = parse(c, elements, e);
- if(ce) {
- if(ce.name === "name") {
- names.push(nsmap[ce.a.ns] + ":" + ce.text);
- e.push(ce)
- }else {
- if(ce.name === "choice" && (ce.names && ce.names.length)) {
- names = names.concat(ce.names);
- delete ce.names;
- e.push(ce)
- }else {
- e.push(ce)
- }
++ function countLineSteps(filter, direction, iterator) {
++ var c = iterator.container(), steps = 0, bestContainer = null, bestOffset, bestXDiff = 10, xDiff, bestCount = 0, top, left, lastTop, rect, range = (rootNode.ownerDocument.createRange()), watch = new core.LoopWatchDog(1E4);
++ rect = getVisibleRect(c, iterator.unfilteredDomOffset(), range);
++ top = rect.top;
++ if(cachedXOffset === undefined) {
++ left = rect.left
++ }else {
++ left = cachedXOffset
++ }
++ lastTop = top;
++ while((direction < 0 ? iterator.previousPosition() : iterator.nextPosition()) === true) {
++ watch.check();
++ if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
++ steps += 1;
++ c = iterator.container();
++ rect = getVisibleRect(c, iterator.unfilteredDomOffset(), range);
++ if(rect.top !== top) {
++ if(rect.top !== lastTop && lastTop !== top) {
++ break
++ }
++ lastTop = rect.top;
++ xDiff = Math.abs(left - rect.left);
++ if(bestContainer === null || xDiff < bestXDiff) {
++ bestContainer = c;
++ bestOffset = iterator.unfilteredDomOffset();
++ bestXDiff = xDiff;
++ bestCount = steps
+ }
- }
- }else {
- if(c.nodeType === Node.TEXT_NODE) {
- text += c.nodeValue
+ }
+ }
- c = c.nextSibling
+ }
- return text
++ if(bestContainer !== null) {
++ iterator.setUnfilteredPosition(bestContainer, (bestOffset));
++ steps = bestCount
++ }else {
++ steps = 0
++ }
++ range.detach();
++ return steps
+ }
- function combineDefines(combine, name, e, siblings) {
- var i, ce;
- for(i = 0;siblings && i < siblings.length;i += 1) {
- ce = siblings[i];
- if(ce.name === "define" && (ce.a && ce.a.name === name)) {
- ce.e = [{name:combine, e:ce.e.concat(e)}];
- return ce
++ function countLinesSteps(lines, filter) {
++ var iterator = getIteratorAtCursor(), stepCount = 0, steps = 0, direction = lines < 0 ? -1 : 1;
++ lines = Math.abs(lines);
++ while(lines > 0) {
++ stepCount += countLineSteps(filter, direction, iterator);
++ if(stepCount === 0) {
++ break
+ }
++ steps += stepCount;
++ lines -= 1
+ }
- return null
++ return steps * direction
+ }
- parse = function parse(element, elements, siblings) {
- var e = [], a, ce, i, text, name = element.localName, names = [];
- a = copyAttributes(element.attributes, name, names);
- a.combine = a.combine || undefined;
- text = parseChildren(element.firstChild, e, elements, names);
- if(name !== "value" && name !== "param") {
- text = /^\s*([\s\S]*\S)?\s*$/.exec(text)[1]
- }
- if(name === "value" && a.type === undefined) {
- a.type = "token";
- a.datatypeLibrary = ""
- }
- if((name === "attribute" || name === "element") && a.name !== undefined) {
- i = splitQName(a.name);
- e = [{name:"name", text:i[1], a:{ns:i[0]}}].concat(e);
- delete a.name
- }
- if(name === "name" || (name === "nsName" || name === "value")) {
- if(a.ns === undefined) {
- a.ns = ""
- }
++ function countStepsToLineBoundary(direction, filter) {
++ var fnNextPos, increment, lastRect, rect, onSameLine, iterator = getIteratorAtCursor(), paragraphNode = odfUtils.getParagraphElement(iterator.getCurrentNode()), steps = 0, range = (rootNode.ownerDocument.createRange());
++ if(direction < 0) {
++ fnNextPos = iterator.previousPosition;
++ increment = -1
+ }else {
- delete a.ns
++ fnNextPos = iterator.nextPosition;
++ increment = 1
+ }
- if(name === "name") {
- i = splitQName(text);
- a.ns = i[0];
- text = i[1]
++ lastRect = getVisibleRect(iterator.container(), iterator.unfilteredDomOffset(), range);
++ while(fnNextPos.call(iterator)) {
++ if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
++ if(odfUtils.getParagraphElement(iterator.getCurrentNode()) !== paragraphNode) {
++ break
++ }
++ rect = getVisibleRect(iterator.container(), iterator.unfilteredDomOffset(), range);
++ if(rect.bottom !== lastRect.bottom) {
++ onSameLine = rect.top >= lastRect.top && rect.bottom < lastRect.bottom || rect.top <= lastRect.top && rect.bottom > lastRect.bottom;
++ if(!onSameLine) {
++ break
++ }
++ }
++ steps += increment;
++ lastRect = rect
++ }
+ }
- if(e.length > 1 && (name === "define" || (name === "oneOrMore" || (name === "zeroOrMore" || (name === "optional" || (name === "list" || name === "mixed")))))) {
- e = [{name:"group", e:splitToDuos({name:"group", e:e}).e}]
++ range.detach();
++ return steps
++ }
++ function countStepsToPosition(targetNode, targetOffset, filter) {
++ runtime.assert(targetNode !== null, "SelectionMover.countStepsToPosition called with element===null");
++ var iterator = getIteratorAtCursor(), c = iterator.container(), o = iterator.unfilteredDomOffset(), steps = 0, watch = new core.LoopWatchDog(1E4), comparison;
++ iterator.setUnfilteredPosition(targetNode, targetOffset);
++ while(filter.acceptPosition(iterator) !== FILTER_ACCEPT && iterator.previousPosition()) {
++ watch.check()
+ }
- if(e.length > 2 && name === "element") {
- e = [e[0]].concat({name:"group", e:splitToDuos({name:"group", e:e.slice(1)}).e})
++ targetNode = iterator.container();
++ runtime.assert(Boolean(targetNode), "SelectionMover.countStepsToPosition: positionIterator.container() returned null");
++ targetOffset = iterator.unfilteredDomOffset();
++ iterator.setUnfilteredPosition(c, o);
++ while(filter.acceptPosition(iterator) !== FILTER_ACCEPT && iterator.previousPosition()) {
++ watch.check()
+ }
- if(e.length === 1 && name === "attribute") {
- e.push({name:"text", text:text})
- }
- if(e.length === 1 && (name === "choice" || (name === "group" || name === "interleave"))) {
- name = e[0].name;
- names = e[0].names;
- a = e[0].a;
- text = e[0].text;
- e = e[0].e
- }else {
- if(e.length > 2 && (name === "choice" || (name === "group" || name === "interleave"))) {
- e = splitToDuos({name:name, e:e}).e
- }
- }
- if(name === "mixed") {
- name = "interleave";
- e = [e[0], {name:"text"}]
- }
- if(name === "optional") {
- name = "choice";
- e = [e[0], {name:"empty"}]
- }
- if(name === "zeroOrMore") {
- name = "choice";
- e = [{name:"oneOrMore", e:[e[0]]}, {name:"empty"}]
- }
- if(name === "define" && a.combine) {
- ce = combineDefines(a.combine, a.name, e, siblings);
- if(ce) {
- return
- }
- }
- ce = {name:name};
- if(e && e.length > 0) {
- ce.e = e
- }
- for(i in a) {
- if(a.hasOwnProperty(i)) {
- ce.a = a;
- break
- }
- }
- if(text !== undefined) {
- ce.text = text
- }
- if(names && names.length > 0) {
- ce.names = names
- }
- if(name === "element") {
- ce.id = elements.length;
- elements.push(ce);
- ce = {name:"elementref", id:ce.id}
- }
- return ce
- };
- function resolveDefines(def, defines) {
- var i = 0, e, defs, end, name = def.name;
- while(def.e && i < def.e.length) {
- e = def.e[i];
- if(e.name === "ref") {
- defs = defines[e.a.name];
- if(!defs) {
- throw e.a.name + " was not defined.";
- }
- end = def.e.slice(i + 1);
- def.e = def.e.slice(0, i);
- def.e = def.e.concat(defs.e);
- def.e = def.e.concat(end)
- }else {
- i += 1;
- resolveDefines(e, defines)
- }
- }
- e = def.e;
- if(name === "choice") {
- if(!e || (!e[1] || e[1].name === "empty")) {
- if(!e || (!e[0] || e[0].name === "empty")) {
- delete def.e;
- def.name = "empty"
- }else {
- e[1] = e[0];
- e[0] = {name:"empty"}
- }
- }
- }
- if(name === "group" || name === "interleave") {
- if(e[0].name === "empty") {
- if(e[1].name === "empty") {
- delete def.e;
- def.name = "empty"
- }else {
- name = def.name = e[1].name;
- def.names = e[1].names;
- e = def.e = e[1].e
++ comparison = domUtils.comparePoints(targetNode, targetOffset, iterator.container(), iterator.unfilteredDomOffset());
++ if(comparison < 0) {
++ while(iterator.nextPosition()) {
++ watch.check();
++ if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
++ steps += 1
+ }
- }else {
- if(e[1].name === "empty") {
- name = def.name = e[0].name;
- def.names = e[0].names;
- e = def.e = e[0].e
++ if(iterator.container() === targetNode && iterator.unfilteredDomOffset() === targetOffset) {
++ return steps
+ }
+ }
- }
- if(name === "oneOrMore" && e[0].name === "empty") {
- delete def.e;
- def.name = "empty"
- }
- if(name === "attribute") {
- splitQNames(def)
- }
- if(name === "interleave") {
- if(e[0].name === "interleave") {
- if(e[1].name === "interleave") {
- e = def.e = e[0].e.concat(e[1].e)
- }else {
- e = def.e = [e[1]].concat(e[0].e)
- }
- }else {
- if(e[1].name === "interleave") {
- e = def.e = [e[0]].concat(e[1].e)
++ }else {
++ if(comparison > 0) {
++ while(iterator.previousPosition()) {
++ watch.check();
++ if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
++ steps -= 1;
++ if(iterator.container() === targetNode && iterator.unfilteredDomOffset() === targetOffset) {
++ break
++ }
++ }
+ }
+ }
+ }
++ return steps
+ }
- function resolveElements(def, elements) {
- var i = 0, e;
- while(def.e && i < def.e.length) {
- e = def.e[i];
- if(e.name === "elementref") {
- e.id = e.id || 0;
- def.e[i] = elements[e.id]
- }else {
- if(e.name !== "element") {
- resolveElements(e, elements)
- }
- }
- i += 1
- }
++ this.getStepCounter = function() {
++ return{countSteps:countStepsPublic, convertForwardStepsBetweenFilters:convertForwardStepsBetweenFilters, convertBackwardStepsBetweenFilters:convertBackwardStepsBetweenFilters, countLinesSteps:countLinesSteps, countStepsToLineBoundary:countStepsToLineBoundary, countStepsToPosition:countStepsToPosition, isPositionWalkable:isPositionWalkable, countPositionsToNearestStep:countPositionsToClosestStep}
++ };
++ function init() {
++ positionIterator = gui.SelectionMover.createPositionIterator(rootNode);
++ var range = rootNode.ownerDocument.createRange();
++ range.setStart(positionIterator.container(), positionIterator.unfilteredDomOffset());
++ range.collapse(true);
++ cursor.setSelectedRange(range)
+ }
- function main(dom, callback) {
- var elements = [], grammar = parse(dom && dom.documentElement, elements, undefined), i, e, defines = {};
- for(i = 0;i < grammar.e.length;i += 1) {
- e = grammar.e[i];
- if(e.name === "define") {
- defines[e.a.name] = e
- }else {
- if(e.name === "start") {
- start = e
- }
- }
- }
- if(!start) {
- return[new RelaxNGParseError("No Relax NG start element was found.")]
- }
- resolveDefines(start, defines);
- for(i in defines) {
- if(defines.hasOwnProperty(i)) {
- resolveDefines(defines[i], defines)
++ init()
++};
++gui.SelectionMover.createPositionIterator = function(rootNode) {
++ function CursorFilter() {
++ this.acceptNode = function(node) {
++ if(!node || (node.namespaceURI === "urn:webodf:names:cursor" || node.namespaceURI === "urn:webodf:names:editinfo")) {
++ return NodeFilter.FILTER_REJECT
+ }
++ return NodeFilter.FILTER_ACCEPT
+ }
- for(i = 0;i < elements.length;i += 1) {
- resolveDefines(elements[i], defines)
- }
- if(callback) {
- self.rootPattern = callback(start.e[0], elements)
++ }
++ var filter = new CursorFilter;
++ return new core.PositionIterator(rootNode, 5, filter, false)
++};
++(function() {
++ return gui.SelectionMover
++})();
++/*
++
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ This file is part of WebODF.
++
++ WebODF is free software: you can redistribute it and/or modify it
++ under the terms of the GNU Affero General Public License (GNU AGPL)
++ as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version.
++
++ WebODF is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU Affero General Public License for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
++ @licend
++
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++runtime.loadClass("odf.Namespaces");
++runtime.loadClass("core.DomUtils");
++odf.MetadataManager = function MetadataManager(metaElement) {
++ var domUtils = new core.DomUtils, metadata = {};
++ function setMetadata(setProperties, removedProperties) {
++ if(setProperties) {
++ Object.keys(setProperties).forEach(function(key) {
++ metadata[key] = setProperties[key]
++ });
++ domUtils.mapKeyValObjOntoNode(metaElement, setProperties, odf.Namespaces.lookupNamespaceURI)
+ }
- resolveElements(start, elements);
- for(i = 0;i < elements.length;i += 1) {
- resolveElements(elements[i], elements)
++ if(removedProperties) {
++ removedProperties.forEach(function(name) {
++ delete metadata[name]
++ });
++ domUtils.removeKeyElementsFromNode(metaElement, removedProperties, odf.Namespaces.lookupNamespaceURI)
+ }
- self.start = start;
- self.elements = elements;
- self.nsmap = nsmap;
- return null
+ }
- this.parseRelaxNGDOM = main
++ this.setMetadata = setMetadata;
++ this.incrementEditingCycles = function() {
++ var cycles = parseInt(metadata["meta:editing-cycles"] || 0, 10) + 1;
++ setMetadata({"meta:editing-cycles":cycles}, null)
++ };
++ function init() {
++ metadata = domUtils.getKeyValRepresentationOfNode(metaElement, odf.Namespaces.lookupPrefix)
++ }
++ init()
+};
- runtime.loadClass("xmldom.RelaxNGParser");
- xmldom.RelaxNG = function RelaxNG() {
- var xmlnsns = "http://www.w3.org/2000/xmlns/", createChoice, createInterleave, createGroup, createAfter, createOneOrMore, createValue, createAttribute, createNameClass, createData, makePattern, notAllowed = {type:"notAllowed", nullable:false, hash:"notAllowed", textDeriv:function() {
- return notAllowed
- }, startTagOpenDeriv:function() {
- return notAllowed
- }, attDeriv:function() {
- return notAllowed
- }, startTagCloseDeriv:function() {
- return notAllowed
- }, endTagDeriv:function() {
- return notAllowed
- }}, empty = {type:"empty", nullable:true, hash:"empty", textDeriv:function() {
- return notAllowed
- }, startTagOpenDeriv:function() {
- return notAllowed
- }, attDeriv:function() {
- return notAllowed
- }, startTagCloseDeriv:function() {
- return empty
- }, endTagDeriv:function() {
- return notAllowed
- }}, text = {type:"text", nullable:true, hash:"text", textDeriv:function() {
- return text
- }, startTagOpenDeriv:function() {
- return notAllowed
- }, attDeriv:function() {
- return notAllowed
- }, startTagCloseDeriv:function() {
- return text
- }, endTagDeriv:function() {
- return notAllowed
- }}, applyAfter, childDeriv, rootPattern;
- function memoize0arg(func) {
- return function() {
- var cache;
- return function() {
- if(cache === undefined) {
- cache = func()
- }
- return cache
- }
- }()
- }
- function memoize1arg(type, func) {
- return function() {
- var cache = {}, cachecount = 0;
- return function(a) {
- var ahash = a.hash || a.toString(), v;
- v = cache[ahash];
- if(v !== undefined) {
- return v
- }
- cache[ahash] = v = func(a);
- v.hash = type + cachecount.toString();
- cachecount += 1;
- return v
++/*
++
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++odf.OdfNodeFilter = function OdfNodeFilter() {
++ this.acceptNode = function(node) {
++ var result;
++ if(node.namespaceURI === "http://www.w3.org/1999/xhtml") {
++ result = NodeFilter.FILTER_SKIP
++ }else {
++ if(node.namespaceURI && node.namespaceURI.match(/^urn:webodf:/)) {
++ result = NodeFilter.FILTER_REJECT
++ }else {
++ result = NodeFilter.FILTER_ACCEPT
+ }
- }()
++ }
++ return result
+ }
- function memoizeNode(func) {
- return function() {
- var cache = {};
- return function(node) {
- var v, m;
- m = cache[node.localName];
- if(m === undefined) {
- cache[node.localName] = m = {}
++};
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++runtime.loadClass("odf.Namespaces");
++runtime.loadClass("odf.OdfUtils");
++runtime.loadClass("xmldom.XPath");
++runtime.loadClass("core.CSSUnits");
++odf.StyleTreeNode = function StyleTreeNode(element) {
++ this.derivedStyles = {};
++ this.element = element
++};
++odf.Style2CSS = function Style2CSS() {
++ var drawns = odf.Namespaces.drawns, fons = odf.Namespaces.fons, officens = odf.Namespaces.officens, stylens = odf.Namespaces.stylens, svgns = odf.Namespaces.svgns, tablens = odf.Namespaces.tablens, textns = odf.Namespaces.textns, xlinkns = odf.Namespaces.xlinkns, presentationns = odf.Namespaces.presentationns, familynamespaceprefixes = {"graphic":"draw", "drawing-page":"draw", "paragraph":"text", "presentation":"presentation", "ruby":"text", "section":"text", "table":"table", "table-c [...]
++ "table-column":"table", "table-row":"table", "text":"text", "list":"text", "page":"office"}, familytagnames = {"graphic":["circle", "connected", "control", "custom-shape", "ellipse", "frame", "g", "line", "measure", "page", "page-thumbnail", "path", "polygon", "polyline", "rect", "regular-polygon"], "paragraph":["alphabetical-index-entry-template", "h", "illustration-index-entry-template", "index-source-style", "object-index-entry-template", "p", "table-index-entry-template", "table-o [...]
++ "user-index-entry-template"], "presentation":["caption", "circle", "connector", "control", "custom-shape", "ellipse", "frame", "g", "line", "measure", "page-thumbnail", "path", "polygon", "polyline", "rect", "regular-polygon"], "drawing-page":["caption", "circle", "connector", "control", "page", "custom-shape", "ellipse", "frame", "g", "line", "measure", "page-thumbnail", "path", "polygon", "polyline", "rect", "regular-polygon"], "ruby":["ruby", "ruby-text"], "section":["alphabetical- [...]
++ "illustration-index", "index-title", "object-index", "section", "table-of-content", "table-index", "user-index"], "table":["background", "table"], "table-cell":["body", "covered-table-cell", "even-columns", "even-rows", "first-column", "first-row", "last-column", "last-row", "odd-columns", "odd-rows", "table-cell"], "table-column":["table-column"], "table-row":["table-row"], "text":["a", "index-entry-chapter", "index-entry-link-end", "index-entry-link-start", "index-entry-page-number" [...]
++ "index-entry-tab-stop", "index-entry-text", "index-title-template", "linenumbering-configuration", "list-level-style-number", "list-level-style-bullet", "outline-level-style", "span"], "list":["list-item"]}, textPropertySimpleMapping = [[fons, "color", "color"], [fons, "background-color", "background-color"], [fons, "font-weight", "font-weight"], [fons, "font-style", "font-style"]], bgImageSimpleMapping = [[stylens, "repeat", "background-repeat"]], paragraphPropertySimpleMapping = [[f [...]
++ "background-color"], [fons, "text-align", "text-align"], [fons, "text-indent", "text-indent"], [fons, "padding", "padding"], [fons, "padding-left", "padding-left"], [fons, "padding-right", "padding-right"], [fons, "padding-top", "padding-top"], [fons, "padding-bottom", "padding-bottom"], [fons, "border-left", "border-left"], [fons, "border-right", "border-right"], [fons, "border-top", "border-top"], [fons, "border-bottom", "border-bottom"], [fons, "margin", "margin"], [fons, "margin-l [...]
++ [fons, "margin-right", "margin-right"], [fons, "margin-top", "margin-top"], [fons, "margin-bottom", "margin-bottom"], [fons, "border", "border"]], graphicPropertySimpleMapping = [[fons, "background-color", "background-color"], [fons, "min-height", "min-height"], [drawns, "stroke", "border"], [svgns, "stroke-color", "border-color"], [svgns, "stroke-width", "border-width"], [fons, "border", "border"], [fons, "border-left", "border-left"], [fons, "border-right", "border-right"], [fons, " [...]
++ "border-top"], [fons, "border-bottom", "border-bottom"]], tablecellPropertySimpleMapping = [[fons, "background-color", "background-color"], [fons, "border-left", "border-left"], [fons, "border-right", "border-right"], [fons, "border-top", "border-top"], [fons, "border-bottom", "border-bottom"], [fons, "border", "border"]], tablecolumnPropertySimpleMapping = [[stylens, "column-width", "width"]], tablerowPropertySimpleMapping = [[stylens, "row-height", "height"], [fons, "keep-together", [...]
++ [[stylens, "width", "width"], [fons, "margin-left", "margin-left"], [fons, "margin-right", "margin-right"], [fons, "margin-top", "margin-top"], [fons, "margin-bottom", "margin-bottom"]], pageContentPropertySimpleMapping = [[fons, "background-color", "background-color"], [fons, "padding", "padding"], [fons, "padding-left", "padding-left"], [fons, "padding-right", "padding-right"], [fons, "padding-top", "padding-top"], [fons, "padding-bottom", "padding-bottom"], [fons, "border", "border [...]
++ "border-left", "border-left"], [fons, "border-right", "border-right"], [fons, "border-top", "border-top"], [fons, "border-bottom", "border-bottom"], [fons, "margin", "margin"], [fons, "margin-left", "margin-left"], [fons, "margin-right", "margin-right"], [fons, "margin-top", "margin-top"], [fons, "margin-bottom", "margin-bottom"]], pageSizePropertySimpleMapping = [[fons, "page-width", "width"], [fons, "page-height", "height"]], borderPropertyMap = {"border":true, "border-left":true, " [...]
++ "border-top":true, "border-bottom":true, "stroke-width":true}, fontFaceDeclsMap = {}, utils = new odf.OdfUtils, documentType, odfRoot, defaultFontSize, xpath = xmldom.XPath, cssUnits = new core.CSSUnits;
++ function getStyleMap(stylesnode) {
++ var node, name, family, style, stylemap = {};
++ if(!stylesnode) {
++ return stylemap
++ }
++ node = stylesnode.firstElementChild;
++ while(node) {
++ if(node.namespaceURI === stylens && (node.localName === "style" || node.localName === "default-style")) {
++ family = node.getAttributeNS(stylens, "family")
++ }else {
++ if(node.namespaceURI === textns && node.localName === "list-style") {
++ family = "list"
+ }else {
- v = m[node.namespaceURI];
- if(v !== undefined) {
- return v
++ if(node.namespaceURI === stylens && (node.localName === "page-layout" || node.localName === "default-page-layout")) {
++ family = "page"
++ }else {
++ family = undefined
+ }
+ }
- m[node.namespaceURI] = v = func(node);
- return v
+ }
- }()
- }
- function memoize2arg(type, fastfunc, func) {
- return function() {
- var cache = {}, cachecount = 0;
- return function(a, b) {
- var v = fastfunc && fastfunc(a, b), ahash, bhash, m;
- if(v !== undefined) {
- return v
++ if(family) {
++ name = node.getAttributeNS(stylens, "name");
++ if(!name) {
++ name = ""
+ }
- ahash = a.hash || a.toString();
- bhash = b.hash || b.toString();
- m = cache[ahash];
- if(m === undefined) {
- cache[ahash] = m = {}
++ if(stylemap.hasOwnProperty(family)) {
++ style = stylemap[family]
+ }else {
- v = m[bhash];
- if(v !== undefined) {
- return v
- }
++ stylemap[family] = style = {}
+ }
- m[bhash] = v = func(a, b);
- v.hash = type + cachecount.toString();
- cachecount += 1;
- return v
++ style[name] = node
+ }
- }()
++ node = node.nextElementSibling
++ }
++ return stylemap
+ }
- function unorderedMemoize2arg(type, fastfunc, func) {
- return function() {
- var cache = {}, cachecount = 0;
- return function(a, b) {
- var v = fastfunc && fastfunc(a, b), ahash, bhash, m;
- if(v !== undefined) {
- return v
- }
- ahash = a.hash || a.toString();
- bhash = b.hash || b.toString();
- if(ahash < bhash) {
- m = ahash;
- ahash = bhash;
- bhash = m;
- m = a;
- a = b;
- b = m
- }
- m = cache[ahash];
- if(m === undefined) {
- cache[ahash] = m = {}
- }else {
- v = m[bhash];
- if(v !== undefined) {
- return v
- }
++ function findStyle(stylestree, name) {
++ if(stylestree.hasOwnProperty(name)) {
++ return stylestree[name]
++ }
++ var n, style = null;
++ for(n in stylestree) {
++ if(stylestree.hasOwnProperty(n)) {
++ style = findStyle(stylestree[n].derivedStyles, name);
++ if(style) {
++ break
+ }
- m[bhash] = v = func(a, b);
- v.hash = type + cachecount.toString();
- cachecount += 1;
- return v
+ }
- }()
++ }
++ return style
+ }
- function getUniqueLeaves(leaves, pattern) {
- if(pattern.p1.type === "choice") {
- getUniqueLeaves(leaves, pattern.p1)
- }else {
- leaves[pattern.p1.hash] = pattern.p1
++ function addStyleToStyleTree(stylename, stylesmap, stylestree) {
++ var style, parentname, parentstyle;
++ if(!stylesmap.hasOwnProperty(stylename)) {
++ return null
+ }
- if(pattern.p2.type === "choice") {
- getUniqueLeaves(leaves, pattern.p2)
++ style = new odf.StyleTreeNode(stylesmap[stylename]);
++ parentname = style.element.getAttributeNS(stylens, "parent-style-name");
++ parentstyle = null;
++ if(parentname) {
++ parentstyle = findStyle(stylestree, parentname) || addStyleToStyleTree(parentname, stylesmap, stylestree)
++ }
++ if(parentstyle) {
++ parentstyle.derivedStyles[stylename] = style
+ }else {
- leaves[pattern.p2.hash] = pattern.p2
++ stylestree[stylename] = style
+ }
++ delete stylesmap[stylename];
++ return style
+ }
- createChoice = memoize2arg("choice", function(p1, p2) {
- if(p1 === notAllowed) {
- return p2
++ function addStyleMapToStyleTree(stylesmap, stylestree) {
++ var name;
++ for(name in stylesmap) {
++ if(stylesmap.hasOwnProperty(name)) {
++ addStyleToStyleTree(name, stylesmap, stylestree)
++ }
+ }
- if(p2 === notAllowed) {
- return p1
++ }
++ function createSelector(family, name) {
++ var prefix = familynamespaceprefixes[family], namepart, selector;
++ if(prefix === undefined) {
++ return null
+ }
- if(p1 === p2) {
- return p1
++ if(name) {
++ namepart = "[" + prefix + '|style-name="' + name + '"]'
++ }else {
++ namepart = ""
+ }
- }, function(p1, p2) {
- function makeChoice(p1, p2) {
- return{type:"choice", p1:p1, p2:p2, nullable:p1.nullable || p2.nullable, textDeriv:function(context, text) {
- return createChoice(p1.textDeriv(context, text), p2.textDeriv(context, text))
- }, startTagOpenDeriv:memoizeNode(function(node) {
- return createChoice(p1.startTagOpenDeriv(node), p2.startTagOpenDeriv(node))
- }), attDeriv:function(context, attribute) {
- return createChoice(p1.attDeriv(context, attribute), p2.attDeriv(context, attribute))
- }, startTagCloseDeriv:memoize0arg(function() {
- return createChoice(p1.startTagCloseDeriv(), p2.startTagCloseDeriv())
- }), endTagDeriv:memoize0arg(function() {
- return createChoice(p1.endTagDeriv(), p2.endTagDeriv())
- })}
- }
- var leaves = {}, i;
- getUniqueLeaves(leaves, {p1:p1, p2:p2});
- p1 = undefined;
- p2 = undefined;
- for(i in leaves) {
- if(leaves.hasOwnProperty(i)) {
- if(p1 === undefined) {
- p1 = leaves[i]
- }else {
- if(p2 === undefined) {
- p2 = leaves[i]
- }else {
- p2 = createChoice(p2, leaves[i])
- }
- }
++ if(prefix === "presentation") {
++ prefix = "draw";
++ if(name) {
++ namepart = '[presentation|style-name="' + name + '"]'
++ }else {
++ namepart = ""
+ }
+ }
- return makeChoice(p1, p2)
- });
- createInterleave = unorderedMemoize2arg("interleave", function(p1, p2) {
- if(p1 === notAllowed || p2 === notAllowed) {
- return notAllowed
- }
- if(p1 === empty) {
- return p2
- }
- if(p2 === empty) {
- return p1
- }
- }, function(p1, p2) {
- return{type:"interleave", p1:p1, p2:p2, nullable:p1.nullable && p2.nullable, textDeriv:function(context, text) {
- return createChoice(createInterleave(p1.textDeriv(context, text), p2), createInterleave(p1, p2.textDeriv(context, text)))
- }, startTagOpenDeriv:memoizeNode(function(node) {
- return createChoice(applyAfter(function(p) {
- return createInterleave(p, p2)
- }, p1.startTagOpenDeriv(node)), applyAfter(function(p) {
- return createInterleave(p1, p)
- }, p2.startTagOpenDeriv(node)))
- }), attDeriv:function(context, attribute) {
- return createChoice(createInterleave(p1.attDeriv(context, attribute), p2), createInterleave(p1, p2.attDeriv(context, attribute)))
- }, startTagCloseDeriv:memoize0arg(function() {
- return createInterleave(p1.startTagCloseDeriv(), p2.startTagCloseDeriv())
- })}
- });
- createGroup = memoize2arg("group", function(p1, p2) {
- if(p1 === notAllowed || p2 === notAllowed) {
- return notAllowed
- }
- if(p1 === empty) {
- return p2
- }
- if(p2 === empty) {
- return p1
++ selector = prefix + "|" + familytagnames[family].join(namepart + "," + prefix + "|") + namepart;
++ return selector
++ }
++ function getSelectors(family, name, node) {
++ var selectors = [], ss, derivedStyles = node.derivedStyles, n;
++ ss = createSelector(family, name);
++ if(ss !== null) {
++ selectors.push(ss)
+ }
- }, function(p1, p2) {
- return{type:"group", p1:p1, p2:p2, nullable:p1.nullable && p2.nullable, textDeriv:function(context, text) {
- var p = createGroup(p1.textDeriv(context, text), p2);
- if(p1.nullable) {
- return createChoice(p, p2.textDeriv(context, text))
- }
- return p
- }, startTagOpenDeriv:function(node) {
- var x = applyAfter(function(p) {
- return createGroup(p, p2)
- }, p1.startTagOpenDeriv(node));
- if(p1.nullable) {
- return createChoice(x, p2.startTagOpenDeriv(node))
++ for(n in derivedStyles) {
++ if(derivedStyles.hasOwnProperty(n)) {
++ ss = getSelectors(family, n, derivedStyles[n]);
++ selectors = selectors.concat(ss)
+ }
- return x
- }, attDeriv:function(context, attribute) {
- return createChoice(createGroup(p1.attDeriv(context, attribute), p2), createGroup(p1, p2.attDeriv(context, attribute)))
- }, startTagCloseDeriv:memoize0arg(function() {
- return createGroup(p1.startTagCloseDeriv(), p2.startTagCloseDeriv())
- })}
- });
- createAfter = memoize2arg("after", function(p1, p2) {
- if(p1 === notAllowed || p2 === notAllowed) {
- return notAllowed
- }
- }, function(p1, p2) {
- return{type:"after", p1:p1, p2:p2, nullable:false, textDeriv:function(context, text) {
- return createAfter(p1.textDeriv(context, text), p2)
- }, startTagOpenDeriv:memoizeNode(function(node) {
- return applyAfter(function(p) {
- return createAfter(p, p2)
- }, p1.startTagOpenDeriv(node))
- }), attDeriv:function(context, attribute) {
- return createAfter(p1.attDeriv(context, attribute), p2)
- }, startTagCloseDeriv:memoize0arg(function() {
- return createAfter(p1.startTagCloseDeriv(), p2)
- }), endTagDeriv:memoize0arg(function() {
- return p1.nullable ? p2 : notAllowed
- })}
- });
- createOneOrMore = memoize1arg("oneormore", function(p) {
- if(p === notAllowed) {
- return notAllowed
+ }
- return{type:"oneOrMore", p:p, nullable:p.nullable, textDeriv:function(context, text) {
- return createGroup(p.textDeriv(context, text), createChoice(this, empty))
- }, startTagOpenDeriv:function(node) {
- var oneOrMore = this;
- return applyAfter(function(pf) {
- return createGroup(pf, createChoice(oneOrMore, empty))
- }, p.startTagOpenDeriv(node))
- }, attDeriv:function(context, attribute) {
- var oneOrMore = this;
- return createGroup(p.attDeriv(context, attribute), createChoice(oneOrMore, empty))
- }, startTagCloseDeriv:memoize0arg(function() {
- return createOneOrMore(p.startTagCloseDeriv())
- })}
- });
- function createElement(nc, p) {
- return{type:"element", nc:nc, nullable:false, textDeriv:function() {
- return notAllowed
- }, startTagOpenDeriv:function(node) {
- if(nc.contains(node)) {
- return createAfter(p, empty)
- }
- return notAllowed
- }, attDeriv:function() {
- return notAllowed
- }, startTagCloseDeriv:function() {
- return this
- }}
- }
- function valueMatch(context, pattern, text) {
- return pattern.nullable && /^\s+$/.test(text) || pattern.textDeriv(context, text).nullable
++ return selectors
+ }
- createAttribute = memoize2arg("attribute", undefined, function(nc, p) {
- return{type:"attribute", nullable:false, nc:nc, p:p, attDeriv:function(context, attribute) {
- if(nc.contains(attribute) && valueMatch(context, p, attribute.nodeValue)) {
- return empty
++ function getDirectChild(node, ns, name) {
++ var e = node && node.firstElementChild;
++ while(e) {
++ if(e.namespaceURI === ns && e.localName === name) {
++ break
+ }
- return notAllowed
- }, startTagCloseDeriv:function() {
- return notAllowed
- }}
- });
- function createList() {
- return{type:"list", nullable:false, hash:"list", textDeriv:function() {
- return empty
- }}
++ e = e.nextElementSibling
++ }
++ return e
+ }
- createValue = memoize1arg("value", function(value) {
- return{type:"value", nullable:false, value:value, textDeriv:function(context, text) {
- return text === value ? empty : notAllowed
- }, attDeriv:function() {
- return notAllowed
- }, startTagCloseDeriv:function() {
- return this
- }}
- });
- createData = memoize1arg("data", function(type) {
- return{type:"data", nullable:false, dataType:type, textDeriv:function() {
- return empty
- }, attDeriv:function() {
- return notAllowed
- }, startTagCloseDeriv:function() {
- return this
- }}
- });
- applyAfter = function applyAfter(f, p) {
- var result;
- if(p.type === "after") {
- result = createAfter(p.p1, f(p.p2))
++ function fixBorderWidth(value) {
++ var index = value.indexOf(" "), width, theRestOfBorderAttributes;
++ if(index !== -1) {
++ width = value.substring(0, index);
++ theRestOfBorderAttributes = value.substring(index)
+ }else {
- if(p.type === "choice") {
- result = createChoice(applyAfter(f, p.p1), applyAfter(f, p.p2))
- }else {
- result = p
- }
- }
- return result
- };
- function attsDeriv(context, pattern, attributes, position) {
- if(pattern === notAllowed) {
- return notAllowed
- }
- if(position >= attributes.length) {
- return pattern
- }
- if(position === 0) {
- position = 0
++ width = value;
++ theRestOfBorderAttributes = ""
+ }
- var a = attributes.item(position);
- while(a.namespaceURI === xmlnsns) {
- position += 1;
- if(position >= attributes.length) {
- return pattern
- }
- a = attributes.item(position)
++ width = utils.parseLength(width);
++ if(width && (width.unit === "pt" && width.value < 0.75)) {
++ value = "0.75pt" + theRestOfBorderAttributes
+ }
- a = attsDeriv(context, pattern.attDeriv(context, attributes.item(position)), attributes, position + 1);
- return a
++ return value
+ }
- function childrenDeriv(context, pattern, walker) {
- var element = walker.currentNode, childNode = walker.firstChild(), childNodes = [], i, p;
- while(childNode) {
- if(childNode.nodeType === Node.ELEMENT_NODE) {
- childNodes.push(childNode)
- }else {
- if(childNode.nodeType === Node.TEXT_NODE && !/^\s*$/.test(childNode.nodeValue)) {
- childNodes.push(childNode.nodeValue)
++ function applySimpleMapping(props, mapping) {
++ var rule = "", i, r, value;
++ for(i = 0;i < mapping.length;i += 1) {
++ r = mapping[i];
++ value = props.getAttributeNS(r[0], r[1]);
++ if(value) {
++ value = value.trim();
++ if(borderPropertyMap.hasOwnProperty(r[1])) {
++ value = fixBorderWidth(value)
+ }
- }
- childNode = walker.nextSibling()
- }
- if(childNodes.length === 0) {
- childNodes = [""]
- }
- p = pattern;
- for(i = 0;p !== notAllowed && i < childNodes.length;i += 1) {
- childNode = childNodes[i];
- if(typeof childNode === "string") {
- if(/^\s*$/.test(childNode)) {
- p = createChoice(p, p.textDeriv(context, childNode))
- }else {
- p = p.textDeriv(context, childNode)
++ if(r[2]) {
++ rule += r[2] + ":" + value + ";"
+ }
- }else {
- walker.currentNode = childNode;
- p = childDeriv(context, p, walker)
+ }
+ }
- walker.currentNode = element;
- return p
++ return rule
+ }
- childDeriv = function childDeriv(context, pattern, walker) {
- var childNode = walker.currentNode, p;
- p = pattern.startTagOpenDeriv(childNode);
- p = attsDeriv(context, p, childNode.attributes, 0);
- p = p.startTagCloseDeriv();
- p = childrenDeriv(context, p, walker);
- p = p.endTagDeriv();
- return p
- };
- function addNames(name, ns, pattern) {
- if(pattern.e[0].a) {
- name.push(pattern.e[0].text);
- ns.push(pattern.e[0].a.ns)
- }else {
- addNames(name, ns, pattern.e[0])
++ function getFontSize(styleNode) {
++ var props = getDirectChild(styleNode, stylens, "text-properties");
++ if(props) {
++ return utils.parseFoFontSize(props.getAttributeNS(fons, "font-size"))
+ }
- if(pattern.e[1].a) {
- name.push(pattern.e[1].text);
- ns.push(pattern.e[1].a.ns)
++ return null
++ }
++ function getParentStyleNode(styleNode) {
++ var parentStyleName = "", parentStyleFamily = "", parentStyleNode = null, xp;
++ if(styleNode.localName === "default-style") {
++ return null
++ }
++ parentStyleName = styleNode.getAttributeNS(stylens, "parent-style-name");
++ parentStyleFamily = styleNode.getAttributeNS(stylens, "family");
++ if(parentStyleName) {
++ xp = "//style:*[@style:name='" + parentStyleName + "'][@style:family='" + parentStyleFamily + "']"
+ }else {
- addNames(name, ns, pattern.e[1])
++ xp = "//style:default-style[@style:family='" + parentStyleFamily + "']"
+ }
++ parentStyleNode = xpath.getODFElementsWithXPath((odfRoot), xp, odf.Namespaces.lookupNamespaceURI)[0];
++ return parentStyleNode
+ }
- createNameClass = function createNameClass(pattern) {
- var name, ns, hash, i, result;
- if(pattern.name === "name") {
- name = pattern.text;
- ns = pattern.a.ns;
- result = {name:name, ns:ns, hash:"{" + ns + "}" + name, contains:function(node) {
- return node.namespaceURI === ns && node.localName === name
- }}
- }else {
- if(pattern.name === "choice") {
- name = [];
- ns = [];
- addNames(name, ns, pattern);
- hash = "";
- for(i = 0;i < name.length;i += 1) {
- hash += "{" + ns[i] + "}" + name[i] + ","
- }
- result = {hash:hash, contains:function(node) {
- var j;
- for(j = 0;j < name.length;j += 1) {
- if(name[j] === node.localName && ns[j] === node.namespaceURI) {
- return true
- }
- }
- return false
- }}
- }else {
- result = {hash:"anyName", contains:function() {
- return true
- }}
- }
++ function getTextProperties(props) {
++ var rule = "", fontName, fontSize, value, textDecoration = "", fontSizeRule = "", sizeMultiplier = 1, parentStyle;
++ rule += applySimpleMapping(props, textPropertySimpleMapping);
++ value = props.getAttributeNS(stylens, "text-underline-style");
++ if(value === "solid") {
++ textDecoration += " underline"
+ }
- return result
- };
- function resolveElement(pattern, elements) {
- var element, p, i, hash;
- hash = "element" + pattern.id.toString();
- p = elements[pattern.id] = {hash:hash};
- element = createElement(createNameClass(pattern.e[0]), makePattern(pattern.e[1], elements));
- for(i in element) {
- if(element.hasOwnProperty(i)) {
- p[i] = element[i]
- }
++ value = props.getAttributeNS(stylens, "text-line-through-style");
++ if(value === "solid") {
++ textDecoration += " line-through"
+ }
- return p
- }
- makePattern = function makePattern(pattern, elements) {
- var p, i;
- if(pattern.name === "elementref") {
- p = pattern.id || 0;
- pattern = elements[p];
- if(pattern.name !== undefined) {
- return resolveElement(pattern, elements)
- }
- return pattern
++ if(textDecoration.length) {
++ textDecoration = "text-decoration:" + textDecoration + ";";
++ rule += textDecoration
+ }
- switch(pattern.name) {
- case "empty":
- return empty;
- case "notAllowed":
- return notAllowed;
- case "text":
- return text;
- case "choice":
- return createChoice(makePattern(pattern.e[0], elements), makePattern(pattern.e[1], elements));
- case "interleave":
- p = makePattern(pattern.e[0], elements);
- for(i = 1;i < pattern.e.length;i += 1) {
- p = createInterleave(p, makePattern(pattern.e[i], elements))
- }
- return p;
- case "group":
- return createGroup(makePattern(pattern.e[0], elements), makePattern(pattern.e[1], elements));
- case "oneOrMore":
- return createOneOrMore(makePattern(pattern.e[0], elements));
- case "attribute":
- return createAttribute(createNameClass(pattern.e[0]), makePattern(pattern.e[1], elements));
- case "value":
- return createValue(pattern.text);
- case "data":
- p = pattern.a && pattern.a.type;
- if(p === undefined) {
- p = ""
- }
- return createData(p);
- case "list":
- return createList()
++ fontName = props.getAttributeNS(stylens, "font-name") || props.getAttributeNS(fons, "font-family");
++ if(fontName) {
++ value = fontFaceDeclsMap[fontName];
++ rule += "font-family: " + (value || fontName) + ";"
+ }
- throw"No support for " + pattern.name;
- };
- this.makePattern = function(pattern, elements) {
- var copy = {}, i;
- for(i in elements) {
- if(elements.hasOwnProperty(i)) {
- copy[i] = elements[i]
++ parentStyle = props.parentElement;
++ fontSize = getFontSize(parentStyle);
++ if(!fontSize) {
++ return rule
++ }
++ while(parentStyle) {
++ fontSize = getFontSize(parentStyle);
++ if(fontSize) {
++ if(fontSize.unit !== "%") {
++ fontSizeRule = "font-size: " + fontSize.value * sizeMultiplier + fontSize.unit + ";";
++ break
++ }
++ sizeMultiplier *= fontSize.value / 100
+ }
++ parentStyle = getParentStyleNode(parentStyle)
+ }
- i = makePattern(pattern, copy);
- return i
- };
- this.validate = function validate(walker, callback) {
- var errors;
- walker.currentNode = walker.root;
- errors = childDeriv(null, rootPattern, walker);
- if(!errors.nullable) {
- runtime.log("Error in Relax NG validation: " + errors);
- callback(["Error in Relax NG validation: " + errors])
- }else {
- callback(null)
++ if(!fontSizeRule) {
++ fontSizeRule = "font-size: " + parseFloat(defaultFontSize) * sizeMultiplier + cssUnits.getUnits(defaultFontSize) + ";"
+ }
- };
- this.init = function init(rootPattern1) {
- rootPattern = rootPattern1
++ rule += fontSizeRule;
++ return rule
+ }
- };
- runtime.loadClass("xmldom.RelaxNGParser");
- xmldom.RelaxNG2 = function RelaxNG2() {
- var start, validateNonEmptyPattern, nsmap;
- function RelaxNGParseError(error, context) {
- this.message = function() {
- if(context) {
- error += context.nodeType === Node.ELEMENT_NODE ? " Element " : " Node ";
- error += context.nodeName;
- if(context.nodeValue) {
- error += " with value '" + context.nodeValue + "'"
- }
- error += "."
++ function getParagraphProperties(props) {
++ var rule = "", bgimage, url, lineHeight;
++ rule += applySimpleMapping(props, paragraphPropertySimpleMapping);
++ bgimage = getDirectChild(props, stylens, "background-image");
++ if(bgimage) {
++ url = bgimage.getAttributeNS(xlinkns, "href");
++ if(url) {
++ rule += "background-image: url('odfkit:" + url + "');";
++ rule += applySimpleMapping(bgimage, bgImageSimpleMapping)
+ }
- return error
+ }
- }
- function validateOneOrMore(elementdef, walker, element) {
- var node, i = 0, err;
- do {
- node = walker.currentNode;
- err = validateNonEmptyPattern(elementdef.e[0], walker, element);
- i += 1
- }while(!err && node !== walker.currentNode);
- if(i > 1) {
- walker.currentNode = node;
- return null
++ lineHeight = props.getAttributeNS(fons, "line-height");
++ if(lineHeight && lineHeight !== "normal") {
++ lineHeight = utils.parseFoLineHeight(lineHeight);
++ if(lineHeight.unit !== "%") {
++ rule += "line-height: " + lineHeight.value + lineHeight.unit + ";"
++ }else {
++ rule += "line-height: " + lineHeight.value / 100 + ";"
++ }
+ }
- return err
++ return rule
+ }
- function qName(node) {
- return nsmap[node.namespaceURI] + ":" + node.localName
++ function matchToRgb(m, r, g, b) {
++ return r + r + g + g + b + b
+ }
- function isWhitespace(node) {
- return node && (node.nodeType === Node.TEXT_NODE && /^\s+$/.test(node.nodeValue))
++ function hexToRgb(hex) {
++ var result, shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
++ hex = hex.replace(shorthandRegex, matchToRgb);
++ result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
++ return result ? {r:parseInt(result[1], 16), g:parseInt(result[2], 16), b:parseInt(result[3], 16)} : null
+ }
- function validatePattern(elementdef, walker, element, data) {
- if(elementdef.name === "empty") {
- return null
- }
- return validateNonEmptyPattern(elementdef, walker, element, data)
++ function isNumber(n) {
++ return!isNaN(parseFloat(n))
+ }
- function validateAttribute(elementdef, walker, element) {
- if(elementdef.e.length !== 2) {
- throw"Attribute with wrong # of elements: " + elementdef.e.length;
- }
- var att, a, l = elementdef.localnames.length, i;
- for(i = 0;i < l;i += 1) {
- a = element.getAttributeNS(elementdef.namespaces[i], elementdef.localnames[i]);
- if(a === "" && !element.hasAttributeNS(elementdef.namespaces[i], elementdef.localnames[i])) {
- a = undefined
++ function getGraphicProperties(props) {
++ var rule = "", alpha, bgcolor, fill;
++ rule += applySimpleMapping(props, graphicPropertySimpleMapping);
++ alpha = props.getAttributeNS(drawns, "opacity");
++ fill = props.getAttributeNS(drawns, "fill");
++ bgcolor = props.getAttributeNS(drawns, "fill-color");
++ if(fill === "solid" || fill === "hatch") {
++ if(bgcolor && bgcolor !== "none") {
++ alpha = isNumber(alpha) ? parseFloat(alpha) / 100 : 1;
++ bgcolor = hexToRgb(bgcolor);
++ if(bgcolor) {
++ rule += "background-color: rgba(" + bgcolor.r + "," + bgcolor.g + "," + bgcolor.b + "," + alpha + ");"
++ }
++ }else {
++ rule += "background: none;"
+ }
- if(att !== undefined && a !== undefined) {
- return[new RelaxNGParseError("Attribute defined too often.", element)]
++ }else {
++ if(fill === "none") {
++ rule += "background: none;"
+ }
- att = a
- }
- if(att === undefined) {
- return[new RelaxNGParseError("Attribute not found: " + elementdef.names, element)]
+ }
- return validatePattern(elementdef.e[1], walker, element, att)
++ return rule
+ }
- function validateTop(elementdef, walker, element) {
- return validatePattern(elementdef, walker, element)
- }
- function validateElement(elementdef, walker) {
- if(elementdef.e.length !== 2) {
- throw"Element with wrong # of elements: " + elementdef.e.length;
++ function getDrawingPageProperties(props) {
++ var rule = "";
++ rule += applySimpleMapping(props, graphicPropertySimpleMapping);
++ if(props.getAttributeNS(presentationns, "background-visible") === "true") {
++ rule += "background: none;"
+ }
- var node = walker.currentNode, type = node ? node.nodeType : 0, error = null;
- while(type > Node.ELEMENT_NODE) {
- if(type !== Node.COMMENT_NODE && (type !== Node.TEXT_NODE || !/^\s+$/.test(walker.currentNode.nodeValue))) {
- return[new RelaxNGParseError("Not allowed node of type " + type + ".")]
++ return rule
++ }
++ function getTableCellProperties(props) {
++ var rule = "";
++ rule += applySimpleMapping(props, tablecellPropertySimpleMapping);
++ return rule
++ }
++ function getTableRowProperties(props) {
++ var rule = "";
++ rule += applySimpleMapping(props, tablerowPropertySimpleMapping);
++ return rule
++ }
++ function getTableColumnProperties(props) {
++ var rule = "";
++ rule += applySimpleMapping(props, tablecolumnPropertySimpleMapping);
++ return rule
++ }
++ function getTableProperties(props) {
++ var rule = "", borderModel;
++ rule += applySimpleMapping(props, tablePropertySimpleMapping);
++ borderModel = props.getAttributeNS(tablens, "border-model");
++ if(borderModel === "collapsing") {
++ rule += "border-collapse:collapse;"
++ }else {
++ if(borderModel === "separating") {
++ rule += "border-collapse:separate;"
+ }
- node = walker.nextSibling();
- type = node ? node.nodeType : 0
+ }
- if(!node) {
- return[new RelaxNGParseError("Missing element " + elementdef.names)]
++ return rule
++ }
++ function addStyleRule(sheet, family, name, node) {
++ var selectors = getSelectors(family, name, node), selector = selectors.join(","), rule = "", properties;
++ properties = getDirectChild(node.element, stylens, "text-properties");
++ if(properties) {
++ rule += getTextProperties(properties)
+ }
- if(elementdef.names && elementdef.names.indexOf(qName(node)) === -1) {
- return[new RelaxNGParseError("Found " + node.nodeName + " instead of " + elementdef.names + ".", node)]
++ properties = getDirectChild(node.element, stylens, "paragraph-properties");
++ if(properties) {
++ rule += getParagraphProperties(properties)
+ }
- if(walker.firstChild()) {
- error = validateTop(elementdef.e[1], walker, node);
- while(walker.nextSibling()) {
- type = walker.currentNode.nodeType;
- if(!isWhitespace(walker.currentNode) && type !== Node.COMMENT_NODE) {
- return[new RelaxNGParseError("Spurious content.", walker.currentNode)]
- }
- }
- if(walker.parentNode() !== node) {
- return[new RelaxNGParseError("Implementation error.")]
- }
++ properties = getDirectChild(node.element, stylens, "graphic-properties");
++ if(properties) {
++ rule += getGraphicProperties(properties)
++ }
++ properties = getDirectChild(node.element, stylens, "drawing-page-properties");
++ if(properties) {
++ rule += getDrawingPageProperties(properties)
++ }
++ properties = getDirectChild(node.element, stylens, "table-cell-properties");
++ if(properties) {
++ rule += getTableCellProperties(properties)
++ }
++ properties = getDirectChild(node.element, stylens, "table-row-properties");
++ if(properties) {
++ rule += getTableRowProperties(properties)
++ }
++ properties = getDirectChild(node.element, stylens, "table-column-properties");
++ if(properties) {
++ rule += getTableColumnProperties(properties)
++ }
++ properties = getDirectChild(node.element, stylens, "table-properties");
++ if(properties) {
++ rule += getTableProperties(properties)
++ }
++ if(rule.length === 0) {
++ return
++ }
++ rule = selector + "{" + rule + "}";
++ try {
++ sheet.insertRule(rule, sheet.cssRules.length)
++ }catch(e) {
++ throw e;
++ }
++ }
++ function getNumberRule(node) {
++ var style = node.getAttributeNS(stylens, "num-format"), suffix = node.getAttributeNS(stylens, "num-suffix") || "", prefix = node.getAttributeNS(stylens, "num-prefix") || "", stylemap = {1:"decimal", "a":"lower-latin", "A":"upper-latin", "i":"lower-roman", "I":"upper-roman"}, content = "";
++ if(prefix) {
++ content += ' "' + prefix + '"'
++ }
++ if(stylemap.hasOwnProperty(style)) {
++ content += " counter(list, " + stylemap[style] + ")"
+ }else {
- error = validateTop(elementdef.e[1], walker, node)
++ if(style) {
++ content += ' "' + style + '"'
++ }else {
++ content += " ''"
++ }
+ }
- node = walker.nextSibling();
- return error
++ return"content:" + content + ' "' + suffix + '"'
+ }
- function validateChoice(elementdef, walker, element, data) {
- if(elementdef.e.length !== 2) {
- throw"Choice with wrong # of options: " + elementdef.e.length;
++ function getImageRule() {
++ return"content: none;"
++ }
++ function getBulletRule(node) {
++ var bulletChar = node.getAttributeNS(textns, "bullet-char");
++ return"content: '" + bulletChar + "';"
++ }
++ function addListStyleRule(sheet, name, node, itemrule) {
++ var selector = 'text|list[text|style-name="' + name + '"]', level = node.getAttributeNS(textns, "level"), itemSelector, listItemRule, listLevelProps = getDirectChild(node, stylens, "list-level-properties"), listLevelLabelAlign = getDirectChild(listLevelProps, stylens, "list-level-label-alignment"), bulletIndent, listIndent, bulletWidth, rule;
++ if(listLevelLabelAlign) {
++ bulletIndent = listLevelLabelAlign.getAttributeNS(fons, "text-indent");
++ listIndent = listLevelLabelAlign.getAttributeNS(fons, "margin-left")
+ }
- var node = walker.currentNode, err;
- if(elementdef.e[0].name === "empty") {
- err = validateNonEmptyPattern(elementdef.e[1], walker, element, data);
- if(err) {
- walker.currentNode = node
++ if(!bulletIndent) {
++ bulletIndent = "-0.6cm"
++ }
++ if(bulletIndent.charAt(0) === "-") {
++ bulletWidth = bulletIndent.substring(1)
++ }else {
++ bulletWidth = "-" + bulletIndent
++ }
++ level = level && parseInt(level, 10);
++ while(level > 1) {
++ selector += " > text|list-item > text|list";
++ level -= 1
++ }
++ if(listIndent) {
++ itemSelector = selector;
++ itemSelector += " > text|list-item > *:not(text|list):first-child";
++ listItemRule = itemSelector + "{";
++ listItemRule += "margin-left:" + listIndent + ";";
++ listItemRule += "}";
++ try {
++ sheet.insertRule(listItemRule, sheet.cssRules.length)
++ }catch(e1) {
++ runtime.log("cannot load rule: " + listItemRule)
+ }
- return null
+ }
- err = validatePattern(elementdef.e[0], walker, element, data);
- if(err) {
- walker.currentNode = node;
- err = validateNonEmptyPattern(elementdef.e[1], walker, element, data)
++ selector += " > text|list-item > *:not(text|list):first-child:before";
++ rule = selector + "{" + itemrule + ";";
++ rule += "counter-increment:list;";
++ rule += "margin-left:" + bulletIndent + ";";
++ rule += "width:" + bulletWidth + ";";
++ rule += "display:inline-block}";
++ try {
++ sheet.insertRule(rule, sheet.cssRules.length)
++ }catch(e2) {
++ runtime.log("cannot load rule: " + rule)
+ }
- return err
+ }
- function validateInterleave(elementdef, walker, element) {
- var l = elementdef.e.length, n = [l], err, i, todo = l, donethisround, node, subnode, e;
- while(todo > 0) {
- donethisround = 0;
- node = walker.currentNode;
- for(i = 0;i < l;i += 1) {
- subnode = walker.currentNode;
- if(n[i] !== true && n[i] !== subnode) {
- e = elementdef.e[i];
- err = validateNonEmptyPattern(e, walker, element);
- if(err) {
- walker.currentNode = subnode;
- if(n[i] === undefined) {
- n[i] = false
- }
- }else {
- if(subnode === walker.currentNode || (e.name === "oneOrMore" || e.name === "choice" && (e.e[0].name === "oneOrMore" || e.e[1].name === "oneOrMore"))) {
- donethisround += 1;
- n[i] = subnode
- }else {
- donethisround += 1;
- n[i] = true
- }
++ function addPageStyleRules(sheet, node) {
++ var rule = "", imageProps, url, contentLayoutRule = "", pageSizeRule = "", props = getDirectChild(node, stylens, "page-layout-properties"), stylename, masterStyles, e, masterStyleName;
++ if(!props) {
++ return
++ }
++ stylename = node.getAttributeNS(stylens, "name");
++ rule += applySimpleMapping(props, pageContentPropertySimpleMapping);
++ imageProps = getDirectChild(props, stylens, "background-image");
++ if(imageProps) {
++ url = imageProps.getAttributeNS(xlinkns, "href");
++ if(url) {
++ rule += "background-image: url('odfkit:" + url + "');";
++ rule += applySimpleMapping(imageProps, bgImageSimpleMapping)
++ }
++ }
++ if(documentType === "presentation") {
++ masterStyles = getDirectChild(node.parentNode.parentElement, officens, "master-styles");
++ e = masterStyles && masterStyles.firstElementChild;
++ while(e) {
++ if(e.namespaceURI === stylens && (e.localName === "master-page" && e.getAttributeNS(stylens, "page-layout-name") === stylename)) {
++ masterStyleName = e.getAttributeNS(stylens, "name");
++ contentLayoutRule = "draw|page[draw|master-page-name=" + masterStyleName + "] {" + rule + "}";
++ pageSizeRule = "office|body, draw|page[draw|master-page-name=" + masterStyleName + "] {" + applySimpleMapping(props, pageSizePropertySimpleMapping) + " }";
++ try {
++ sheet.insertRule(contentLayoutRule, sheet.cssRules.length);
++ sheet.insertRule(pageSizeRule, sheet.cssRules.length)
++ }catch(e1) {
++ throw e1;
+ }
+ }
++ e = e.nextElementSibling
+ }
- if(node === walker.currentNode && donethisround === todo) {
- return null
- }
- if(donethisround === 0) {
- for(i = 0;i < l;i += 1) {
- if(n[i] === false) {
- return[new RelaxNGParseError("Interleave does not match.", element)]
- }
++ }else {
++ if(documentType === "text") {
++ contentLayoutRule = "office|text {" + rule + "}";
++ rule = "";
++ pageSizeRule = "office|body {" + "width: " + props.getAttributeNS(fons, "page-width") + ";" + "}";
++ try {
++ sheet.insertRule(contentLayoutRule, sheet.cssRules.length);
++ sheet.insertRule(pageSizeRule, sheet.cssRules.length)
++ }catch(e2) {
++ throw e2;
+ }
- return null
+ }
- todo = 0;
- for(i = 0;i < l;i += 1) {
- if(n[i] !== true) {
- todo += 1
++ }
++ }
++ function addListStyleRules(sheet, name, node) {
++ var n = node.firstChild, e, itemrule;
++ while(n) {
++ if(n.namespaceURI === textns) {
++ e = (n);
++ if(n.localName === "list-level-style-number") {
++ itemrule = getNumberRule(e);
++ addListStyleRule(sheet, name, e, itemrule)
++ }else {
++ if(n.localName === "list-level-style-image") {
++ itemrule = getImageRule();
++ addListStyleRule(sheet, name, e, itemrule)
++ }else {
++ if(n.localName === "list-level-style-bullet") {
++ itemrule = getBulletRule(e);
++ addListStyleRule(sheet, name, e, itemrule)
++ }
++ }
+ }
+ }
++ n = n.nextSibling
+ }
- return null
+ }
- function validateGroup(elementdef, walker, element) {
- if(elementdef.e.length !== 2) {
- throw"Group with wrong # of members: " + elementdef.e.length;
++ function addRule(sheet, family, name, node) {
++ if(family === "list") {
++ addListStyleRules(sheet, name, node.element)
++ }else {
++ if(family === "page") {
++ addPageStyleRules(sheet, node.element)
++ }else {
++ addStyleRule(sheet, family, name, node)
++ }
+ }
- return validateNonEmptyPattern(elementdef.e[0], walker, element) || validateNonEmptyPattern(elementdef.e[1], walker, element)
+ }
- function validateText(elementdef, walker, element) {
- var node = walker.currentNode, type = node ? node.nodeType : 0;
- while(node !== element && type !== 3) {
- if(type === 1) {
- return[new RelaxNGParseError("Element not allowed here.", node)]
++ function addRules(sheet, family, name, node) {
++ addRule(sheet, family, name, node);
++ var n;
++ for(n in node.derivedStyles) {
++ if(node.derivedStyles.hasOwnProperty(n)) {
++ addRules(sheet, family, n, node.derivedStyles[n])
+ }
- node = walker.nextSibling();
- type = node ? node.nodeType : 0
+ }
- walker.nextSibling();
- return null
+ }
- validateNonEmptyPattern = function validateNonEmptyPattern(elementdef, walker, element, data) {
- var name = elementdef.name, err = null;
- if(name === "text") {
- err = validateText(elementdef, walker, element)
- }else {
- if(name === "data") {
- err = null
- }else {
- if(name === "value") {
- if(data !== elementdef.text) {
- err = [new RelaxNGParseError("Wrong value, should be '" + elementdef.text + "', not '" + data + "'", element)]
- }
- }else {
- if(name === "list") {
- err = null
- }else {
- if(name === "attribute") {
- err = validateAttribute(elementdef, walker, element)
- }else {
- if(name === "element") {
- err = validateElement(elementdef, walker)
- }else {
- if(name === "oneOrMore") {
- err = validateOneOrMore(elementdef, walker, element)
- }else {
- if(name === "choice") {
- err = validateChoice(elementdef, walker, element, data)
- }else {
- if(name === "group") {
- err = validateGroup(elementdef, walker, element)
- }else {
- if(name === "interleave") {
- err = validateInterleave(elementdef, walker, element)
- }else {
- throw name + " not allowed in nonEmptyPattern.";
- }
- }
- }
- }
- }
- }
++ this.style2css = function(doctype, stylesheet, fontFaceMap, styles, autostyles) {
++ var doc, styletree, tree, rule, name, family, stylenodes, styleautonodes;
++ while(stylesheet.cssRules.length) {
++ stylesheet.deleteRule(stylesheet.cssRules.length - 1)
++ }
++ doc = null;
++ if(styles) {
++ doc = styles.ownerDocument;
++ odfRoot = styles.parentNode
++ }
++ if(autostyles) {
++ doc = autostyles.ownerDocument;
++ odfRoot = autostyles.parentNode
++ }
++ if(!doc) {
++ return
++ }
++ odf.Namespaces.forEachPrefix(function(prefix, ns) {
++ rule = "@namespace " + prefix + " url(" + ns + ");";
++ try {
++ stylesheet.insertRule(rule, stylesheet.cssRules.length)
++ }catch(ignore) {
++ }
++ });
++ fontFaceDeclsMap = fontFaceMap;
++ documentType = doctype;
++ defaultFontSize = runtime.getWindow().getComputedStyle(document.body, null).getPropertyValue("font-size") || "12pt";
++ stylenodes = getStyleMap(styles);
++ styleautonodes = getStyleMap(autostyles);
++ styletree = {};
++ for(family in familynamespaceprefixes) {
++ if(familynamespaceprefixes.hasOwnProperty(family)) {
++ tree = styletree[family] = {};
++ addStyleMapToStyleTree(stylenodes[family], tree);
++ addStyleMapToStyleTree(styleautonodes[family], tree);
++ for(name in tree) {
++ if(tree.hasOwnProperty(name)) {
++ addRules(stylesheet, family, name, tree[name])
+ }
+ }
+ }
+ }
- return err
- };
- this.validate = function validate(walker, callback) {
- walker.currentNode = walker.root;
- var errors = validatePattern(start.e[0], walker, (walker.root));
- callback(errors)
- };
- this.init = function init(start1, nsmap1) {
- start = start1;
- nsmap = nsmap1
+ }
+};
- xmldom.XPathIterator = function XPathIterator() {
- };
- xmldom.XPath = function() {
- var createXPathPathIterator, parsePredicates;
- function isSmallestPositive(a, b, c) {
- return a !== -1 && ((a < b || b === -1) && (a < c || c === -1))
- }
- function parseXPathStep(xpath, pos, end, steps) {
- var location = "", predicates = [], brapos = xpath.indexOf("[", pos), slapos = xpath.indexOf("/", pos), eqpos = xpath.indexOf("=", pos);
- if(isSmallestPositive(slapos, brapos, eqpos)) {
- location = xpath.substring(pos, slapos);
- pos = slapos + 1
- }else {
- if(isSmallestPositive(brapos, slapos, eqpos)) {
- location = xpath.substring(pos, brapos);
- pos = parsePredicates(xpath, brapos, predicates)
- }else {
- if(isSmallestPositive(eqpos, slapos, brapos)) {
- location = xpath.substring(pos, eqpos);
- pos = eqpos
- }else {
- location = xpath.substring(pos, end);
- pos = end
- }
- }
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++runtime.loadClass("xmldom.XPath");
++runtime.loadClass("odf.Namespaces");
++odf.StyleInfo = function StyleInfo() {
++ var chartns = odf.Namespaces.chartns, dbns = odf.Namespaces.dbns, dr3dns = odf.Namespaces.dr3dns, drawns = odf.Namespaces.drawns, formns = odf.Namespaces.formns, numberns = odf.Namespaces.numberns, officens = odf.Namespaces.officens, presentationns = odf.Namespaces.presentationns, stylens = odf.Namespaces.stylens, tablens = odf.Namespaces.tablens, textns = odf.Namespaces.textns, nsprefixes = {"urn:oasis:names:tc:opendocument:xmlns:chart:1.0":"chart:", "urn:oasis:names:tc:opendocument: [...]
++ "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0":"dr3d:", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0":"draw:", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0":"fo:", "urn:oasis:names:tc:opendocument:xmlns:form:1.0":"form:", "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0":"number:", "urn:oasis:names:tc:opendocument:xmlns:office:1.0":"office:", "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0":"presentation:", "urn:oasis:names:tc:opendocument:xmlns:sty [...]
++ "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0":"svg:", "urn:oasis:names:tc:opendocument:xmlns:table:1.0":"table:", "urn:oasis:names:tc:opendocument:xmlns:text:1.0":"chart:", "http://www.w3.org/XML/1998/namespace":"xml:"}, elementstyles = {"text":[{ens:stylens, en:"tab-stop", ans:stylens, a:"leader-text-style"}, {ens:stylens, en:"drop-cap", ans:stylens, a:"style-name"}, {ens:textns, en:"notes-configuration", ans:textns, a:"citation-body-style-name"}, {ens:textns, en:"notes- [...]
++ ans:textns, a:"citation-style-name"}, {ens:textns, en:"a", ans:textns, a:"style-name"}, {ens:textns, en:"alphabetical-index", ans:textns, a:"style-name"}, {ens:textns, en:"linenumbering-configuration", ans:textns, a:"style-name"}, {ens:textns, en:"list-level-style-number", ans:textns, a:"style-name"}, {ens:textns, en:"ruby-text", ans:textns, a:"style-name"}, {ens:textns, en:"span", ans:textns, a:"style-name"}, {ens:textns, en:"a", ans:textns, a:"visited-style-name"}, {ens:stylens, en: [...]
++ ans:stylens, a:"text-line-through-text-style"}, {ens:textns, en:"alphabetical-index-source", ans:textns, a:"main-entry-style-name"}, {ens:textns, en:"index-entry-bibliography", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-chapter", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-link-end", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-link-start", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-page-number", ans:textns, a:"style-name"}, {en [...]
++ en:"index-entry-span", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-tab-stop", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-text", ans:textns, a:"style-name"}, {ens:textns, en:"index-title-template", ans:textns, a:"style-name"}, {ens:textns, en:"list-level-style-bullet", ans:textns, a:"style-name"}, {ens:textns, en:"outline-level-style", ans:textns, a:"style-name"}], "paragraph":[{ens:drawns, en:"caption", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"ci [...]
++ a:"text-style-name"}, {ens:drawns, en:"connector", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"control", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"custom-shape", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"ellipse", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"frame", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"line", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"measure", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"path", ans:drawns, a: [...]
++ {ens:drawns, en:"polygon", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"polyline", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"rect", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"regular-polygon", ans:drawns, a:"text-style-name"}, {ens:officens, en:"annotation", ans:drawns, a:"text-style-name"}, {ens:formns, en:"column", ans:formns, a:"text-style-name"}, {ens:stylens, en:"style", ans:stylens, a:"next-style-name"}, {ens:tablens, en:"body", ans:tablens, a:"paragraph-s [...]
++ {ens:tablens, en:"even-columns", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"even-rows", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"first-column", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"first-row", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"last-column", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"last-row", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"odd-columns", ans:tablens, a:"paragraph-styl [...]
++ {ens:tablens, en:"odd-rows", ans:tablens, a:"paragraph-style-name"}, {ens:textns, en:"notes-configuration", ans:textns, a:"default-style-name"}, {ens:textns, en:"alphabetical-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"bibliography-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"h", ans:textns, a:"style-name"}, {ens:textns, en:"illustration-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"index-source-style", ans:textns, a:"s [...]
++ {ens:textns, en:"object-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"p", ans:textns, a:"style-name"}, {ens:textns, en:"table-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"table-of-content-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"table-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"user-index-entry-template", ans:textns, a:"style-name"}, {ens:stylens, en:"page-layout-properties", ans:stylens, a:" [...]
++ "chart":[{ens:chartns, en:"axis", ans:chartns, a:"style-name"}, {ens:chartns, en:"chart", ans:chartns, a:"style-name"}, {ens:chartns, en:"data-label", ans:chartns, a:"style-name"}, {ens:chartns, en:"data-point", ans:chartns, a:"style-name"}, {ens:chartns, en:"equation", ans:chartns, a:"style-name"}, {ens:chartns, en:"error-indicator", ans:chartns, a:"style-name"}, {ens:chartns, en:"floor", ans:chartns, a:"style-name"}, {ens:chartns, en:"footer", ans:chartns, a:"style-name"}, {ens:char [...]
++ ans:chartns, a:"style-name"}, {ens:chartns, en:"legend", ans:chartns, a:"style-name"}, {ens:chartns, en:"mean-value", ans:chartns, a:"style-name"}, {ens:chartns, en:"plot-area", ans:chartns, a:"style-name"}, {ens:chartns, en:"regression-curve", ans:chartns, a:"style-name"}, {ens:chartns, en:"series", ans:chartns, a:"style-name"}, {ens:chartns, en:"stock-gain-marker", ans:chartns, a:"style-name"}, {ens:chartns, en:"stock-loss-marker", ans:chartns, a:"style-name"}, {ens:chartns, en:"sto [...]
++ ans:chartns, a:"style-name"}, {ens:chartns, en:"subtitle", ans:chartns, a:"style-name"}, {ens:chartns, en:"title", ans:chartns, a:"style-name"}, {ens:chartns, en:"wall", ans:chartns, a:"style-name"}], "section":[{ens:textns, en:"alphabetical-index", ans:textns, a:"style-name"}, {ens:textns, en:"bibliography", ans:textns, a:"style-name"}, {ens:textns, en:"illustration-index", ans:textns, a:"style-name"}, {ens:textns, en:"index-title", ans:textns, a:"style-name"}, {ens:textns, en:"objec [...]
++ ans:textns, a:"style-name"}, {ens:textns, en:"section", ans:textns, a:"style-name"}, {ens:textns, en:"table-of-content", ans:textns, a:"style-name"}, {ens:textns, en:"table-index", ans:textns, a:"style-name"}, {ens:textns, en:"user-index", ans:textns, a:"style-name"}], "ruby":[{ens:textns, en:"ruby", ans:textns, a:"style-name"}], "table":[{ens:dbns, en:"query", ans:dbns, a:"style-name"}, {ens:dbns, en:"table-representation", ans:dbns, a:"style-name"}, {ens:tablens, en:"background", an [...]
++ a:"style-name"}, {ens:tablens, en:"table", ans:tablens, a:"style-name"}], "table-column":[{ens:dbns, en:"column", ans:dbns, a:"style-name"}, {ens:tablens, en:"table-column", ans:tablens, a:"style-name"}], "table-row":[{ens:dbns, en:"query", ans:dbns, a:"default-row-style-name"}, {ens:dbns, en:"table-representation", ans:dbns, a:"default-row-style-name"}, {ens:tablens, en:"table-row", ans:tablens, a:"style-name"}], "table-cell":[{ens:dbns, en:"column", ans:dbns, a:"default-cell-style-n [...]
++ en:"table-column", ans:tablens, a:"default-cell-style-name"}, {ens:tablens, en:"table-row", ans:tablens, a:"default-cell-style-name"}, {ens:tablens, en:"body", ans:tablens, a:"style-name"}, {ens:tablens, en:"covered-table-cell", ans:tablens, a:"style-name"}, {ens:tablens, en:"even-columns", ans:tablens, a:"style-name"}, {ens:tablens, en:"covered-table-cell", ans:tablens, a:"style-name"}, {ens:tablens, en:"even-columns", ans:tablens, a:"style-name"}, {ens:tablens, en:"even-rows", ans:t [...]
++ {ens:tablens, en:"first-column", ans:tablens, a:"style-name"}, {ens:tablens, en:"first-row", ans:tablens, a:"style-name"}, {ens:tablens, en:"last-column", ans:tablens, a:"style-name"}, {ens:tablens, en:"last-row", ans:tablens, a:"style-name"}, {ens:tablens, en:"odd-columns", ans:tablens, a:"style-name"}, {ens:tablens, en:"odd-rows", ans:tablens, a:"style-name"}, {ens:tablens, en:"table-cell", ans:tablens, a:"style-name"}], "graphic":[{ens:dr3dns, en:"cube", ans:drawns, a:"style-name"} [...]
++ en:"extrude", ans:drawns, a:"style-name"}, {ens:dr3dns, en:"rotate", ans:drawns, a:"style-name"}, {ens:dr3dns, en:"scene", ans:drawns, a:"style-name"}, {ens:dr3dns, en:"sphere", ans:drawns, a:"style-name"}, {ens:drawns, en:"caption", ans:drawns, a:"style-name"}, {ens:drawns, en:"circle", ans:drawns, a:"style-name"}, {ens:drawns, en:"connector", ans:drawns, a:"style-name"}, {ens:drawns, en:"control", ans:drawns, a:"style-name"}, {ens:drawns, en:"custom-shape", ans:drawns, a:"style-name [...]
++ en:"ellipse", ans:drawns, a:"style-name"}, {ens:drawns, en:"frame", ans:drawns, a:"style-name"}, {ens:drawns, en:"g", ans:drawns, a:"style-name"}, {ens:drawns, en:"line", ans:drawns, a:"style-name"}, {ens:drawns, en:"measure", ans:drawns, a:"style-name"}, {ens:drawns, en:"page-thumbnail", ans:drawns, a:"style-name"}, {ens:drawns, en:"path", ans:drawns, a:"style-name"}, {ens:drawns, en:"polygon", ans:drawns, a:"style-name"}, {ens:drawns, en:"polyline", ans:drawns, a:"style-name"}, {ens [...]
++ ans:drawns, a:"style-name"}, {ens:drawns, en:"regular-polygon", ans:drawns, a:"style-name"}, {ens:officens, en:"annotation", ans:drawns, a:"style-name"}], "presentation":[{ens:dr3dns, en:"cube", ans:presentationns, a:"style-name"}, {ens:dr3dns, en:"extrude", ans:presentationns, a:"style-name"}, {ens:dr3dns, en:"rotate", ans:presentationns, a:"style-name"}, {ens:dr3dns, en:"scene", ans:presentationns, a:"style-name"}, {ens:dr3dns, en:"sphere", ans:presentationns, a:"style-name"}, {ens: [...]
++ ans:presentationns, a:"style-name"}, {ens:drawns, en:"circle", ans:presentationns, a:"style-name"}, {ens:drawns, en:"connector", ans:presentationns, a:"style-name"}, {ens:drawns, en:"control", ans:presentationns, a:"style-name"}, {ens:drawns, en:"custom-shape", ans:presentationns, a:"style-name"}, {ens:drawns, en:"ellipse", ans:presentationns, a:"style-name"}, {ens:drawns, en:"frame", ans:presentationns, a:"style-name"}, {ens:drawns, en:"g", ans:presentationns, a:"style-name"}, {ens:d [...]
++ ans:presentationns, a:"style-name"}, {ens:drawns, en:"measure", ans:presentationns, a:"style-name"}, {ens:drawns, en:"page-thumbnail", ans:presentationns, a:"style-name"}, {ens:drawns, en:"path", ans:presentationns, a:"style-name"}, {ens:drawns, en:"polygon", ans:presentationns, a:"style-name"}, {ens:drawns, en:"polyline", ans:presentationns, a:"style-name"}, {ens:drawns, en:"rect", ans:presentationns, a:"style-name"}, {ens:drawns, en:"regular-polygon", ans:presentationns, a:"style-na [...]
++ en:"annotation", ans:presentationns, a:"style-name"}], "drawing-page":[{ens:drawns, en:"page", ans:drawns, a:"style-name"}, {ens:presentationns, en:"notes", ans:drawns, a:"style-name"}, {ens:stylens, en:"handout-master", ans:drawns, a:"style-name"}, {ens:stylens, en:"master-page", ans:drawns, a:"style-name"}], "list-style":[{ens:textns, en:"list", ans:textns, a:"style-name"}, {ens:textns, en:"numbered-paragraph", ans:textns, a:"style-name"}, {ens:textns, en:"list-item", ans:textns, a: [...]
++ {ens:stylens, en:"style", ans:stylens, a:"list-style-name"}], "data":[{ens:stylens, en:"style", ans:stylens, a:"data-style-name"}, {ens:stylens, en:"style", ans:stylens, a:"percentage-data-style-name"}, {ens:presentationns, en:"date-time-decl", ans:stylens, a:"data-style-name"}, {ens:textns, en:"creation-date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"creation-time", ans:stylens, a:"data-style-name"}, {ens:textns, en:"database-display", ans:stylens, a:"data-style-name"}, {e [...]
++ en:"date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"editing-duration", ans:stylens, a:"data-style-name"}, {ens:textns, en:"expression", ans:stylens, a:"data-style-name"}, {ens:textns, en:"meta-field", ans:stylens, a:"data-style-name"}, {ens:textns, en:"modification-date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"modification-time", ans:stylens, a:"data-style-name"}, {ens:textns, en:"print-date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"print-time", ans [...]
++ a:"data-style-name"}, {ens:textns, en:"table-formula", ans:stylens, a:"data-style-name"}, {ens:textns, en:"time", ans:stylens, a:"data-style-name"}, {ens:textns, en:"user-defined", ans:stylens, a:"data-style-name"}, {ens:textns, en:"user-field-get", ans:stylens, a:"data-style-name"}, {ens:textns, en:"user-field-input", ans:stylens, a:"data-style-name"}, {ens:textns, en:"variable-get", ans:stylens, a:"data-style-name"}, {ens:textns, en:"variable-input", ans:stylens, a:"data-style-name" [...]
++ en:"variable-set", ans:stylens, a:"data-style-name"}], "page-layout":[{ens:presentationns, en:"notes", ans:stylens, a:"page-layout-name"}, {ens:stylens, en:"handout-master", ans:stylens, a:"page-layout-name"}, {ens:stylens, en:"master-page", ans:stylens, a:"page-layout-name"}]}, elements, xpath = xmldom.XPath;
++ function hasDerivedStyles(odfbody, nsResolver, styleElement) {
++ var nodes, xp, styleName = styleElement.getAttributeNS(stylens, "name"), styleFamily = styleElement.getAttributeNS(stylens, "family");
++ xp = "//style:*[@style:parent-style-name='" + styleName + "'][@style:family='" + styleFamily + "']";
++ nodes = xpath.getODFElementsWithXPath(odfbody, xp, nsResolver);
++ if(nodes.length) {
++ return true
+ }
- steps.push({location:location, predicates:predicates});
- return pos
++ return false
+ }
- function parseXPath(xpath) {
- var steps = [], p = 0, end = xpath.length, value;
- while(p < end) {
- p = parseXPathStep(xpath, p, end, steps);
- if(p < end && xpath[p] === "=") {
- value = xpath.substring(p + 1, end);
- if(value.length > 2 && (value[0] === "'" || value[0] === '"')) {
- value = value.slice(1, value.length - 1)
- }else {
- try {
- value = parseInt(value, 10)
- }catch(ignore) {
- }
- }
- p = end
++ function prefixUsedStyleNames(element, prefix) {
++ var i, stylename, a, e, ns, elname, elns, localName, length = 0;
++ elname = elements[element.localName];
++ if(elname) {
++ elns = elname[element.namespaceURI];
++ if(elns) {
++ length = elns.length
+ }
+ }
- return{steps:steps, value:value}
- }
- parsePredicates = function parsePredicates(xpath, start, predicates) {
- var pos = start, l = xpath.length, depth = 0;
- while(pos < l) {
- if(xpath[pos] === "]") {
- depth -= 1;
- if(depth <= 0) {
- predicates.push(parseXPath(xpath.substring(start, pos)))
- }
- }else {
- if(xpath[pos] === "[") {
- if(depth <= 0) {
- start = pos + 1
- }
- depth += 1
- }
++ for(i = 0;i < length;i += 1) {
++ a = (elns[i]);
++ ns = a.ns;
++ localName = a.localname;
++ stylename = element.getAttributeNS(ns, localName);
++ if(stylename) {
++ element.setAttributeNS(ns, nsprefixes[ns] + localName, prefix + stylename)
+ }
- pos += 1
+ }
- return pos
- };
- xmldom.XPathIterator.prototype.next = function() {
- };
- xmldom.XPathIterator.prototype.reset = function() {
- };
- function XPathNodeIterator() {
- var node, done = false;
- this.setNode = function setNode(n) {
- node = n
- };
- this.reset = function() {
- done = false
- };
- this.next = function next() {
- var val = done ? null : node;
- done = true;
- return val
++ e = element.firstElementChild;
++ while(e) {
++ prefixUsedStyleNames(e, prefix);
++ e = e.nextElementSibling
+ }
+ }
- function AttributeIterator(it, namespace, localName) {
- this.reset = function reset() {
- it.reset()
- };
- this.next = function next() {
- var node = it.next();
- while(node) {
- node = node.getAttributeNodeNS(namespace, localName);
- if(node) {
- return node
- }
- node = it.next()
++ function prefixStyleName(styleElement, prefix) {
++ var stylename = styleElement.getAttributeNS(drawns, "name"), ns;
++ if(stylename) {
++ ns = drawns
++ }else {
++ stylename = styleElement.getAttributeNS(stylens, "name");
++ if(stylename) {
++ ns = stylens
+ }
- return node
++ }
++ if(ns) {
++ styleElement.setAttributeNS(ns, nsprefixes[ns] + "name", prefix + stylename)
+ }
+ }
- function AllChildElementIterator(it, recurse) {
- var root = it.next(), node = null;
- this.reset = function reset() {
- it.reset();
- root = it.next();
- node = null
- };
- this.next = function next() {
- while(root) {
- if(node) {
- if(recurse && node.firstChild) {
- node = node.firstChild
- }else {
- while(!node.nextSibling && node !== root) {
- node = node.parentNode
- }
- if(node === root) {
- root = it.next()
- }else {
- node = node.nextSibling
- }
- }
- }else {
- do {
- node = root.firstChild;
- if(!node) {
- root = it.next()
- }
- }while(root && !node)
- }
- if(node && node.nodeType === Node.ELEMENT_NODE) {
- return node
++ function prefixStyleNames(styleElementsRoot, prefix, styleUsingElementsRoot) {
++ var s;
++ if(styleElementsRoot) {
++ s = styleElementsRoot.firstChild;
++ while(s) {
++ if(s.nodeType === Node.ELEMENT_NODE) {
++ prefixStyleName((s), prefix)
+ }
++ s = s.nextSibling
++ }
++ prefixUsedStyleNames(styleElementsRoot, prefix);
++ if(styleUsingElementsRoot) {
++ prefixUsedStyleNames(styleUsingElementsRoot, prefix)
+ }
- return null
+ }
+ }
- function ConditionIterator(it, condition) {
- this.reset = function reset() {
- it.reset()
- };
- this.next = function next() {
- var n = it.next();
- while(n && !condition(n)) {
- n = it.next()
++ function removeRegExpFromUsedStyleNames(element, regExp) {
++ var i, stylename, e, elname, elns, a, ns, localName, length = 0;
++ elname = elements[element.localName];
++ if(elname) {
++ elns = elname[element.namespaceURI];
++ if(elns) {
++ length = elns.length
+ }
- return n
+ }
- }
- function createNodenameFilter(it, name, namespaceResolver) {
- var s = name.split(":", 2), namespace = namespaceResolver(s[0]), localName = s[1];
- return new ConditionIterator(it, function(node) {
- return node.localName === localName && node.namespaceURI === namespace
- })
- }
- function createPredicateFilteredIterator(it, p, namespaceResolver) {
- var nit = new XPathNodeIterator, pit = createXPathPathIterator(nit, p, namespaceResolver), value = p.value;
- if(value === undefined) {
- return new ConditionIterator(it, function(node) {
- nit.setNode(node);
- pit.reset();
- return pit.next()
- })
++ for(i = 0;i < length;i += 1) {
++ a = (elns[i]);
++ ns = a.ns;
++ localName = a.localname;
++ stylename = element.getAttributeNS(ns, localName);
++ if(stylename) {
++ stylename = stylename.replace(regExp, "");
++ element.setAttributeNS(ns, nsprefixes[ns] + localName, stylename)
++ }
++ }
++ e = element.firstElementChild;
++ while(e) {
++ removeRegExpFromUsedStyleNames(e, regExp);
++ e = e.nextElementSibling
+ }
- return new ConditionIterator(it, function(node) {
- nit.setNode(node);
- pit.reset();
- var n = pit.next();
- return n && n.nodeValue === value
- })
+ }
- createXPathPathIterator = function createXPathPathIterator(it, xpath, namespaceResolver) {
- var i, j, step, location, p;
- for(i = 0;i < xpath.steps.length;i += 1) {
- step = xpath.steps[i];
- location = step.location;
- if(location === "") {
- it = new AllChildElementIterator(it, false)
- }else {
- if(location[0] === "@") {
- p = location.slice(1).split(":", 2);
- it = new AttributeIterator(it, namespaceResolver(p[0]), p[1])
- }else {
- if(location !== ".") {
- it = new AllChildElementIterator(it, false);
- if(location.indexOf(":") !== -1) {
- it = createNodenameFilter(it, location, namespaceResolver)
- }
- }
- }
- }
- for(j = 0;j < step.predicates.length;j += 1) {
- p = step.predicates[j];
- it = createPredicateFilteredIterator(it, p, namespaceResolver)
++ function removeRegExpFromStyleName(styleElement, regExp) {
++ var stylename = styleElement.getAttributeNS(drawns, "name"), ns;
++ if(stylename) {
++ ns = drawns
++ }else {
++ stylename = styleElement.getAttributeNS(stylens, "name");
++ if(stylename) {
++ ns = stylens
+ }
+ }
- return it
- };
- function fallback(node, xpath, namespaceResolver) {
- var it = new XPathNodeIterator, i, nodelist, parsedXPath;
- it.setNode(node);
- parsedXPath = parseXPath(xpath);
- it = createXPathPathIterator(it, parsedXPath, namespaceResolver);
- nodelist = [];
- i = it.next();
- while(i) {
- nodelist.push(i);
- i = it.next()
++ if(ns) {
++ stylename = stylename.replace(regExp, "");
++ styleElement.setAttributeNS(ns, nsprefixes[ns] + "name", stylename)
+ }
- return nodelist
+ }
- function getODFElementsWithXPath(node, xpath, namespaceResolver) {
- var doc = node.ownerDocument, nodes, elements = [], n = null;
- if(!doc || !doc.evaluate) {
- elements = fallback(node, xpath, namespaceResolver)
- }else {
- nodes = doc.evaluate(xpath, node, namespaceResolver, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null);
- n = nodes.iterateNext();
- while(n !== null) {
- if(n.nodeType === Node.ELEMENT_NODE) {
- elements.push(n)
++ function removePrefixFromStyleNames(styleElementsRoot, prefix, styleUsingElementsRoot) {
++ var s, regExp = new RegExp("^" + prefix);
++ if(styleElementsRoot) {
++ s = styleElementsRoot.firstChild;
++ while(s) {
++ if(s.nodeType === Node.ELEMENT_NODE) {
++ removeRegExpFromStyleName((s), regExp)
+ }
- n = nodes.iterateNext()
++ s = s.nextSibling
++ }
++ removeRegExpFromUsedStyleNames(styleElementsRoot, regExp);
++ if(styleUsingElementsRoot) {
++ removeRegExpFromUsedStyleNames(styleUsingElementsRoot, regExp)
+ }
+ }
- return elements
- }
- xmldom.XPath = function XPath() {
- this.getODFElementsWithXPath = getODFElementsWithXPath
- };
- return xmldom.XPath
- }();
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- gui.AnnotationViewManager = function AnnotationViewManager(odfCanvas, odfFragment, annotationsPane) {
- var annotations = [], doc = odfFragment.ownerDocument, odfUtils = new odf.OdfUtils, CONNECTOR_MARGIN = 30, NOTE_MARGIN = 20, window = runtime.getWindow();
- runtime.assert(Boolean(window), "Expected to be run in an environment which has a global window, like a browser.");
- function wrapAnnotation(annotation) {
- var annotationWrapper = doc.createElement("div"), annotationNote = doc.createElement("div"), connectorHorizontal = doc.createElement("div"), connectorAngular = doc.createElement("div"), removeButton = doc.createElement("div"), annotationNode = annotation.node;
- annotationWrapper.className = "annotationWrapper";
- annotationNode.parentNode.insertBefore(annotationWrapper, annotationNode);
- annotationNote.className = "annotationNote";
- annotationNote.appendChild(annotationNode);
- removeButton.className = "annotationRemoveButton";
- annotationNote.appendChild(removeButton);
- connectorHorizontal.className = "annotationConnector horizontal";
- connectorAngular.className = "annotationConnector angular";
- annotationWrapper.appendChild(annotationNote);
- annotationWrapper.appendChild(connectorHorizontal);
- annotationWrapper.appendChild(connectorAngular)
+ }
- function unwrapAnnotation(annotation) {
- var annotationNode = annotation.node, annotationWrapper = annotationNode.parentNode.parentNode;
- if(annotationWrapper.localName === "div") {
- annotationWrapper.parentNode.insertBefore(annotationNode, annotationWrapper);
- annotationWrapper.parentNode.removeChild(annotationWrapper)
++ function determineStylesForNode(element, usedStyles) {
++ var i, stylename, elname, elns, a, ns, localName, keyname, length = 0, map;
++ elname = elements[element.localName];
++ if(elname) {
++ elns = elname[element.namespaceURI];
++ if(elns) {
++ length = elns.length
++ }
+ }
- }
- function highlightAnnotation(annotation) {
- var annotationNode = annotation.node, annotationEnd = annotation.end, range = doc.createRange(), textNodes;
- if(annotationEnd) {
- range.setStart(annotationNode, annotationNode.childNodes.length);
- range.setEnd(annotationEnd, 0);
- textNodes = odfUtils.getTextNodes(range, false);
- textNodes.forEach(function(n) {
- var container = doc.createElement("span");
- container.className = "annotationHighlight";
- container.setAttribute("annotation", annotationNode.getAttributeNS(odf.Namespaces.officens, "name"));
- n.parentNode.insertBefore(container, n);
- container.appendChild(n)
- })
++ for(i = 0;i < length;i += 1) {
++ a = (elns[i]);
++ ns = a.ns;
++ localName = a.localname;
++ stylename = element.getAttributeNS(ns, localName);
++ if(stylename) {
++ usedStyles = usedStyles || {};
++ keyname = a.keyname;
++ if(usedStyles.hasOwnProperty(keyname)) {
++ usedStyles[keyname][stylename] = 1
++ }else {
++ map = {};
++ map[stylename] = 1;
++ usedStyles[keyname] = map
++ }
++ }
+ }
- range.detach()
++ return usedStyles
+ }
- function unhighlightAnnotation(annotation) {
- var annotationName = annotation.node.getAttributeNS(odf.Namespaces.officens, "name"), highlightSpans = doc.querySelectorAll('span.annotationHighlight[annotation="' + annotationName + '"]'), i, container;
- for(i = 0;i < highlightSpans.length;i += 1) {
- container = highlightSpans[i];
- while(container.firstChild) {
- container.parentNode.insertBefore(container.firstChild, container)
++ function determineUsedStyles(styleUsingElementsRoot, usedStyles) {
++ var i, e;
++ determineStylesForNode(styleUsingElementsRoot, usedStyles);
++ i = styleUsingElementsRoot.firstChild;
++ while(i) {
++ if(i.nodeType === Node.ELEMENT_NODE) {
++ e = (i);
++ determineUsedStyles(e, usedStyles)
+ }
- container.parentNode.removeChild(container)
++ i = i.nextSibling
+ }
+ }
- function lineDistance(point1, point2) {
- var xs = 0, ys = 0;
- xs = point2.x - point1.x;
- xs = xs * xs;
- ys = point2.y - point1.y;
- ys = ys * ys;
- return Math.sqrt(xs + ys)
++ function StyleDefinition(key, name, family) {
++ this.key = key;
++ this.name = name;
++ this.family = family;
++ this.requires = {}
+ }
- function renderAnnotation(annotation) {
- var annotationNote = annotation.node.parentNode, connectorHorizontal = annotationNote.nextSibling, connectorAngular = connectorHorizontal.nextSibling, annotationWrapper = annotationNote.parentNode, connectorAngle = 0, previousAnnotation = annotations[annotations.indexOf(annotation) - 1], previousRect, zoomLevel = odfCanvas.getZoomLevel();
- annotationNote.style.left = (annotationsPane.getBoundingClientRect().left - annotationWrapper.getBoundingClientRect().left) / zoomLevel + "px";
- annotationNote.style.width = annotationsPane.getBoundingClientRect().width / zoomLevel + "px";
- connectorHorizontal.style.width = parseFloat(annotationNote.style.left) - CONNECTOR_MARGIN + "px";
- if(previousAnnotation) {
- previousRect = previousAnnotation.node.parentNode.getBoundingClientRect();
- if((annotationWrapper.getBoundingClientRect().top - previousRect.bottom) / zoomLevel <= NOTE_MARGIN) {
- annotationNote.style.top = Math.abs(annotationWrapper.getBoundingClientRect().top - previousRect.bottom) / zoomLevel + NOTE_MARGIN + "px"
- }else {
- annotationNote.style.top = "0px"
++ function getStyleDefinition(stylename, stylefamily, knownStyles) {
++ var styleKey = stylename + '"' + stylefamily, styleDefinition = knownStyles[styleKey];
++ if(!styleDefinition) {
++ styleDefinition = knownStyles[styleKey] = new StyleDefinition(styleKey, stylename, stylefamily)
++ }
++ return styleDefinition
++ }
++ function determineDependentStyles(element, styleScope, knownStyles) {
++ var i, stylename, elname, elns, a, ns, localName, e, referencedStyleFamily, referencedStyleDef, length = 0, newScopeName = element.getAttributeNS(stylens, "name"), newScopeFamily = element.getAttributeNS(stylens, "family");
++ if(newScopeName && newScopeFamily) {
++ styleScope = getStyleDefinition(newScopeName, newScopeFamily, knownStyles)
++ }
++ if(styleScope) {
++ elname = elements[element.localName];
++ if(elname) {
++ elns = elname[element.namespaceURI];
++ if(elns) {
++ length = elns.length
++ }
++ }
++ for(i = 0;i < length;i += 1) {
++ a = (elns[i]);
++ ns = a.ns;
++ localName = a.localname;
++ stylename = element.getAttributeNS(ns, localName);
++ if(stylename) {
++ referencedStyleFamily = a.keyname;
++ referencedStyleDef = getStyleDefinition(stylename, referencedStyleFamily, knownStyles);
++ styleScope.requires[referencedStyleDef.key] = referencedStyleDef
++ }
+ }
+ }
- connectorAngular.style.left = connectorHorizontal.getBoundingClientRect().width / zoomLevel + "px";
- connectorAngular.style.width = lineDistance({x:connectorAngular.getBoundingClientRect().left / zoomLevel, y:connectorAngular.getBoundingClientRect().top / zoomLevel}, {x:annotationNote.getBoundingClientRect().left / zoomLevel, y:annotationNote.getBoundingClientRect().top / zoomLevel}) + "px";
- connectorAngle = Math.asin((annotationNote.getBoundingClientRect().top - connectorAngular.getBoundingClientRect().top) / (zoomLevel * parseFloat(connectorAngular.style.width)));
- connectorAngular.style.transform = "rotate(" + connectorAngle + "rad)";
- connectorAngular.style.MozTransform = "rotate(" + connectorAngle + "rad)";
- connectorAngular.style.WebkitTransform = "rotate(" + connectorAngle + "rad)";
- connectorAngular.style.msTransform = "rotate(" + connectorAngle + "rad)"
++ e = element.firstElementChild;
++ while(e) {
++ determineDependentStyles(e, styleScope, knownStyles);
++ e = e.nextElementSibling
++ }
++ return knownStyles
+ }
- function showAnnotationsPane(show) {
- var sizer = odfCanvas.getSizer();
- if(show) {
- annotationsPane.style.display = "inline-block";
- sizer.style.paddingRight = window.getComputedStyle(annotationsPane).width
- }else {
- annotationsPane.style.display = "none";
- sizer.style.paddingRight = 0
++ function inverse() {
++ var i, l, keyname, list, item, e = {}, map, array, en, ens;
++ for(keyname in elementstyles) {
++ if(elementstyles.hasOwnProperty(keyname)) {
++ list = elementstyles[keyname];
++ l = list.length;
++ for(i = 0;i < l;i += 1) {
++ item = list[i];
++ en = item.en;
++ ens = item.ens;
++ if(e.hasOwnProperty(en)) {
++ map = e[en]
++ }else {
++ e[en] = map = {}
++ }
++ if(map.hasOwnProperty(ens)) {
++ array = map[ens]
++ }else {
++ map[ens] = array = []
++ }
++ array.push({ns:item.ans, localname:item.a, keyname:keyname})
++ }
++ }
+ }
- odfCanvas.refreshSize()
++ return e
+ }
- function sortAnnotations() {
- annotations.sort(function(a, b) {
- if(a.node.compareDocumentPosition(b.node) === Node.DOCUMENT_POSITION_FOLLOWING) {
- return-1
++ function mergeRequiredStyles(styleDependency, usedStyles) {
++ var family = usedStyles[styleDependency.family];
++ if(!family) {
++ family = usedStyles[styleDependency.family] = {}
++ }
++ family[styleDependency.name] = 1;
++ Object.keys((styleDependency.requires)).forEach(function(requiredStyleKey) {
++ mergeRequiredStyles((styleDependency.requires[requiredStyleKey]), usedStyles)
++ })
++ }
++ function mergeUsedAutomaticStyles(automaticStylesRoot, usedStyles) {
++ var automaticStyles = determineDependentStyles(automaticStylesRoot, null, {});
++ Object.keys(automaticStyles).forEach(function(styleKey) {
++ var automaticStyleDefinition = automaticStyles[styleKey], usedFamily = usedStyles[automaticStyleDefinition.family];
++ if(usedFamily && usedFamily.hasOwnProperty(automaticStyleDefinition.name)) {
++ mergeRequiredStyles(automaticStyleDefinition, usedStyles)
+ }
- return 1
+ })
+ }
- function rerenderAnnotations() {
- var i;
- for(i = 0;i < annotations.length;i += 1) {
- renderAnnotation(annotations[i])
++ function collectUsedFontFaces(usedFontFaceDeclMap, styleElement) {
++ var localNames = ["font-name", "font-name-asian", "font-name-complex"], e, currentElement;
++ function collectByAttribute(localName) {
++ var fontFaceName = currentElement.getAttributeNS(stylens, localName);
++ if(fontFaceName) {
++ usedFontFaceDeclMap[fontFaceName] = true
++ }
+ }
- }
- this.rerenderAnnotations = rerenderAnnotations;
- function addAnnotation(annotation) {
- showAnnotationsPane(true);
- annotations.push({node:annotation.node, end:annotation.end});
- sortAnnotations();
- wrapAnnotation(annotation);
- if(annotation.end) {
- highlightAnnotation(annotation)
++ e = styleElement && styleElement.firstElementChild;
++ while(e) {
++ currentElement = e;
++ localNames.forEach(collectByAttribute);
++ collectUsedFontFaces(usedFontFaceDeclMap, currentElement);
++ e = e.nextElementSibling
+ }
- rerenderAnnotations()
+ }
- this.addAnnotation = addAnnotation;
- function forgetAnnotation(annotation) {
- var index = annotations.indexOf(annotation);
- unwrapAnnotation(annotation);
- unhighlightAnnotation(annotation);
- if(index !== -1) {
- annotations.splice(index, 1)
++ this.collectUsedFontFaces = collectUsedFontFaces;
++ function changeFontFaceNames(styleElement, fontFaceNameChangeMap) {
++ var localNames = ["font-name", "font-name-asian", "font-name-complex"], e, currentElement;
++ function changeFontFaceNameByAttribute(localName) {
++ var fontFaceName = currentElement.getAttributeNS(stylens, localName);
++ if(fontFaceName && fontFaceNameChangeMap.hasOwnProperty(fontFaceName)) {
++ currentElement.setAttributeNS(stylens, "style:" + localName, fontFaceNameChangeMap[fontFaceName])
++ }
+ }
- if(annotations.length === 0) {
- showAnnotationsPane(false)
++ e = styleElement && styleElement.firstElementChild;
++ while(e) {
++ currentElement = e;
++ localNames.forEach(changeFontFaceNameByAttribute);
++ changeFontFaceNames(currentElement, fontFaceNameChangeMap);
++ e = e.nextElementSibling
+ }
+ }
- function forgetAnnotations() {
- while(annotations.length) {
- forgetAnnotation(annotations[0])
++ this.changeFontFaceNames = changeFontFaceNames;
++ this.UsedStyleList = function(styleUsingElementsRoot, automaticStylesRoot) {
++ var usedStyles = {};
++ this.uses = function(element) {
++ var localName = element.localName, name = element.getAttributeNS(drawns, "name") || element.getAttributeNS(stylens, "name"), keyName, map;
++ if(localName === "style") {
++ keyName = element.getAttributeNS(stylens, "family")
++ }else {
++ if(element.namespaceURI === numberns) {
++ keyName = "data"
++ }else {
++ keyName = localName
++ }
++ }
++ map = usedStyles[keyName];
++ return map ? map[name] > 0 : false
++ };
++ determineUsedStyles(styleUsingElementsRoot, usedStyles);
++ if(automaticStylesRoot) {
++ mergeUsedAutomaticStyles(automaticStylesRoot, usedStyles)
+ }
- }
- this.forgetAnnotations = forgetAnnotations
++ };
++ this.hasDerivedStyles = hasDerivedStyles;
++ this.prefixStyleNames = prefixStyleNames;
++ this.removePrefixFromStyleNames = removePrefixFromStyleNames;
++ this.determineStylesForNode = determineStylesForNode;
++ elements = inverse()
+};
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- odf.OdfNodeFilter = function OdfNodeFilter() {
- this.acceptNode = function(node) {
- var result;
- if(node.namespaceURI === "http://www.w3.org/1999/xhtml") {
- result = NodeFilter.FILTER_SKIP
- }else {
- if(node.namespaceURI && node.namespaceURI.match(/^urn:webodf:/)) {
- result = NodeFilter.FILTER_REJECT
++runtime.loadClass("odf.OdfUtils");
++odf.TextSerializer = function TextSerializer() {
++ var self = this, odfUtils = new odf.OdfUtils;
++ function serializeNode(node) {
++ var s = "", accept = self.filter ? self.filter.acceptNode(node) : NodeFilter.FILTER_ACCEPT, nodeType = node.nodeType, child;
++ if(accept === NodeFilter.FILTER_ACCEPT || accept === NodeFilter.FILTER_SKIP) {
++ child = node.firstChild;
++ while(child) {
++ s += serializeNode(child);
++ child = child.nextSibling
++ }
++ }
++ if(accept === NodeFilter.FILTER_ACCEPT) {
++ if(nodeType === Node.ELEMENT_NODE && odfUtils.isParagraph(node)) {
++ s += "\n"
+ }else {
- result = NodeFilter.FILTER_ACCEPT
++ if(nodeType === Node.TEXT_NODE && node.textContent) {
++ s += node.textContent
++ }
+ }
+ }
- return result
++ return s
++ }
++ this.filter = null;
++ this.writeToString = function(node) {
++ var plainText;
++ if(!node) {
++ return""
++ }
++ plainText = serializeNode(node);
++ if(plainText[plainText.length - 1] === "\n") {
++ plainText = plainText.substr(0, plainText.length - 1)
++ }
++ return plainText
+ }
+};
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- odf.Namespaces = function() {
- var dbns = "urn:oasis:names:tc:opendocument:xmlns:database:1.0", dcns = "http://purl.org/dc/elements/1.1/", metans = "urn:oasis:names:tc:opendocument:xmlns:meta:1.0", dr3dns = "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0", drawns = "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0", chartns = "urn:oasis:names:tc:opendocument:xmlns:chart:1.0", fons = "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0", formns = "urn:oasis:names:tc:opendocument:xmlns:form:1.0", numberns = [...]
- officens = "urn:oasis:names:tc:opendocument:xmlns:office:1.0", presentationns = "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0", stylens = "urn:oasis:names:tc:opendocument:xmlns:style:1.0", svgns = "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0", tablens = "urn:oasis:names:tc:opendocument:xmlns:table:1.0", textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0", xlinkns = "http://www.w3.org/1999/xlink", xmlns = "http://www.w3.org/XML/1998/namespace", namespaceMap [...]
- "dc":dcns, "meta":metans, "dr3d":dr3dns, "draw":drawns, "chart":chartns, "fo":fons, "form":formns, "numberns":numberns, "office":officens, "presentation":presentationns, "style":stylens, "svg":svgns, "table":tablens, "text":textns, "xlink":xlinkns, "xml":xmlns}, namespaces;
- function forEachPrefix(cb) {
- var prefix;
- for(prefix in namespaceMap) {
- if(namespaceMap.hasOwnProperty(prefix)) {
- cb(prefix, namespaceMap[prefix])
- }
- }
- }
- function resolvePrefix(prefix) {
- return namespaceMap[prefix] || null
- }
- function lookupPrefix(namespaceURI) {
- var foundPrefix, prefix;
- for(prefix in namespaceMap) {
- if(namespaceMap.hasOwnProperty(prefix) && namespaceMap[prefix] === namespaceURI) {
- foundPrefix = prefix;
- break
++runtime.loadClass("core.PositionFilter");
++runtime.loadClass("odf.OdfUtils");
++ops.TextPositionFilter = function TextPositionFilter(getRootNode) {
++ var odfUtils = new odf.OdfUtils, ELEMENT_NODE = Node.ELEMENT_NODE, TEXT_NODE = Node.TEXT_NODE, FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT, FILTER_REJECT = core.PositionFilter.FilterResult.FILTER_REJECT;
++ function checkLeftRight(container, leftNode, rightNode) {
++ var r, firstPos, rightOfChar;
++ if(leftNode) {
++ r = odfUtils.lookLeftForCharacter(leftNode);
++ if(r === 1) {
++ return FILTER_ACCEPT
++ }
++ if(r === 2 && (odfUtils.scanRightForAnyCharacter(rightNode) || odfUtils.scanRightForAnyCharacter(odfUtils.nextNode(container)))) {
++ return FILTER_ACCEPT
+ }
+ }
- return foundPrefix
- }
- resolvePrefix.lookupNamespaceURI = resolvePrefix;
- namespaces = function Namespaces() {
- };
- namespaces.forEachPrefix = forEachPrefix;
- namespaces.resolvePrefix = resolvePrefix;
- namespaces.lookupPrefix = lookupPrefix;
- namespaces.namespaceMap = namespaceMap;
- namespaces.dbns = dbns;
- namespaces.dcns = dcns;
- namespaces.metans = metans;
- namespaces.dr3dns = dr3dns;
- namespaces.drawns = drawns;
- namespaces.chartns = chartns;
- namespaces.fons = fons;
- namespaces.formns = formns;
- namespaces.numberns = numberns;
- namespaces.officens = officens;
- namespaces.presentationns = presentationns;
- namespaces.stylens = stylens;
- namespaces.svgns = svgns;
- namespaces.tablens = tablens;
- namespaces.textns = textns;
- namespaces.xlinkns = xlinkns;
- namespaces.xmlns = xmlns;
- return namespaces
- }();
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- runtime.loadClass("xmldom.XPath");
- runtime.loadClass("odf.Namespaces");
- odf.StyleInfo = function StyleInfo() {
- var chartns = odf.Namespaces.chartns, dbns = odf.Namespaces.dbns, dr3dns = odf.Namespaces.dr3dns, drawns = odf.Namespaces.drawns, formns = odf.Namespaces.formns, numberns = odf.Namespaces.numberns, officens = odf.Namespaces.officens, presentationns = odf.Namespaces.presentationns, stylens = odf.Namespaces.stylens, tablens = odf.Namespaces.tablens, textns = odf.Namespaces.textns, nsprefixes = {"urn:oasis:names:tc:opendocument:xmlns:chart:1.0":"chart:", "urn:oasis:names:tc:opendocument: [...]
- "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0":"dr3d:", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0":"draw:", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0":"fo:", "urn:oasis:names:tc:opendocument:xmlns:form:1.0":"form:", "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0":"number:", "urn:oasis:names:tc:opendocument:xmlns:office:1.0":"office:", "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0":"presentation:", "urn:oasis:names:tc:opendocument:xmlns:sty [...]
- "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0":"svg:", "urn:oasis:names:tc:opendocument:xmlns:table:1.0":"table:", "urn:oasis:names:tc:opendocument:xmlns:text:1.0":"chart:", "http://www.w3.org/XML/1998/namespace":"xml:"}, elementstyles = {"text":[{ens:stylens, en:"tab-stop", ans:stylens, a:"leader-text-style"}, {ens:stylens, en:"drop-cap", ans:stylens, a:"style-name"}, {ens:textns, en:"notes-configuration", ans:textns, a:"citation-body-style-name"}, {ens:textns, en:"notes- [...]
- ans:textns, a:"citation-style-name"}, {ens:textns, en:"a", ans:textns, a:"style-name"}, {ens:textns, en:"alphabetical-index", ans:textns, a:"style-name"}, {ens:textns, en:"linenumbering-configuration", ans:textns, a:"style-name"}, {ens:textns, en:"list-level-style-number", ans:textns, a:"style-name"}, {ens:textns, en:"ruby-text", ans:textns, a:"style-name"}, {ens:textns, en:"span", ans:textns, a:"style-name"}, {ens:textns, en:"a", ans:textns, a:"visited-style-name"}, {ens:stylens, en: [...]
- ans:stylens, a:"text-line-through-text-style"}, {ens:textns, en:"alphabetical-index-source", ans:textns, a:"main-entry-style-name"}, {ens:textns, en:"index-entry-bibliography", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-chapter", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-link-end", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-link-start", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-page-number", ans:textns, a:"style-name"}, {en [...]
- en:"index-entry-span", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-tab-stop", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-text", ans:textns, a:"style-name"}, {ens:textns, en:"index-title-template", ans:textns, a:"style-name"}, {ens:textns, en:"list-level-style-bullet", ans:textns, a:"style-name"}, {ens:textns, en:"outline-level-style", ans:textns, a:"style-name"}], "paragraph":[{ens:drawns, en:"caption", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"ci [...]
- a:"text-style-name"}, {ens:drawns, en:"connector", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"control", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"custom-shape", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"ellipse", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"frame", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"line", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"measure", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"path", ans:drawns, a: [...]
- {ens:drawns, en:"polygon", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"polyline", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"rect", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"regular-polygon", ans:drawns, a:"text-style-name"}, {ens:officens, en:"annotation", ans:drawns, a:"text-style-name"}, {ens:formns, en:"column", ans:formns, a:"text-style-name"}, {ens:stylens, en:"style", ans:stylens, a:"next-style-name"}, {ens:tablens, en:"body", ans:tablens, a:"paragraph-s [...]
- {ens:tablens, en:"even-columns", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"even-rows", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"first-column", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"first-row", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"last-column", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"last-row", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"odd-columns", ans:tablens, a:"paragraph-styl [...]
- {ens:tablens, en:"odd-rows", ans:tablens, a:"paragraph-style-name"}, {ens:textns, en:"notes-configuration", ans:textns, a:"default-style-name"}, {ens:textns, en:"alphabetical-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"bibliography-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"h", ans:textns, a:"style-name"}, {ens:textns, en:"illustration-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"index-source-style", ans:textns, a:"s [...]
- {ens:textns, en:"object-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"p", ans:textns, a:"style-name"}, {ens:textns, en:"table-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"table-of-content-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"table-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"user-index-entry-template", ans:textns, a:"style-name"}, {ens:stylens, en:"page-layout-properties", ans:stylens, a:" [...]
- "chart":[{ens:chartns, en:"axis", ans:chartns, a:"style-name"}, {ens:chartns, en:"chart", ans:chartns, a:"style-name"}, {ens:chartns, en:"data-label", ans:chartns, a:"style-name"}, {ens:chartns, en:"data-point", ans:chartns, a:"style-name"}, {ens:chartns, en:"equation", ans:chartns, a:"style-name"}, {ens:chartns, en:"error-indicator", ans:chartns, a:"style-name"}, {ens:chartns, en:"floor", ans:chartns, a:"style-name"}, {ens:chartns, en:"footer", ans:chartns, a:"style-name"}, {ens:char [...]
- ans:chartns, a:"style-name"}, {ens:chartns, en:"legend", ans:chartns, a:"style-name"}, {ens:chartns, en:"mean-value", ans:chartns, a:"style-name"}, {ens:chartns, en:"plot-area", ans:chartns, a:"style-name"}, {ens:chartns, en:"regression-curve", ans:chartns, a:"style-name"}, {ens:chartns, en:"series", ans:chartns, a:"style-name"}, {ens:chartns, en:"stock-gain-marker", ans:chartns, a:"style-name"}, {ens:chartns, en:"stock-loss-marker", ans:chartns, a:"style-name"}, {ens:chartns, en:"sto [...]
- ans:chartns, a:"style-name"}, {ens:chartns, en:"subtitle", ans:chartns, a:"style-name"}, {ens:chartns, en:"title", ans:chartns, a:"style-name"}, {ens:chartns, en:"wall", ans:chartns, a:"style-name"}], "section":[{ens:textns, en:"alphabetical-index", ans:textns, a:"style-name"}, {ens:textns, en:"bibliography", ans:textns, a:"style-name"}, {ens:textns, en:"illustration-index", ans:textns, a:"style-name"}, {ens:textns, en:"index-title", ans:textns, a:"style-name"}, {ens:textns, en:"objec [...]
- ans:textns, a:"style-name"}, {ens:textns, en:"section", ans:textns, a:"style-name"}, {ens:textns, en:"table-of-content", ans:textns, a:"style-name"}, {ens:textns, en:"table-index", ans:textns, a:"style-name"}, {ens:textns, en:"user-index", ans:textns, a:"style-name"}], "ruby":[{ens:textns, en:"ruby", ans:textns, a:"style-name"}], "table":[{ens:dbns, en:"query", ans:dbns, a:"style-name"}, {ens:dbns, en:"table-representation", ans:dbns, a:"style-name"}, {ens:tablens, en:"background", an [...]
- a:"style-name"}, {ens:tablens, en:"table", ans:tablens, a:"style-name"}], "table-column":[{ens:dbns, en:"column", ans:dbns, a:"style-name"}, {ens:tablens, en:"table-column", ans:tablens, a:"style-name"}], "table-row":[{ens:dbns, en:"query", ans:dbns, a:"default-row-style-name"}, {ens:dbns, en:"table-representation", ans:dbns, a:"default-row-style-name"}, {ens:tablens, en:"table-row", ans:tablens, a:"style-name"}], "table-cell":[{ens:dbns, en:"column", ans:dbns, a:"default-cell-style-n [...]
- en:"table-column", ans:tablens, a:"default-cell-style-name"}, {ens:tablens, en:"table-row", ans:tablens, a:"default-cell-style-name"}, {ens:tablens, en:"body", ans:tablens, a:"style-name"}, {ens:tablens, en:"covered-table-cell", ans:tablens, a:"style-name"}, {ens:tablens, en:"even-columns", ans:tablens, a:"style-name"}, {ens:tablens, en:"covered-table-cell", ans:tablens, a:"style-name"}, {ens:tablens, en:"even-columns", ans:tablens, a:"style-name"}, {ens:tablens, en:"even-rows", ans:t [...]
- {ens:tablens, en:"first-column", ans:tablens, a:"style-name"}, {ens:tablens, en:"first-row", ans:tablens, a:"style-name"}, {ens:tablens, en:"last-column", ans:tablens, a:"style-name"}, {ens:tablens, en:"last-row", ans:tablens, a:"style-name"}, {ens:tablens, en:"odd-columns", ans:tablens, a:"style-name"}, {ens:tablens, en:"odd-rows", ans:tablens, a:"style-name"}, {ens:tablens, en:"table-cell", ans:tablens, a:"style-name"}], "graphic":[{ens:dr3dns, en:"cube", ans:drawns, a:"style-name"} [...]
- en:"extrude", ans:drawns, a:"style-name"}, {ens:dr3dns, en:"rotate", ans:drawns, a:"style-name"}, {ens:dr3dns, en:"scene", ans:drawns, a:"style-name"}, {ens:dr3dns, en:"sphere", ans:drawns, a:"style-name"}, {ens:drawns, en:"caption", ans:drawns, a:"style-name"}, {ens:drawns, en:"circle", ans:drawns, a:"style-name"}, {ens:drawns, en:"connector", ans:drawns, a:"style-name"}, {ens:drawns, en:"control", ans:drawns, a:"style-name"}, {ens:drawns, en:"custom-shape", ans:drawns, a:"style-name [...]
- en:"ellipse", ans:drawns, a:"style-name"}, {ens:drawns, en:"frame", ans:drawns, a:"style-name"}, {ens:drawns, en:"g", ans:drawns, a:"style-name"}, {ens:drawns, en:"line", ans:drawns, a:"style-name"}, {ens:drawns, en:"measure", ans:drawns, a:"style-name"}, {ens:drawns, en:"page-thumbnail", ans:drawns, a:"style-name"}, {ens:drawns, en:"path", ans:drawns, a:"style-name"}, {ens:drawns, en:"polygon", ans:drawns, a:"style-name"}, {ens:drawns, en:"polyline", ans:drawns, a:"style-name"}, {ens [...]
- ans:drawns, a:"style-name"}, {ens:drawns, en:"regular-polygon", ans:drawns, a:"style-name"}, {ens:officens, en:"annotation", ans:drawns, a:"style-name"}], "presentation":[{ens:dr3dns, en:"cube", ans:presentationns, a:"style-name"}, {ens:dr3dns, en:"extrude", ans:presentationns, a:"style-name"}, {ens:dr3dns, en:"rotate", ans:presentationns, a:"style-name"}, {ens:dr3dns, en:"scene", ans:presentationns, a:"style-name"}, {ens:dr3dns, en:"sphere", ans:presentationns, a:"style-name"}, {ens: [...]
- ans:presentationns, a:"style-name"}, {ens:drawns, en:"circle", ans:presentationns, a:"style-name"}, {ens:drawns, en:"connector", ans:presentationns, a:"style-name"}, {ens:drawns, en:"control", ans:presentationns, a:"style-name"}, {ens:drawns, en:"custom-shape", ans:presentationns, a:"style-name"}, {ens:drawns, en:"ellipse", ans:presentationns, a:"style-name"}, {ens:drawns, en:"frame", ans:presentationns, a:"style-name"}, {ens:drawns, en:"g", ans:presentationns, a:"style-name"}, {ens:d [...]
- ans:presentationns, a:"style-name"}, {ens:drawns, en:"measure", ans:presentationns, a:"style-name"}, {ens:drawns, en:"page-thumbnail", ans:presentationns, a:"style-name"}, {ens:drawns, en:"path", ans:presentationns, a:"style-name"}, {ens:drawns, en:"polygon", ans:presentationns, a:"style-name"}, {ens:drawns, en:"polyline", ans:presentationns, a:"style-name"}, {ens:drawns, en:"rect", ans:presentationns, a:"style-name"}, {ens:drawns, en:"regular-polygon", ans:presentationns, a:"style-na [...]
- en:"annotation", ans:presentationns, a:"style-name"}], "drawing-page":[{ens:drawns, en:"page", ans:drawns, a:"style-name"}, {ens:presentationns, en:"notes", ans:drawns, a:"style-name"}, {ens:stylens, en:"handout-master", ans:drawns, a:"style-name"}, {ens:stylens, en:"master-page", ans:drawns, a:"style-name"}], "list-style":[{ens:textns, en:"list", ans:textns, a:"style-name"}, {ens:textns, en:"numbered-paragraph", ans:textns, a:"style-name"}, {ens:textns, en:"list-item", ans:textns, a: [...]
- {ens:stylens, en:"style", ans:stylens, a:"list-style-name"}], "data":[{ens:stylens, en:"style", ans:stylens, a:"data-style-name"}, {ens:stylens, en:"style", ans:stylens, a:"percentage-data-style-name"}, {ens:presentationns, en:"date-time-decl", ans:stylens, a:"data-style-name"}, {ens:textns, en:"creation-date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"creation-time", ans:stylens, a:"data-style-name"}, {ens:textns, en:"database-display", ans:stylens, a:"data-style-name"}, {e [...]
- en:"date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"editing-duration", ans:stylens, a:"data-style-name"}, {ens:textns, en:"expression", ans:stylens, a:"data-style-name"}, {ens:textns, en:"meta-field", ans:stylens, a:"data-style-name"}, {ens:textns, en:"modification-date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"modification-time", ans:stylens, a:"data-style-name"}, {ens:textns, en:"print-date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"print-time", ans [...]
- a:"data-style-name"}, {ens:textns, en:"table-formula", ans:stylens, a:"data-style-name"}, {ens:textns, en:"time", ans:stylens, a:"data-style-name"}, {ens:textns, en:"user-defined", ans:stylens, a:"data-style-name"}, {ens:textns, en:"user-field-get", ans:stylens, a:"data-style-name"}, {ens:textns, en:"user-field-input", ans:stylens, a:"data-style-name"}, {ens:textns, en:"variable-get", ans:stylens, a:"data-style-name"}, {ens:textns, en:"variable-input", ans:stylens, a:"data-style-name" [...]
- en:"variable-set", ans:stylens, a:"data-style-name"}], "page-layout":[{ens:presentationns, en:"notes", ans:stylens, a:"page-layout-name"}, {ens:stylens, en:"handout-master", ans:stylens, a:"page-layout-name"}, {ens:stylens, en:"master-page", ans:stylens, a:"page-layout-name"}]}, elements, xpath = new xmldom.XPath;
- function hasDerivedStyles(odfbody, nsResolver, styleElement) {
- var nodes, xp, resolver = nsResolver("style"), styleName = styleElement.getAttributeNS(resolver, "name"), styleFamily = styleElement.getAttributeNS(resolver, "family");
- xp = "//style:*[@style:parent-style-name='" + styleName + "'][@style:family='" + styleFamily + "']";
- nodes = xpath.getODFElementsWithXPath(odfbody, xp, nsResolver);
- if(nodes.length) {
- return true
- }
- return false
- }
- function prefixUsedStyleNames(styleUsingElementsRoot, prefix) {
- var elname = elements[styleUsingElementsRoot.localName], elns = elname && elname[styleUsingElementsRoot.namespaceURI], length = elns ? elns.length : 0, i, stylename, e;
- for(i = 0;i < length;i += 1) {
- stylename = styleUsingElementsRoot.getAttributeNS(elns[i].ns, elns[i].localname);
- if(stylename) {
- styleUsingElementsRoot.setAttributeNS(elns[i].ns, nsprefixes[elns[i].ns] + elns[i].localname, prefix + stylename)
++ firstPos = leftNode === null && odfUtils.isParagraph(container);
++ rightOfChar = odfUtils.lookRightForCharacter(rightNode);
++ if(firstPos) {
++ if(rightOfChar) {
++ return FILTER_ACCEPT
+ }
++ return odfUtils.scanRightForAnyCharacter(rightNode) ? FILTER_REJECT : FILTER_ACCEPT
+ }
- i = styleUsingElementsRoot.firstChild;
- while(i) {
- if(i.nodeType === Node.ELEMENT_NODE) {
- e = (i);
- prefixUsedStyleNames(e, prefix)
- }
- i = i.nextSibling
++ if(!rightOfChar) {
++ return FILTER_REJECT
+ }
++ leftNode = leftNode || odfUtils.previousNode(container);
++ return odfUtils.scanLeftForAnyCharacter(leftNode) ? FILTER_REJECT : FILTER_ACCEPT
+ }
- function prefixStyleName(styleElement, prefix) {
- var stylename = styleElement.getAttributeNS(drawns, "name"), ns;
- if(stylename) {
- ns = drawns
++ this.acceptPosition = function(iterator) {
++ var container = iterator.container(), nodeType = container.nodeType, offset, text, leftChar, rightChar, leftNode, rightNode, r;
++ if(nodeType !== ELEMENT_NODE && nodeType !== TEXT_NODE) {
++ return FILTER_REJECT
++ }
++ if(nodeType === TEXT_NODE) {
++ if(!odfUtils.isGroupingElement(container.parentNode) || odfUtils.isWithinTrackedChanges(container.parentNode, getRootNode())) {
++ return FILTER_REJECT
++ }
++ offset = iterator.unfilteredDomOffset();
++ text = container.data;
++ runtime.assert(offset !== text.length, "Unexpected offset.");
++ if(offset > 0) {
++ leftChar = (text[offset - 1]);
++ if(!odfUtils.isODFWhitespace(leftChar)) {
++ return FILTER_ACCEPT
++ }
++ if(offset > 1) {
++ leftChar = (text[offset - 2]);
++ if(!odfUtils.isODFWhitespace(leftChar)) {
++ r = FILTER_ACCEPT
++ }else {
++ if(!odfUtils.isODFWhitespace(text.substr(0, offset))) {
++ return FILTER_REJECT
++ }
++ }
++ }else {
++ leftNode = odfUtils.previousNode(container);
++ if(odfUtils.scanLeftForNonSpace(leftNode)) {
++ r = FILTER_ACCEPT
++ }
++ }
++ if(r === FILTER_ACCEPT) {
++ return odfUtils.isTrailingWhitespace((container), offset) ? FILTER_REJECT : FILTER_ACCEPT
++ }
++ rightChar = (text[offset]);
++ if(odfUtils.isODFWhitespace(rightChar)) {
++ return FILTER_REJECT
++ }
++ return odfUtils.scanLeftForAnyCharacter(odfUtils.previousNode(container)) ? FILTER_REJECT : FILTER_ACCEPT
++ }
++ leftNode = iterator.leftNode();
++ rightNode = container;
++ container = (container.parentNode);
++ r = checkLeftRight(container, leftNode, rightNode)
+ }else {
- stylename = styleElement.getAttributeNS(stylens, "name");
- if(stylename) {
- ns = stylens
++ if(!odfUtils.isGroupingElement(container) || odfUtils.isWithinTrackedChanges(container, getRootNode())) {
++ r = FILTER_REJECT
++ }else {
++ leftNode = iterator.leftNode();
++ rightNode = iterator.rightNode();
++ r = checkLeftRight(container, leftNode, rightNode)
+ }
+ }
- if(ns) {
- styleElement.setAttributeNS(ns, nsprefixes[ns] + "name", prefix + stylename)
- }
++ return r
+ }
- function prefixStyleNames(styleElementsRoot, prefix, styleUsingElementsRoot) {
- var s;
- if(styleElementsRoot) {
- s = styleElementsRoot.firstChild;
- while(s) {
- if(s.nodeType === Node.ELEMENT_NODE) {
- prefixStyleName((s), prefix)
++};
++if(typeof Object.create !== "function") {
++ Object["create"] = function(o) {
++ var F = function() {
++ };
++ F.prototype = o;
++ return new F
++ }
++}
++xmldom.LSSerializer = function LSSerializer() {
++ var self = this;
++ function Namespaces(nsmap) {
++ function invertMap(map) {
++ var m = {}, i;
++ for(i in map) {
++ if(map.hasOwnProperty(i)) {
++ m[map[i]] = i
+ }
- s = s.nextSibling
+ }
- prefixUsedStyleNames(styleElementsRoot, prefix);
- if(styleUsingElementsRoot) {
- prefixUsedStyleNames(styleUsingElementsRoot, prefix)
++ return m
++ }
++ var current = nsmap || {}, currentrev = invertMap(nsmap), levels = [current], levelsrev = [currentrev], level = 0;
++ this.push = function() {
++ level += 1;
++ current = levels[level] = Object.create(current);
++ currentrev = levelsrev[level] = Object.create(currentrev)
++ };
++ this.pop = function() {
++ levels.pop();
++ levelsrev.pop();
++ level -= 1;
++ current = levels[level];
++ currentrev = levelsrev[level]
++ };
++ this.getLocalNamespaceDefinitions = function() {
++ return currentrev
++ };
++ this.getQName = function(node) {
++ var ns = node.namespaceURI, i = 0, p;
++ if(!ns) {
++ return node.localName
++ }
++ p = currentrev[ns];
++ if(p) {
++ return p + ":" + node.localName
+ }
++ do {
++ if(p || !node.prefix) {
++ p = "ns" + i;
++ i += 1
++ }else {
++ p = node.prefix
++ }
++ if(current[p] === ns) {
++ break
++ }
++ if(!current[p]) {
++ current[p] = ns;
++ currentrev[ns] = p;
++ break
++ }
++ p = null
++ }while(p === null);
++ return p + ":" + node.localName
+ }
+ }
- function removeRegExpFromUsedStyleNames(styleUsingElementsRoot, regExp) {
- var elname = elements[styleUsingElementsRoot.localName], elns = elname && elname[styleUsingElementsRoot.namespaceURI], length = elns ? elns.length : 0, i, stylename, e;
++ function escapeContent(value) {
++ return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/'/g, "'").replace(/"/g, """)
++ }
++ function serializeAttribute(qname, attr) {
++ var escapedValue = typeof attr.value === "string" ? escapeContent(attr.value) : attr.value, s = qname + '="' + escapedValue + '"';
++ return s
++ }
++ function startElement(ns, qname, element) {
++ var s = "", atts = (element.attributes), length, i, attr, attstr = "", accept, prefix, nsmap;
++ s += "<" + qname;
++ length = atts.length;
+ for(i = 0;i < length;i += 1) {
- stylename = styleUsingElementsRoot.getAttributeNS(elns[i].ns, elns[i].localname);
- if(stylename) {
- stylename = stylename.replace(regExp, "");
- styleUsingElementsRoot.setAttributeNS(elns[i].ns, nsprefixes[elns[i].ns] + elns[i].localname, stylename)
++ attr = (atts.item(i));
++ if(attr.namespaceURI !== "http://www.w3.org/2000/xmlns/") {
++ accept = self.filter ? self.filter.acceptNode(attr) : NodeFilter.FILTER_ACCEPT;
++ if(accept === NodeFilter.FILTER_ACCEPT) {
++ attstr += " " + serializeAttribute(ns.getQName(attr), attr)
++ }
+ }
+ }
- i = styleUsingElementsRoot.firstChild;
- while(i) {
- if(i.nodeType === Node.ELEMENT_NODE) {
- e = (i);
- removeRegExpFromUsedStyleNames(e, regExp)
++ nsmap = ns.getLocalNamespaceDefinitions();
++ for(i in nsmap) {
++ if(nsmap.hasOwnProperty(i)) {
++ prefix = nsmap[i];
++ if(!prefix) {
++ s += ' xmlns="' + i + '"'
++ }else {
++ if(prefix !== "xmlns") {
++ s += " xmlns:" + nsmap[i] + '="' + i + '"'
++ }
++ }
+ }
- i = i.nextSibling
+ }
++ s += attstr + ">";
++ return s
+ }
- function removeRegExpFromStyleName(styleElement, regExp) {
- var stylename = styleElement.getAttributeNS(drawns, "name"), ns;
- if(stylename) {
- ns = drawns
- }else {
- stylename = styleElement.getAttributeNS(stylens, "name");
- if(stylename) {
- ns = stylens
- }
- }
- if(ns) {
- stylename = stylename.replace(regExp, "");
- styleElement.setAttributeNS(ns, nsprefixes[ns] + "name", stylename)
++ function serializeNode(ns, node) {
++ var s = "", accept = self.filter ? self.filter.acceptNode(node) : NodeFilter.FILTER_ACCEPT, child, qname;
++ if(accept === NodeFilter.FILTER_ACCEPT && node.nodeType === Node.ELEMENT_NODE) {
++ ns.push();
++ qname = ns.getQName(node);
++ s += startElement(ns, qname, node)
+ }
- }
- function removePrefixFromStyleNames(styleElementsRoot, prefix, styleUsingElementsRoot) {
- var s, regExp = new RegExp("^" + prefix);
- if(styleElementsRoot) {
- s = styleElementsRoot.firstChild;
- while(s) {
- if(s.nodeType === Node.ELEMENT_NODE) {
- removeRegExpFromStyleName((s), regExp)
- }
- s = s.nextSibling
++ if(accept === NodeFilter.FILTER_ACCEPT || accept === NodeFilter.FILTER_SKIP) {
++ child = node.firstChild;
++ while(child) {
++ s += serializeNode(ns, child);
++ child = child.nextSibling
+ }
- removeRegExpFromUsedStyleNames(styleElementsRoot, regExp);
- if(styleUsingElementsRoot) {
- removeRegExpFromUsedStyleNames(styleUsingElementsRoot, regExp)
++ if(node.nodeValue) {
++ s += escapeContent(node.nodeValue)
+ }
+ }
- }
- function determineStylesForNode(node, usedStyles) {
- var elname = elements[node.localName], elns = elname && elname[node.namespaceURI], length = elns ? elns.length : 0, stylename, keyname, map, i;
- for(i = 0;i < length;i += 1) {
- stylename = node.getAttributeNS(elns[i].ns, elns[i].localname);
- if(stylename) {
- usedStyles = usedStyles || {};
- keyname = elns[i].keyname;
- map = usedStyles[keyname] = usedStyles[keyname] || {};
- map[stylename] = 1
- }
++ if(qname) {
++ s += "</" + qname + ">";
++ ns.pop()
+ }
- return usedStyles
++ return s
+ }
- function determineUsedStyles(styleUsingElementsRoot, usedStyles) {
- var i, e;
- determineStylesForNode(styleUsingElementsRoot, usedStyles);
- i = styleUsingElementsRoot.firstChild;
- while(i) {
- if(i.nodeType === Node.ELEMENT_NODE) {
- e = (i);
- determineUsedStyles(e, usedStyles)
- }
- i = i.nextSibling
++ this.filter = null;
++ this.writeToString = function(node, nsmap) {
++ if(!node) {
++ return""
+ }
++ var ns = new Namespaces(nsmap);
++ return serializeNode(ns, node)
+ }
- function StyleDefinition(key, name, family) {
- this.key = key;
- this.name = name;
- this.family = family;
- this.requires = {}
- }
- function getStyleDefinition(stylename, stylefamily, knownStyles) {
- var styleKey = stylename + '"' + stylefamily, styleDefinition = knownStyles[styleKey];
- if(!styleDefinition) {
- styleDefinition = knownStyles[styleKey] = new StyleDefinition(styleKey, stylename, stylefamily)
- }
- return styleDefinition
- }
- function determineDependentStyles(styleUsingElementsRoot, styleScope, knownStyles) {
- var elname = elements[styleUsingElementsRoot.localName], elns = elname && elname[styleUsingElementsRoot.namespaceURI], length = elns ? elns.length : 0, newScopeName = styleUsingElementsRoot.getAttributeNS(stylens, "name"), newScopeFamily = styleUsingElementsRoot.getAttributeNS(stylens, "family"), referencedStyleName, referencedStyleFamily, referencedStyleDef, i, e;
- if(newScopeName && newScopeFamily) {
- styleScope = getStyleDefinition(newScopeName, newScopeFamily, knownStyles)
- }
- if(styleScope) {
- for(i = 0;i < length;i += 1) {
- referencedStyleName = styleUsingElementsRoot.getAttributeNS(elns[i].ns, elns[i].localname);
- if(referencedStyleName) {
- referencedStyleFamily = elns[i].keyname;
- referencedStyleDef = getStyleDefinition(referencedStyleName, referencedStyleFamily, knownStyles);
- styleScope.requires[referencedStyleDef.key] = referencedStyleDef
- }
- }
- }
- i = styleUsingElementsRoot.firstChild;
- while(i) {
- if(i.nodeType === Node.ELEMENT_NODE) {
- e = (i);
- determineDependentStyles(e, styleScope, knownStyles)
- }
- i = i.nextSibling
- }
- return knownStyles
- }
- function inverse(elementstyles) {
- var keyname, i, l, list, item, e = {}, map, array;
- for(keyname in elementstyles) {
- if(elementstyles.hasOwnProperty(keyname)) {
- list = elementstyles[keyname];
- l = list.length;
- for(i = 0;i < l;i += 1) {
- item = list[i];
- map = e[item.en] = e[item.en] || {};
- array = map[item.ens] = map[item.ens] || [];
- array.push({ns:item.ans, localname:item.a, keyname:keyname})
- }
- }
- }
- return e
- }
- function mergeRequiredStyles(styleDependency, usedStyles) {
- var family = usedStyles[styleDependency.family];
- if(!family) {
- family = usedStyles[styleDependency.family] = {}
- }
- family[styleDependency.name] = 1;
- Object.keys((styleDependency.requires)).forEach(function(requiredStyleKey) {
- mergeRequiredStyles((styleDependency.requires[requiredStyleKey]), usedStyles)
- })
- }
- function mergeUsedAutomaticStyles(automaticStylesRoot, usedStyles) {
- var automaticStyles = determineDependentStyles(automaticStylesRoot, null, {});
- Object.keys(automaticStyles).forEach(function(styleKey) {
- var automaticStyleDefinition = automaticStyles[styleKey], usedFamily = usedStyles[automaticStyleDefinition.family];
- if(usedFamily && usedFamily.hasOwnProperty(automaticStyleDefinition.name)) {
- mergeRequiredStyles(automaticStyleDefinition, usedStyles)
- }
- })
- }
- function collectUsedFontFaces(usedFontFaceDeclMap, styleElementsRoot) {
- var localNames = ["font-name", "font-name-asian", "font-name-complex"], currentNode;
- function collectByAttribute(localName) {
- var fontFaceName = currentNode.getAttributeNS(stylens, localName);
- if(fontFaceName) {
- usedFontFaceDeclMap[fontFaceName] = true
- }
- }
- if(styleElementsRoot) {
- currentNode = styleElementsRoot.firstChild;
- while(currentNode) {
- if(currentNode.nodeType === Node.ELEMENT_NODE) {
- localNames.forEach(collectByAttribute);
- collectUsedFontFaces(usedFontFaceDeclMap, (currentNode))
- }
- currentNode = currentNode.nextSibling
- }
- }
- }
- this.collectUsedFontFaces = collectUsedFontFaces;
- function changeFontFaceNames(styleElementsRoot, fontFaceNameChangeMap) {
- var localNames = ["font-name", "font-name-asian", "font-name-complex"], currentNode;
- function changeFontFaceNameByAttribute(localName) {
- var fontFaceName = currentNode.getAttributeNS(stylens, localName);
- if(fontFaceName && fontFaceNameChangeMap.hasOwnProperty(fontFaceName)) {
- currentNode.setAttributeNS(stylens, "style:" + localName, fontFaceNameChangeMap[fontFaceName])
- }
- }
- if(styleElementsRoot) {
- currentNode = styleElementsRoot.firstChild;
- while(currentNode) {
- if(currentNode.nodeType === Node.ELEMENT_NODE) {
- localNames.forEach(changeFontFaceNameByAttribute);
- changeFontFaceNames((currentNode), fontFaceNameChangeMap)
- }
- currentNode = currentNode.nextSibling
- }
++};
++/*
++
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++runtime.loadClass("odf.Namespaces");
++runtime.loadClass("xmldom.LSSerializer");
++runtime.loadClass("odf.OdfNodeFilter");
++runtime.loadClass("odf.TextSerializer");
++gui.Clipboard = function Clipboard() {
++ var xmlSerializer, textSerializer, filter;
++ this.setDataFromRange = function(e, range) {
++ var result = true, setDataResult, clipboard = e.clipboardData, window = runtime.getWindow(), document = range.startContainer.ownerDocument, fragmentContainer;
++ if(!clipboard && window) {
++ clipboard = window.clipboardData
+ }
- }
- this.changeFontFaceNames = changeFontFaceNames;
- this.UsedStyleList = function(styleUsingElementsRoot, automaticStylesRoot) {
- var usedStyles = {};
- this.uses = function(element) {
- var localName = element.localName, name = element.getAttributeNS(drawns, "name") || element.getAttributeNS(stylens, "name"), keyName, map;
- if(localName === "style") {
- keyName = element.getAttributeNS(stylens, "family")
- }else {
- if(element.namespaceURI === numberns) {
- keyName = "data"
- }else {
- keyName = localName
- }
- }
- map = usedStyles[keyName];
- return map ? map[name] > 0 : false
- };
- determineUsedStyles(styleUsingElementsRoot, usedStyles);
- if(automaticStylesRoot) {
- mergeUsedAutomaticStyles(automaticStylesRoot, usedStyles)
++ if(clipboard) {
++ fragmentContainer = document.createElement("span");
++ fragmentContainer.appendChild(range.cloneContents());
++ setDataResult = clipboard.setData("text/plain", textSerializer.writeToString(fragmentContainer));
++ result = result && setDataResult;
++ setDataResult = clipboard.setData("text/html", xmlSerializer.writeToString(fragmentContainer, odf.Namespaces.namespaceMap));
++ result = result && setDataResult;
++ e.preventDefault()
++ }else {
++ result = false
+ }
++ return result
+ };
- this.hasDerivedStyles = hasDerivedStyles;
- this.prefixStyleNames = prefixStyleNames;
- this.removePrefixFromStyleNames = removePrefixFromStyleNames;
- this.determineStylesForNode = determineStylesForNode;
- elements = inverse(elementstyles)
++ function init() {
++ xmlSerializer = new xmldom.LSSerializer;
++ textSerializer = new odf.TextSerializer;
++ filter = new odf.OdfNodeFilter;
++ xmlSerializer.filter = filter;
++ textSerializer.filter = filter
++ }
++ init()
+};
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.DomUtils");
++runtime.loadClass("core.Base64");
++runtime.loadClass("core.Zip");
++runtime.loadClass("xmldom.LSSerializer");
++runtime.loadClass("odf.StyleInfo");
+runtime.loadClass("odf.Namespaces");
- odf.OdfUtils = function OdfUtils() {
- var textns = odf.Namespaces.textns, drawns = odf.Namespaces.drawns, whitespaceOnly = /^\s*$/, domUtils = new core.DomUtils;
- function isImage(e) {
- var name = e && e.localName;
- return name === "image" && e.namespaceURI === drawns
- }
- this.isImage = isImage;
- function isCharacterFrame(e) {
- var name = e && e.localName;
- return name === "frame" && (e.namespaceURI === drawns && e.getAttributeNS(textns, "anchor-type") === "as-char")
- }
- this.isCharacterFrame = isCharacterFrame;
- this.isTextSpan = function(e) {
- var name = e && e.localName;
- return name === "span" && e.namespaceURI === textns
- };
- function isParagraph(e) {
- var name = e && e.localName;
- return(name === "p" || name === "h") && e.namespaceURI === textns
- }
- this.isParagraph = isParagraph;
- function getParagraphElement(node) {
- while(node && !isParagraph(node)) {
- node = node.parentNode
++runtime.loadClass("odf.OdfNodeFilter");
++runtime.loadClass("odf.MetadataManager");
++(function() {
++ var styleInfo = new odf.StyleInfo, metadataManager, officens = "urn:oasis:names:tc:opendocument:xmlns:office:1.0", manifestns = "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0", webodfns = "urn:webodf:names:scope", stylens = odf.Namespaces.stylens, nodeorder = ["meta", "settings", "scripts", "font-face-decls", "styles", "automatic-styles", "master-styles", "body"], automaticStylePrefix = (new Date).getTime() + "_webodf_", base64 = new core.Base64, documentStylesScope = "document-s [...]
++ "document-content";
++ function getDirectChild(node, ns, name) {
++ node = node ? node.firstChild : null;
++ while(node) {
++ if(node.localName === name && node.namespaceURI === ns) {
++ return(node)
++ }
++ node = node.nextSibling
+ }
- return node
++ return null
+ }
- this.getParagraphElement = getParagraphElement;
- this.isWithinTrackedChanges = function(node, container) {
- while(node && node !== container) {
- if(node.namespaceURI === textns && node.localName === "tracked-changes") {
- return true
++ function getNodePosition(child) {
++ var i, l = nodeorder.length;
++ for(i = 0;i < l;i += 1) {
++ if(child.namespaceURI === officens && child.localName === nodeorder[i]) {
++ return i
+ }
- node = node.parentNode
+ }
- return false
- };
- this.isListItem = function(e) {
- var name = e && e.localName;
- return name === "list-item" && e.namespaceURI === textns
- };
- this.isLineBreak = function(e) {
- var name = e && e.localName;
- return name === "line-break" && e.namespaceURI === textns
- };
- function isODFWhitespace(text) {
- return/^[ \t\r\n]+$/.test(text)
++ return-1
+ }
- this.isODFWhitespace = isODFWhitespace;
- function isGroupingElement(e) {
- var localName = e && e.localName;
- if(/^(span|p|h|a|meta)$/.test(localName) && e.namespaceURI === textns || localName === "span" && e.className === "annotationHighlight") {
- return true
++ function OdfStylesFilter(styleUsingElementsRoot, automaticStyles) {
++ var usedStyleList = new styleInfo.UsedStyleList(styleUsingElementsRoot, automaticStyles), odfNodeFilter = new odf.OdfNodeFilter;
++ this.acceptNode = function(node) {
++ var result = odfNodeFilter.acceptNode(node);
++ if(result === NodeFilter.FILTER_ACCEPT && (node.parentNode === automaticStyles && node.nodeType === Node.ELEMENT_NODE)) {
++ if(usedStyleList.uses((node))) {
++ result = NodeFilter.FILTER_ACCEPT
++ }else {
++ result = NodeFilter.FILTER_REJECT
++ }
++ }
++ return result
+ }
- return false
+ }
- this.isGroupingElement = isGroupingElement;
- function isCharacterElement(e) {
- var n = e && e.localName, ns, r = false;
- if(n) {
- ns = e.namespaceURI;
- if(ns === textns) {
- r = n === "s" || (n === "tab" || n === "line-break")
- }else {
- r = isCharacterFrame(e)
++ function OdfContentFilter(styleUsingElementsRoot, automaticStyles) {
++ var odfStylesFilter = new OdfStylesFilter(styleUsingElementsRoot, automaticStyles);
++ this.acceptNode = function(node) {
++ var result = odfStylesFilter.acceptNode(node);
++ if(result === NodeFilter.FILTER_ACCEPT && (node.parentNode && (node.parentNode.namespaceURI === odf.Namespaces.textns && (node.parentNode.localName === "s" || node.parentNode.localName === "tab")))) {
++ result = NodeFilter.FILTER_REJECT
+ }
++ return result
+ }
- return r
+ }
- this.isCharacterElement = isCharacterElement;
- function isSpaceElement(e) {
- var n = e && e.localName, ns, r = false;
- if(n) {
- ns = e.namespaceURI;
- if(ns === textns) {
- r = n === "s"
- }
++ function setChild(node, child) {
++ if(!child) {
++ return
+ }
- return r
- }
- this.isSpaceElement = isSpaceElement;
- function firstChild(node) {
- while(node.firstChild !== null && isGroupingElement(node)) {
- node = node.firstChild
++ var childpos = getNodePosition(child), pos, c = node.firstChild;
++ if(childpos === -1) {
++ return
+ }
- return node
- }
- this.firstChild = firstChild;
- function lastChild(node) {
- while(node.lastChild !== null && isGroupingElement(node)) {
- node = node.lastChild
++ while(c) {
++ pos = getNodePosition(c);
++ if(pos !== -1 && pos > childpos) {
++ break
++ }
++ c = c.nextSibling
+ }
- return node
++ node.insertBefore(child, c)
+ }
- this.lastChild = lastChild;
- function previousNode(node) {
- while(!isParagraph(node) && node.previousSibling === null) {
- node = (node.parentNode)
++ odf.ODFElement = function ODFElement() {
++ };
++ odf.ODFDocumentElement = function ODFDocumentElement() {
++ };
++ odf.ODFDocumentElement.prototype = new odf.ODFElement;
++ odf.ODFDocumentElement.prototype.constructor = odf.ODFDocumentElement;
++ odf.ODFDocumentElement.prototype.automaticStyles;
++ odf.ODFDocumentElement.prototype.body;
++ odf.ODFDocumentElement.prototype.fontFaceDecls = null;
++ odf.ODFDocumentElement.prototype.manifest = null;
++ odf.ODFDocumentElement.prototype.masterStyles;
++ odf.ODFDocumentElement.prototype.meta;
++ odf.ODFDocumentElement.prototype.settings = null;
++ odf.ODFDocumentElement.prototype.styles;
++ odf.ODFDocumentElement.namespaceURI = officens;
++ odf.ODFDocumentElement.localName = "document";
++ odf.OdfPart = function OdfPart(name, mimetype, container, zip) {
++ var self = this;
++ this.size = 0;
++ this.type = null;
++ this.name = name;
++ this.container = container;
++ this.url = null;
++ this.mimetype = mimetype;
++ this.document = null;
++ this.onstatereadychange = null;
++ this.onchange;
++ this.EMPTY = 0;
++ this.LOADING = 1;
++ this.DONE = 2;
++ this.state = this.EMPTY;
++ this.data = "";
++ this.load = function() {
++ if(zip === null) {
++ return
++ }
++ this.mimetype = mimetype;
++ zip.loadAsDataURL(name, mimetype, function(err, url) {
++ if(err) {
++ runtime.log(err)
++ }
++ self.url = url;
++ if(self.onchange) {
++ self.onchange(self)
++ }
++ if(self.onstatereadychange) {
++ self.onstatereadychange(self)
++ }
++ })
+ }
- return isParagraph(node) ? null : lastChild((node.previousSibling))
- }
- this.previousNode = previousNode;
- function nextNode(node) {
- while(!isParagraph(node) && node.nextSibling === null) {
- node = (node.parentNode)
++ };
++ odf.OdfPart.prototype.load = function() {
++ };
++ odf.OdfPart.prototype.getUrl = function() {
++ if(this.data) {
++ return"data:;base64," + base64.toBase64(this.data)
+ }
- return isParagraph(node) ? null : firstChild((node.nextSibling))
- }
- this.nextNode = nextNode;
- function scanLeftForNonSpace(node) {
- var r = false;
- while(node) {
- if(node.nodeType === Node.TEXT_NODE) {
- if(node.length === 0) {
- node = previousNode(node)
- }else {
- return!isODFWhitespace(node.data.substr(node.length - 1, 1))
- }
- }else {
- if(isCharacterElement(node)) {
- r = isSpaceElement(node) === false;
- node = null
++ return null
++ };
++ odf.OdfContainer = function OdfContainer(url, onstatereadychange) {
++ var self = this, zip, partMimetypes = {}, contentElement;
++ this.onstatereadychange = onstatereadychange;
++ this.onchange = null;
++ this.state = null;
++ this.rootElement;
++ function removeProcessingInstructions(element) {
++ var n = element.firstChild, next, e;
++ while(n) {
++ next = n.nextSibling;
++ if(n.nodeType === Node.ELEMENT_NODE) {
++ e = (n);
++ removeProcessingInstructions(e)
+ }else {
- node = previousNode(node)
++ if(n.nodeType === Node.PROCESSING_INSTRUCTION_NODE) {
++ element.removeChild(n)
++ }
+ }
++ n = next
+ }
+ }
- return r
- }
- this.scanLeftForNonSpace = scanLeftForNonSpace;
- function lookLeftForCharacter(node) {
- var text, r = 0;
- if(node.nodeType === Node.TEXT_NODE && node.length > 0) {
- text = node.data;
- if(!isODFWhitespace(text.substr(text.length - 1, 1))) {
- r = 1
- }else {
- if(text.length === 1) {
- r = scanLeftForNonSpace(previousNode(node)) ? 2 : 0
- }else {
- r = isODFWhitespace(text.substr(text.length - 2, 1)) ? 0 : 2
++ function setAutomaticStylesScope(stylesRootElement, scope) {
++ var n = stylesRootElement && stylesRootElement.firstChild;
++ while(n) {
++ if(n.nodeType === Node.ELEMENT_NODE) {
++ (n).setAttributeNS(webodfns, "scope", scope)
+ }
- }
- }else {
- if(isCharacterElement(node)) {
- r = 1
++ n = n.nextSibling
+ }
+ }
- return r
- }
- this.lookLeftForCharacter = lookLeftForCharacter;
- function lookRightForCharacter(node) {
- var r = false;
- if(node && (node.nodeType === Node.TEXT_NODE && node.length > 0)) {
- r = !isODFWhitespace(node.data.substr(0, 1))
- }else {
- if(isCharacterElement(node)) {
- r = true
++ function unusedKey(key, map1, map2) {
++ var i = 0, postFixedKey;
++ key = key.replace(/\d+$/, "");
++ postFixedKey = key;
++ while(map1.hasOwnProperty(postFixedKey) || map2.hasOwnProperty(postFixedKey)) {
++ i += 1;
++ postFixedKey = key + i
+ }
++ return postFixedKey
+ }
- return r
- }
- this.lookRightForCharacter = lookRightForCharacter;
- function scanLeftForAnyCharacter(node) {
- var r = false;
- node = node && lastChild(node);
- while(node) {
- if(node.nodeType === Node.TEXT_NODE && (node.length > 0 && !isODFWhitespace(node.data))) {
- r = true;
- break
- }
- if(isCharacterElement(node)) {
- r = true;
- break
++ function mapByFontFaceName(fontFaceDecls) {
++ var fn, result = {}, fontname;
++ fn = fontFaceDecls.firstChild;
++ while(fn) {
++ if(fn.nodeType === Node.ELEMENT_NODE && (fn.namespaceURI === stylens && fn.localName === "font-face")) {
++ fontname = (fn).getAttributeNS(stylens, "name");
++ result[fontname] = fn
++ }
++ fn = fn.nextSibling
+ }
- node = previousNode(node)
++ return result
+ }
- return r
- }
- this.scanLeftForAnyCharacter = scanLeftForAnyCharacter;
- function scanRightForAnyCharacter(node) {
- var r = false;
- node = node && firstChild(node);
- while(node) {
- if(node.nodeType === Node.TEXT_NODE && (node.length > 0 && !isODFWhitespace(node.data))) {
- r = true;
- break
++ function mergeFontFaceDecls(targetFontFaceDeclsRootElement, sourceFontFaceDeclsRootElement) {
++ var e, s, fontFaceName, newFontFaceName, targetFontFaceDeclsMap, sourceFontFaceDeclsMap, fontFaceNameChangeMap = {};
++ targetFontFaceDeclsMap = mapByFontFaceName(targetFontFaceDeclsRootElement);
++ sourceFontFaceDeclsMap = mapByFontFaceName(sourceFontFaceDeclsRootElement);
++ e = sourceFontFaceDeclsRootElement.firstElementChild;
++ while(e) {
++ s = e.nextElementSibling;
++ if(e.namespaceURI === stylens && e.localName === "font-face") {
++ fontFaceName = e.getAttributeNS(stylens, "name");
++ if(targetFontFaceDeclsMap.hasOwnProperty(fontFaceName)) {
++ if(!e.isEqualNode(targetFontFaceDeclsMap[fontFaceName])) {
++ newFontFaceName = unusedKey(fontFaceName, targetFontFaceDeclsMap, sourceFontFaceDeclsMap);
++ e.setAttributeNS(stylens, "style:name", newFontFaceName);
++ targetFontFaceDeclsRootElement.appendChild(e);
++ targetFontFaceDeclsMap[newFontFaceName] = e;
++ delete sourceFontFaceDeclsMap[fontFaceName];
++ fontFaceNameChangeMap[fontFaceName] = newFontFaceName
++ }
++ }else {
++ targetFontFaceDeclsRootElement.appendChild(e);
++ targetFontFaceDeclsMap[fontFaceName] = e;
++ delete sourceFontFaceDeclsMap[fontFaceName]
++ }
++ }
++ e = s
+ }
- if(isCharacterElement(node)) {
- r = true;
- break
++ return fontFaceNameChangeMap
++ }
++ function cloneStylesInScope(stylesRootElement, scope) {
++ var copy = null, e, s, scopeAttrValue;
++ if(stylesRootElement) {
++ copy = stylesRootElement.cloneNode(true);
++ e = copy.firstElementChild;
++ while(e) {
++ s = e.nextElementSibling;
++ scopeAttrValue = e.getAttributeNS(webodfns, "scope");
++ if(scopeAttrValue && scopeAttrValue !== scope) {
++ copy.removeChild(e)
++ }
++ e = s
++ }
+ }
- node = nextNode(node)
++ return copy
+ }
- return r
- }
- this.scanRightForAnyCharacter = scanRightForAnyCharacter;
- function isTrailingWhitespace(textnode, offset) {
- if(!isODFWhitespace(textnode.data.substr(offset))) {
- return false
++ function cloneFontFaceDeclsUsedInStyles(fontFaceDeclsRootElement, stylesRootElementList) {
++ var e, nextSibling, fontFaceName, copy = null, usedFontFaceDeclMap = {};
++ if(fontFaceDeclsRootElement) {
++ stylesRootElementList.forEach(function(stylesRootElement) {
++ styleInfo.collectUsedFontFaces(usedFontFaceDeclMap, stylesRootElement)
++ });
++ copy = fontFaceDeclsRootElement.cloneNode(true);
++ e = copy.firstElementChild;
++ while(e) {
++ nextSibling = e.nextElementSibling;
++ fontFaceName = e.getAttributeNS(stylens, "name");
++ if(!usedFontFaceDeclMap[fontFaceName]) {
++ copy.removeChild(e)
++ }
++ e = nextSibling
++ }
++ }
++ return copy
+ }
- return!scanRightForAnyCharacter(nextNode(textnode))
- }
- this.isTrailingWhitespace = isTrailingWhitespace;
- function isSignificantWhitespace(textNode, offset) {
- var text = textNode.data, result;
- if(!isODFWhitespace(text[offset])) {
- return false
++ function initializeMetadataManager(metaRootElement) {
++ metadataManager = new odf.MetadataManager(metaRootElement)
+ }
- if(isCharacterElement(textNode.parentNode)) {
- return false
++ function importRootNode(xmldoc) {
++ var doc = self.rootElement.ownerDocument, node;
++ if(xmldoc) {
++ removeProcessingInstructions(xmldoc.documentElement);
++ try {
++ node = doc.importNode(xmldoc.documentElement, true)
++ }catch(ignore) {
++ }
++ }
++ return node
+ }
- if(offset > 0) {
- if(!isODFWhitespace(text[offset - 1])) {
- result = true
++ function setState(state) {
++ self.state = state;
++ if(self.onchange) {
++ self.onchange(self)
+ }
- }else {
- if(scanLeftForNonSpace(previousNode(textNode))) {
- result = true
++ if(self.onstatereadychange) {
++ self.onstatereadychange(self)
+ }
+ }
- if(result === true) {
- return isTrailingWhitespace(textNode, offset) ? false : true
++ function setRootElement(root) {
++ contentElement = null;
++ self.rootElement = (root);
++ root.fontFaceDecls = getDirectChild(root, officens, "font-face-decls");
++ root.styles = getDirectChild(root, officens, "styles");
++ root.automaticStyles = getDirectChild(root, officens, "automatic-styles");
++ root.masterStyles = getDirectChild(root, officens, "master-styles");
++ root.body = getDirectChild(root, officens, "body");
++ root.meta = getDirectChild(root, officens, "meta")
+ }
- return false
- }
- this.isSignificantWhitespace = isSignificantWhitespace;
- this.isDowngradableSpaceElement = function(node) {
- if(node.namespaceURI === textns && node.localName === "s") {
- return scanLeftForNonSpace(previousNode(node)) && scanRightForAnyCharacter(nextNode(node))
- }
- return false
- };
- function getFirstNonWhitespaceChild(node) {
- var child = node && node.firstChild;
- while(child && (child.nodeType === Node.TEXT_NODE && whitespaceOnly.test(child.nodeValue))) {
- child = child.nextSibling
- }
- return child
- }
- this.getFirstNonWhitespaceChild = getFirstNonWhitespaceChild;
- function parseLength(length) {
- var re = /(-?[0-9]*[0-9][0-9]*(\.[0-9]*)?|0+\.[0-9]*[1-9][0-9]*|\.[0-9]*[1-9][0-9]*)((cm)|(mm)|(in)|(pt)|(pc)|(px)|(%))/, m = re.exec(length);
- if(!m) {
- return null
- }
- return{value:parseFloat(m[1]), unit:m[3]}
- }
- this.parseLength = parseLength;
- function parsePositiveLength(length) {
- var result = parseLength(length);
- if(result && (result.value <= 0 || result.unit === "%")) {
- return null
- }
- return result
- }
- function parseNonNegativeLength(length) {
- var result = parseLength(length);
- if(result && (result.value < 0 || result.unit === "%")) {
- return null
- }
- return result
- }
- this.parseNonNegativeLength = parseNonNegativeLength;
- function parsePercentage(length) {
- var result = parseLength(length);
- if(result && result.unit !== "%") {
- return null
- }
- return result
- }
- function parseFoFontSize(fontSize) {
- return parsePositiveLength(fontSize) || parsePercentage(fontSize)
- }
- this.parseFoFontSize = parseFoFontSize;
- function parseFoLineHeight(lineHeight) {
- return parseNonNegativeLength(lineHeight) || parsePercentage(lineHeight)
- }
- this.parseFoLineHeight = parseFoLineHeight;
- function getImpactedParagraphs(range) {
- var outerContainer = (range.commonAncestorContainer), impactedParagraphs = [];
- if(outerContainer.nodeType === Node.ELEMENT_NODE) {
- impactedParagraphs = domUtils.getElementsByTagNameNS(outerContainer, textns, "p").concat(domUtils.getElementsByTagNameNS(outerContainer, textns, "h"))
- }
- while(outerContainer && !isParagraph(outerContainer)) {
- outerContainer = outerContainer.parentNode
- }
- if(outerContainer) {
- impactedParagraphs.push(outerContainer)
++ function handleFlatXml(xmldoc) {
++ var root = importRootNode(xmldoc);
++ if(!root || (root.localName !== "document" || root.namespaceURI !== officens)) {
++ setState(OdfContainer.INVALID);
++ return
++ }
++ setRootElement((root));
++ setState(OdfContainer.DONE)
+ }
- return impactedParagraphs.filter(function(n) {
- return domUtils.rangeIntersectsNode(range, n)
- })
- }
- this.getImpactedParagraphs = getImpactedParagraphs;
- function isAcceptedNode(node) {
- switch(node.namespaceURI) {
- case odf.Namespaces.drawns:
- ;
- case odf.Namespaces.svgns:
- ;
- case odf.Namespaces.dr3dns:
- return false;
- case odf.Namespaces.textns:
- switch(node.localName) {
- case "note-body":
- ;
- case "ruby-text":
- return false
- }
- break;
- case odf.Namespaces.officens:
- switch(node.localName) {
- case "annotation":
- ;
- case "binary-data":
- ;
- case "event-listeners":
- return false
- }
- break;
- default:
- switch(node.localName) {
- case "editinfo":
- return false
- }
- break
++ function handleStylesXml(xmldoc) {
++ var node = importRootNode(xmldoc), root = self.rootElement, n;
++ if(!node || (node.localName !== "document-styles" || node.namespaceURI !== officens)) {
++ setState(OdfContainer.INVALID);
++ return
++ }
++ root.fontFaceDecls = getDirectChild(node, officens, "font-face-decls");
++ setChild(root, root.fontFaceDecls);
++ n = getDirectChild(node, officens, "styles");
++ root.styles = n || xmldoc.createElementNS(officens, "styles");
++ setChild(root, root.styles);
++ n = getDirectChild(node, officens, "automatic-styles");
++ root.automaticStyles = n || xmldoc.createElementNS(officens, "automatic-styles");
++ setAutomaticStylesScope(root.automaticStyles, documentStylesScope);
++ setChild(root, root.automaticStyles);
++ node = getDirectChild(node, officens, "master-styles");
++ root.masterStyles = node || xmldoc.createElementNS(officens, "master-styles");
++ setChild(root, root.masterStyles);
++ styleInfo.prefixStyleNames(root.automaticStyles, automaticStylePrefix, root.masterStyles)
+ }
- return true
- }
- function isSignificantTextContent(textNode) {
- return Boolean(getParagraphElement(textNode) && (!isODFWhitespace(textNode.textContent) || isSignificantWhitespace(textNode, 0)))
- }
- function includeNode(range, nodeRange, includePartial) {
- return includePartial && domUtils.rangesIntersect(range, nodeRange) || domUtils.containsRange(range, nodeRange)
- }
- function getTextNodes(range, includePartial) {
- var document = range.startContainer.ownerDocument, nodeRange = document.createRange(), textNodes;
- function nodeFilter(node) {
- nodeRange.selectNodeContents(node);
- if(node.nodeType === Node.TEXT_NODE) {
- if(includeNode(range, nodeRange, includePartial)) {
- return isSignificantTextContent(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT
- }
++ function handleContentXml(xmldoc) {
++ var node = importRootNode(xmldoc), root, automaticStyles, fontFaceDecls, fontFaceNameChangeMap, c;
++ if(!node || (node.localName !== "document-content" || node.namespaceURI !== officens)) {
++ setState(OdfContainer.INVALID);
++ return
++ }
++ root = self.rootElement;
++ fontFaceDecls = getDirectChild(node, officens, "font-face-decls");
++ if(root.fontFaceDecls && fontFaceDecls) {
++ fontFaceNameChangeMap = mergeFontFaceDecls(root.fontFaceDecls, fontFaceDecls)
+ }else {
- if(domUtils.rangesIntersect(range, nodeRange)) {
- if(isAcceptedNode(node)) {
- return NodeFilter.FILTER_SKIP
- }
++ if(fontFaceDecls) {
++ root.fontFaceDecls = fontFaceDecls;
++ setChild(root, fontFaceDecls)
+ }
+ }
- return NodeFilter.FILTER_REJECT
- }
- textNodes = domUtils.getNodesInRange(range, nodeFilter);
- nodeRange.detach();
- return textNodes
- }
- this.getTextNodes = getTextNodes;
- this.getTextElements = function(range, includePartial, includeInsignificantWhitespace) {
- var document = range.startContainer.ownerDocument, nodeRange = document.createRange(), elements;
- function nodeFilter(node) {
- nodeRange.selectNodeContents(node);
- if(isCharacterElement(node.parentNode)) {
- return NodeFilter.FILTER_REJECT
++ automaticStyles = getDirectChild(node, officens, "automatic-styles");
++ setAutomaticStylesScope(automaticStyles, documentContentScope);
++ if(fontFaceNameChangeMap) {
++ styleInfo.changeFontFaceNames(automaticStyles, fontFaceNameChangeMap)
+ }
- if(node.nodeType === Node.TEXT_NODE) {
- if(includeNode(range, nodeRange, includePartial)) {
- if(includeInsignificantWhitespace || isSignificantTextContent(node)) {
- return NodeFilter.FILTER_ACCEPT
- }
++ if(root.automaticStyles && automaticStyles) {
++ c = automaticStyles.firstChild;
++ while(c) {
++ root.automaticStyles.appendChild(c);
++ c = automaticStyles.firstChild
+ }
+ }else {
- if(isCharacterElement(node)) {
- if(includeNode(range, nodeRange, includePartial)) {
- return NodeFilter.FILTER_ACCEPT
- }
- }else {
- if(isAcceptedNode(node) || isGroupingElement(node)) {
- return NodeFilter.FILTER_SKIP
- }
++ if(automaticStyles) {
++ root.automaticStyles = automaticStyles;
++ setChild(root, automaticStyles)
+ }
+ }
- return NodeFilter.FILTER_REJECT
++ node = getDirectChild(node, officens, "body");
++ if(node === null) {
++ throw"<office:body/> tag is mising.";
++ }
++ root.body = node;
++ setChild(root, root.body)
+ }
- elements = domUtils.getNodesInRange(range, nodeFilter);
- nodeRange.detach();
- return elements
- };
- this.getParagraphElements = function(range) {
- var document = range.startContainer.ownerDocument, nodeRange = document.createRange(), elements;
- function nodeFilter(node) {
- nodeRange.selectNodeContents(node);
- if(isParagraph(node)) {
- if(domUtils.rangesIntersect(range, nodeRange)) {
- return NodeFilter.FILTER_ACCEPT
++ function handleMetaXml(xmldoc) {
++ var node = importRootNode(xmldoc), root;
++ if(!node || (node.localName !== "document-meta" || node.namespaceURI !== officens)) {
++ return
++ }
++ root = self.rootElement;
++ node = getDirectChild(node, officens, "meta");
++ root.meta = node || xmldoc.createElementNS(officens, "meta");
++ setChild(root, root.meta);
++ initializeMetadataManager(root.meta)
++ }
++ function handleSettingsXml(xmldoc) {
++ var node = importRootNode(xmldoc), root;
++ if(!node || (node.localName !== "document-settings" || node.namespaceURI !== officens)) {
++ return
++ }
++ root = self.rootElement;
++ root.settings = getDirectChild(node, officens, "settings");
++ setChild(root, root.settings)
++ }
++ function handleManifestXml(xmldoc) {
++ var node = importRootNode(xmldoc), root, e;
++ if(!node || (node.localName !== "manifest" || node.namespaceURI !== manifestns)) {
++ return
++ }
++ root = self.rootElement;
++ root.manifest = (node);
++ e = root.manifest.firstElementChild;
++ while(e) {
++ if(e.localName === "file-entry" && e.namespaceURI === manifestns) {
++ partMimetypes[e.getAttributeNS(manifestns, "full-path")] = e.getAttributeNS(manifestns, "media-type")
+ }
++ e = e.nextElementSibling
++ }
++ }
++ function loadNextComponent(remainingComponents) {
++ var component = remainingComponents.shift();
++ if(component) {
++ zip.loadAsDOM(component.path, function(err, xmldoc) {
++ component.handler(xmldoc);
++ if(err || self.state === OdfContainer.INVALID) {
++ return
++ }
++ loadNextComponent(remainingComponents)
++ })
+ }else {
- if(isAcceptedNode(node) || isGroupingElement(node)) {
- return NodeFilter.FILTER_SKIP
- }
++ setState(OdfContainer.DONE)
+ }
- return NodeFilter.FILTER_REJECT
+ }
- elements = domUtils.getNodesInRange(range, nodeFilter);
- nodeRange.detach();
- return elements
- };
- this.getImageElements = function(range) {
- var document = range.startContainer.ownerDocument, nodeRange = document.createRange(), elements;
- function nodeFilter(node) {
- nodeRange.selectNodeContents(node);
- if(isImage(node) && domUtils.containsRange(range, nodeRange)) {
- return NodeFilter.FILTER_ACCEPT
++ function loadComponents() {
++ var componentOrder = [{path:"styles.xml", handler:handleStylesXml}, {path:"content.xml", handler:handleContentXml}, {path:"meta.xml", handler:handleMetaXml}, {path:"settings.xml", handler:handleSettingsXml}, {path:"META-INF/manifest.xml", handler:handleManifestXml}];
++ loadNextComponent(componentOrder)
++ }
++ function createDocumentElement(name) {
++ var s = "";
++ function defineNamespace(prefix, ns) {
++ s += " xmlns:" + prefix + '="' + ns + '"'
+ }
- return NodeFilter.FILTER_SKIP
++ odf.Namespaces.forEachPrefix(defineNamespace);
++ return'<?xml version="1.0" encoding="UTF-8"?><office:' + name + " " + s + ' office:version="1.2">'
+ }
- elements = domUtils.getNodesInRange(range, nodeFilter);
- nodeRange.detach();
- return elements
- }
- };
++ function serializeMetaXml() {
++ var serializer = new xmldom.LSSerializer, s = createDocumentElement("document-meta");
++ serializer.filter = new odf.OdfNodeFilter;
++ s += serializer.writeToString(self.rootElement.meta, odf.Namespaces.namespaceMap);
++ s += "</office:document-meta>";
++ return s
++ }
++ function createManifestEntry(fullPath, mediaType) {
++ var element = document.createElementNS(manifestns, "manifest:file-entry");
++ element.setAttributeNS(manifestns, "manifest:full-path", fullPath);
++ element.setAttributeNS(manifestns, "manifest:media-type", mediaType);
++ return element
++ }
++ function serializeManifestXml() {
++ var header = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n', xml = '<manifest:manifest xmlns:manifest="' + manifestns + '" manifest:version="1.2"></manifest:manifest>', manifest = (runtime.parseXML(xml)), manifestRoot = getDirectChild(manifest, manifestns, "manifest"), serializer = new xmldom.LSSerializer, fullPath;
++ for(fullPath in partMimetypes) {
++ if(partMimetypes.hasOwnProperty(fullPath)) {
++ manifestRoot.appendChild(createManifestEntry(fullPath, partMimetypes[fullPath]))
++ }
++ }
++ serializer.filter = new odf.OdfNodeFilter;
++ return header + serializer.writeToString(manifest, odf.Namespaces.namespaceMap)
++ }
++ function serializeSettingsXml() {
++ var serializer = new xmldom.LSSerializer, s = createDocumentElement("document-settings");
++ serializer.filter = new odf.OdfNodeFilter;
++ s += serializer.writeToString(self.rootElement.settings, odf.Namespaces.namespaceMap);
++ s += "</office:document-settings>";
++ return s
++ }
++ function serializeStylesXml() {
++ var fontFaceDecls, automaticStyles, masterStyles, nsmap = odf.Namespaces.namespaceMap, serializer = new xmldom.LSSerializer, s = createDocumentElement("document-styles");
++ automaticStyles = cloneStylesInScope(self.rootElement.automaticStyles, documentStylesScope);
++ masterStyles = (self.rootElement.masterStyles.cloneNode(true));
++ fontFaceDecls = cloneFontFaceDeclsUsedInStyles(self.rootElement.fontFaceDecls, [masterStyles, self.rootElement.styles, automaticStyles]);
++ styleInfo.removePrefixFromStyleNames(automaticStyles, automaticStylePrefix, masterStyles);
++ serializer.filter = new OdfStylesFilter(masterStyles, automaticStyles);
++ s += serializer.writeToString(fontFaceDecls, nsmap);
++ s += serializer.writeToString(self.rootElement.styles, nsmap);
++ s += serializer.writeToString(automaticStyles, nsmap);
++ s += serializer.writeToString(masterStyles, nsmap);
++ s += "</office:document-styles>";
++ return s
++ }
++ function serializeContentXml() {
++ var fontFaceDecls, automaticStyles, nsmap = odf.Namespaces.namespaceMap, serializer = new xmldom.LSSerializer, s = createDocumentElement("document-content");
++ automaticStyles = cloneStylesInScope(self.rootElement.automaticStyles, documentContentScope);
++ fontFaceDecls = cloneFontFaceDeclsUsedInStyles(self.rootElement.fontFaceDecls, [automaticStyles]);
++ serializer.filter = new OdfContentFilter(self.rootElement.body, automaticStyles);
++ s += serializer.writeToString(fontFaceDecls, nsmap);
++ s += serializer.writeToString(automaticStyles, nsmap);
++ s += serializer.writeToString(self.rootElement.body, nsmap);
++ s += "</office:document-content>";
++ return s
++ }
++ function createElement(type) {
++ var original = document.createElementNS(type.namespaceURI, type.localName), method, iface = new type.Type;
++ for(method in iface) {
++ if(iface.hasOwnProperty(method)) {
++ original[method] = iface[method]
++ }
++ }
++ return original
++ }
++ function loadFromXML(url, callback) {
++ runtime.loadXML(url, function(err, dom) {
++ if(err) {
++ callback(err)
++ }else {
++ handleFlatXml(dom)
++ }
++ })
++ }
++ this.setRootElement = setRootElement;
++ this.getContentElement = function() {
++ var body;
++ if(!contentElement) {
++ body = self.rootElement.body;
++ contentElement = getDirectChild(body, officens, "text") || (getDirectChild(body, officens, "presentation") || getDirectChild(body, officens, "spreadsheet"))
++ }
++ if(!contentElement) {
++ throw"Could not find content element in <office:body/>.";
++ }
++ return contentElement
++ };
++ this.getDocumentType = function() {
++ var content = self.getContentElement();
++ return content && content.localName
++ };
++ this.getMetadataManager = function() {
++ return metadataManager
++ };
++ this.getPart = function(partname) {
++ return new odf.OdfPart(partname, partMimetypes[partname], self, zip)
++ };
++ this.getPartData = function(url, callback) {
++ zip.load(url, callback)
++ };
++ function updateMetadataForSaving() {
++ var generatorString, window = runtime.getWindow();
++ generatorString = "WebODF/" + (String(typeof webodf_version) !== "undefined" ? webodf_version : "FromSource");
++ if(window) {
++ generatorString = generatorString + " " + window.navigator.userAgent
++ }
++ metadataManager.setMetadata({"meta:generator":generatorString}, null)
++ }
++ function createEmptyTextDocument() {
++ var emptyzip = new core.Zip("", null), data = runtime.byteArrayFromString("application/vnd.oasis.opendocument.text", "utf8"), root = self.rootElement, text = document.createElementNS(officens, "text");
++ emptyzip.save("mimetype", data, false, new Date);
++ function addToplevelElement(memberName, realLocalName) {
++ var element;
++ if(!realLocalName) {
++ realLocalName = memberName
++ }
++ element = document.createElementNS(officens, realLocalName);
++ root[memberName] = element;
++ root.appendChild(element)
++ }
++ addToplevelElement("meta");
++ addToplevelElement("settings");
++ addToplevelElement("scripts");
++ addToplevelElement("fontFaceDecls", "font-face-decls");
++ addToplevelElement("styles");
++ addToplevelElement("automaticStyles", "automatic-styles");
++ addToplevelElement("masterStyles", "master-styles");
++ addToplevelElement("body");
++ root.body.appendChild(text);
++ initializeMetadataManager(root.meta);
++ setState(OdfContainer.DONE);
++ return emptyzip
++ }
++ function fillZip() {
++ var data, date = new Date;
++ updateMetadataForSaving();
++ data = runtime.byteArrayFromString(serializeSettingsXml(), "utf8");
++ zip.save("settings.xml", data, true, date);
++ data = runtime.byteArrayFromString(serializeMetaXml(), "utf8");
++ zip.save("meta.xml", data, true, date);
++ data = runtime.byteArrayFromString(serializeStylesXml(), "utf8");
++ zip.save("styles.xml", data, true, date);
++ data = runtime.byteArrayFromString(serializeContentXml(), "utf8");
++ zip.save("content.xml", data, true, date);
++ data = runtime.byteArrayFromString(serializeManifestXml(), "utf8");
++ zip.save("META-INF/manifest.xml", data, true, date)
++ }
++ function createByteArray(successCallback, errorCallback) {
++ fillZip();
++ zip.createByteArray(successCallback, errorCallback)
++ }
++ this.createByteArray = createByteArray;
++ function saveAs(newurl, callback) {
++ fillZip();
++ zip.writeAs(newurl, function(err) {
++ callback(err)
++ })
++ }
++ this.saveAs = saveAs;
++ this.save = function(callback) {
++ saveAs(url, callback)
++ };
++ this.getUrl = function() {
++ return url
++ };
++ this.setBlob = function(filename, mimetype, content) {
++ var data = base64.convertBase64ToByteArray(content), date = new Date;
++ zip.save(filename, data, false, date);
++ if(partMimetypes.hasOwnProperty(filename)) {
++ runtime.log(filename + " has been overwritten.")
++ }
++ partMimetypes[filename] = mimetype
++ };
++ this.removeBlob = function(filename) {
++ var foundAndRemoved = zip.remove(filename);
++ runtime.assert(foundAndRemoved, "file is not found: " + filename);
++ delete partMimetypes[filename]
++ };
++ this.state = OdfContainer.LOADING;
++ this.rootElement = (createElement({Type:odf.ODFDocumentElement, namespaceURI:odf.ODFDocumentElement.namespaceURI, localName:odf.ODFDocumentElement.localName}));
++ if(url) {
++ zip = new core.Zip(url, function(err, zipobject) {
++ zip = zipobject;
++ if(err) {
++ loadFromXML(url, function(xmlerr) {
++ if(err) {
++ zip.error = err + "\n" + xmlerr;
++ setState(OdfContainer.INVALID)
++ }
++ })
++ }else {
++ loadComponents()
++ }
++ })
++ }else {
++ zip = createEmptyTextDocument()
++ }
++ };
++ odf.OdfContainer.EMPTY = 0;
++ odf.OdfContainer.LOADING = 1;
++ odf.OdfContainer.DONE = 2;
++ odf.OdfContainer.INVALID = 3;
++ odf.OdfContainer.SAVING = 4;
++ odf.OdfContainer.MODIFIED = 5;
++ odf.OdfContainer.getContainer = function(url) {
++ return new odf.OdfContainer(url, null)
++ };
++ return odf.OdfContainer
++})();
+/*
+
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("odf.OdfUtils");
- odf.TextSerializer = function TextSerializer() {
- var self = this, odfUtils = new odf.OdfUtils;
- function serializeNode(node) {
- var s = "", accept = self.filter ? self.filter.acceptNode(node) : NodeFilter.FILTER_ACCEPT, nodeType = node.nodeType, child;
- if(accept === NodeFilter.FILTER_ACCEPT || accept === NodeFilter.FILTER_SKIP) {
- child = node.firstChild;
- while(child) {
- s += serializeNode(child);
- child = child.nextSibling
- }
++runtime.loadClass("core.Base64");
++runtime.loadClass("xmldom.XPath");
++runtime.loadClass("odf.OdfContainer");
++(function() {
++ var xpath = xmldom.XPath, base64 = new core.Base64;
++ function getEmbeddedFontDeclarations(fontFaceDecls) {
++ var decls = {}, fonts, i, font, name, uris, href, family;
++ if(!fontFaceDecls) {
++ return decls
+ }
- if(accept === NodeFilter.FILTER_ACCEPT) {
- if(nodeType === Node.ELEMENT_NODE && odfUtils.isParagraph(node)) {
- s += "\n"
- }else {
- if(nodeType === Node.TEXT_NODE && node.textContent) {
- s += node.textContent
- }
++ fonts = xpath.getODFElementsWithXPath(fontFaceDecls, "style:font-face[svg:font-face-src]", odf.Namespaces.lookupNamespaceURI);
++ for(i = 0;i < fonts.length;i += 1) {
++ font = fonts[i];
++ name = font.getAttributeNS(odf.Namespaces.stylens, "name");
++ family = font.getAttributeNS(odf.Namespaces.svgns, "font-family");
++ uris = xpath.getODFElementsWithXPath(font, "svg:font-face-src/svg:font-face-uri", odf.Namespaces.lookupNamespaceURI);
++ if(uris.length > 0) {
++ href = uris[0].getAttributeNS(odf.Namespaces.xlinkns, "href");
++ decls[name] = {href:href, family:family}
+ }
+ }
- return s
++ return decls
+ }
- this.filter = null;
- this.writeToString = function(node) {
- var plainText;
- if(!node) {
- return""
- }
- plainText = serializeNode(node);
- if(plainText[plainText.length - 1] === "\n") {
- plainText = plainText.substr(0, plainText.length - 1)
++ function addFontToCSS(name, font, fontdata, stylesheet) {
++ var cssFamily = font.family || name, rule = "@font-face { font-family: '" + cssFamily + "'; src: " + "url(data:application/x-font-ttf;charset=binary;base64," + base64.convertUTF8ArrayToBase64(fontdata) + ') format("truetype"); }';
++ try {
++ stylesheet.insertRule(rule, stylesheet.cssRules.length)
++ }catch(e) {
++ runtime.log("Problem inserting rule in CSS: " + runtime.toJson(e) + "\nRule: " + rule)
+ }
- return plainText
+ }
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++ function loadFontIntoCSS(embeddedFontDeclarations, odfContainer, pos, stylesheet, callback) {
++ var name, i = 0, n;
++ for(n in embeddedFontDeclarations) {
++ if(embeddedFontDeclarations.hasOwnProperty(n)) {
++ if(i === pos) {
++ name = n;
++ break
++ }
++ i += 1
++ }
++ }
++ if(!name) {
++ if(callback) {
++ callback()
++ }
++ return
++ }
++ odfContainer.getPartData(embeddedFontDeclarations[name].href, function(err, fontdata) {
++ if(err) {
++ runtime.log(err)
++ }else {
++ if(!fontdata) {
++ runtime.log("missing font data for " + embeddedFontDeclarations[name].href)
++ }else {
++ addFontToCSS(name, embeddedFontDeclarations[name], fontdata, stylesheet)
++ }
++ }
++ loadFontIntoCSS(embeddedFontDeclarations, odfContainer, pos + 1, stylesheet, callback)
++ })
++ }
++ function loadFontsIntoCSS(embeddedFontDeclarations, odfContainer, stylesheet) {
++ loadFontIntoCSS(embeddedFontDeclarations, odfContainer, 0, stylesheet)
++ }
++ odf.FontLoader = function FontLoader() {
++ this.loadFonts = function(odfContainer, stylesheet) {
++ var embeddedFontDeclarations, fontFaceDecls = odfContainer.rootElement.fontFaceDecls;
++ while(stylesheet.cssRules.length) {
++ stylesheet.deleteRule(stylesheet.cssRules.length - 1)
++ }
++ if(fontFaceDecls) {
++ embeddedFontDeclarations = getEmbeddedFontDeclarations(fontFaceDecls);
++ loadFontsIntoCSS(embeddedFontDeclarations, odfContainer, stylesheet)
++ }
++ }
++ };
++ return odf.FontLoader
++})();
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++runtime.loadClass("core.DomUtils");
++runtime.loadClass("core.Utils");
++odf.ObjectNameGenerator = function ObjectNameGenerator(odfContainer, memberId) {
++ var stylens = odf.Namespaces.stylens, drawns = odf.Namespaces.drawns, xlinkns = odf.Namespaces.xlinkns, domUtils = new core.DomUtils, utils = new core.Utils, memberIdHash = utils.hashString(memberId), styleNameGenerator = null, frameNameGenerator = null, imageNameGenerator = null, existingFrameNames = {}, existingImageNames = {};
++ function NameGenerator(prefix, findExistingNames) {
++ var reportedNames = {};
++ this.generateName = function() {
++ var existingNames = findExistingNames(), startIndex = 0, name;
++ do {
++ name = prefix + startIndex;
++ startIndex += 1
++ }while(reportedNames[name] || existingNames[name]);
++ reportedNames[name] = true;
++ return name
++ }
++ }
++ function getAllStyleNames() {
++ var styleElements = [odfContainer.rootElement.automaticStyles, odfContainer.rootElement.styles], styleNames = {};
++ function getStyleNames(styleListElement) {
++ var e = styleListElement.firstElementChild;
++ while(e) {
++ if(e.namespaceURI === stylens && e.localName === "style") {
++ styleNames[e.getAttributeNS(stylens, "name")] = true
++ }
++ e = e.nextElementSibling
++ }
++ }
++ styleElements.forEach(getStyleNames);
++ return styleNames
++ }
++ this.generateStyleName = function() {
++ if(styleNameGenerator === null) {
++ styleNameGenerator = new NameGenerator("auto" + memberIdHash + "_", function() {
++ return getAllStyleNames()
++ })
++ }
++ return styleNameGenerator.generateName()
++ };
++ this.generateFrameName = function() {
++ if(frameNameGenerator === null) {
++ var nodes = domUtils.getElementsByTagNameNS(odfContainer.rootElement.body, drawns, "frame");
++ nodes.forEach(function(frame) {
++ existingFrameNames[frame.getAttributeNS(drawns, "name")] = true
++ });
++ frameNameGenerator = new NameGenerator("fr" + memberIdHash + "_", function() {
++ return existingFrameNames
++ })
++ }
++ return frameNameGenerator.generateName()
++ };
++ this.generateImageName = function() {
++ if(imageNameGenerator === null) {
++ var nodes = domUtils.getElementsByTagNameNS(odfContainer.rootElement.body, drawns, "image");
++ nodes.forEach(function(image) {
++ var path = image.getAttributeNS(xlinkns, "href");
++ path = path.substring("Pictures/".length, path.lastIndexOf("."));
++ existingImageNames[path] = true
++ });
++ imageNameGenerator = new NameGenerator("img" + memberIdHash + "_", function() {
++ return existingImageNames
++ })
++ }
++ return imageNameGenerator.generateName()
++ }
++};
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+runtime.loadClass("core.DomUtils");
+runtime.loadClass("core.LoopWatchDog");
+runtime.loadClass("odf.Namespaces");
++odf.TextStyleApplicatorFormatting = function() {
++};
++odf.TextStyleApplicatorFormatting.prototype.getAppliedStylesForElement = function(textnode) {
++};
++odf.TextStyleApplicatorFormatting.prototype.createDerivedStyleObject = function(parentStyleName, family, overrides) {
++};
++odf.TextStyleApplicatorFormatting.prototype.updateStyle = function(styleNode, properties) {
++};
+odf.TextStyleApplicator = function TextStyleApplicator(objectNameGenerator, formatting, automaticStyles) {
+ var domUtils = new core.DomUtils, textns = odf.Namespaces.textns, stylens = odf.Namespaces.stylens, textProperties = "style:text-properties", webodfns = "urn:webodf:names:scope";
+ function StyleLookup(info) {
+ function compare(expected, actual) {
+ if(typeof expected === "object" && typeof actual === "object") {
+ return Object.keys(expected).every(function(key) {
+ return compare(expected[key], actual[key])
+ })
+ }
+ return expected === actual
+ }
+ this.isStyleApplied = function(textNode) {
+ var appliedStyle = formatting.getAppliedStylesForElement(textNode);
+ return compare(info, appliedStyle)
+ }
+ }
+ function StyleManager(info) {
+ var createdStyles = {};
+ function createDirectFormat(existingStyleName, document) {
+ var derivedStyleInfo, derivedStyleNode;
+ derivedStyleInfo = existingStyleName ? formatting.createDerivedStyleObject(existingStyleName, "text", info) : info;
+ derivedStyleNode = document.createElementNS(stylens, "style:style");
+ formatting.updateStyle(derivedStyleNode, derivedStyleInfo);
+ derivedStyleNode.setAttributeNS(stylens, "style:name", objectNameGenerator.generateStyleName());
+ derivedStyleNode.setAttributeNS(stylens, "style:family", "text");
+ derivedStyleNode.setAttributeNS(webodfns, "scope", "document-content");
+ automaticStyles.appendChild(derivedStyleNode);
+ return derivedStyleNode
+ }
+ function getDirectStyle(existingStyleName, document) {
+ existingStyleName = existingStyleName || "";
+ if(!createdStyles.hasOwnProperty(existingStyleName)) {
+ createdStyles[existingStyleName] = createDirectFormat(existingStyleName, document)
+ }
+ return createdStyles[existingStyleName].getAttributeNS(stylens, "name")
+ }
+ this.applyStyleToContainer = function(container) {
+ var name = getDirectStyle(container.getAttributeNS(textns, "style-name"), container.ownerDocument);
+ container.setAttributeNS(textns, "text:style-name", name)
+ }
+ }
+ function isTextSpan(node) {
+ return node.localName === "span" && node.namespaceURI === textns
+ }
+ function moveToNewSpan(startNode, limits) {
+ var document = startNode.ownerDocument, originalContainer = (startNode.parentNode), styledContainer, trailingContainer, moveTrailing, node, nextNode, loopGuard = new core.LoopWatchDog(1E4), styledNodes = [];
+ if(!isTextSpan(originalContainer)) {
+ styledContainer = document.createElementNS(textns, "text:span");
+ originalContainer.insertBefore(styledContainer, startNode);
+ moveTrailing = false
+ }else {
+ if(startNode.previousSibling && !domUtils.rangeContainsNode(limits, (originalContainer.firstChild))) {
+ styledContainer = originalContainer.cloneNode(false);
+ originalContainer.parentNode.insertBefore(styledContainer, originalContainer.nextSibling);
+ moveTrailing = true
+ }else {
+ styledContainer = originalContainer;
+ moveTrailing = true
+ }
+ }
+ styledNodes.push(startNode);
+ node = startNode.nextSibling;
+ while(node && domUtils.rangeContainsNode(limits, node)) {
+ loopGuard.check();
+ styledNodes.push(node);
+ node = node.nextSibling
+ }
- styledNodes.forEach(function(node) {
- if(node.parentNode !== styledContainer) {
- styledContainer.appendChild(node)
++ styledNodes.forEach(function(n) {
++ if(n.parentNode !== styledContainer) {
++ styledContainer.appendChild(n)
+ }
+ });
+ if(node && moveTrailing) {
+ trailingContainer = styledContainer.cloneNode(false);
+ styledContainer.parentNode.insertBefore(trailingContainer, styledContainer.nextSibling);
+ while(node) {
+ loopGuard.check();
+ nextNode = node.nextSibling;
+ trailingContainer.appendChild(node);
+ node = nextNode
+ }
+ }
+ return(styledContainer)
+ }
+ this.applyStyle = function(textNodes, limits, info) {
+ var textPropsOnly = {}, isStyled, container, styleCache, styleLookup;
- runtime.assert(info && info[textProperties], "applyStyle without any text properties");
++ runtime.assert(info && info.hasOwnProperty(textProperties), "applyStyle without any text properties");
+ textPropsOnly[textProperties] = info[textProperties];
+ styleCache = new StyleManager(textPropsOnly);
+ styleLookup = new StyleLookup(textPropsOnly);
- textNodes.forEach(function(n) {
++ function apply(n) {
+ isStyled = styleLookup.isStyleApplied(n);
+ if(isStyled === false) {
- container = moveToNewSpan((n), limits);
++ container = moveToNewSpan(n, limits);
+ styleCache.applyStyleToContainer(container)
+ }
- })
++ }
++ textNodes.forEach(apply)
+ }
+};
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
++runtime.loadClass("core.Utils");
++runtime.loadClass("odf.ObjectNameGenerator");
+runtime.loadClass("odf.Namespaces");
++runtime.loadClass("odf.OdfContainer");
++runtime.loadClass("odf.StyleInfo");
+runtime.loadClass("odf.OdfUtils");
- runtime.loadClass("xmldom.XPath");
- runtime.loadClass("core.CSSUnits");
- odf.Style2CSS = function Style2CSS() {
- var drawns = odf.Namespaces.drawns, fons = odf.Namespaces.fons, stylens = odf.Namespaces.stylens, svgns = odf.Namespaces.svgns, tablens = odf.Namespaces.tablens, textns = odf.Namespaces.textns, xlinkns = odf.Namespaces.xlinkns, presentationns = odf.Namespaces.presentationns, familynamespaceprefixes = {"graphic":"draw", "drawing-page":"draw", "paragraph":"text", "presentation":"presentation", "ruby":"text", "section":"text", "table":"table", "table-cell":"table", "table-column":"table" [...]
- "text":"text", "list":"text", "page":"office"}, familytagnames = {"graphic":["circle", "connected", "control", "custom-shape", "ellipse", "frame", "g", "line", "measure", "page", "page-thumbnail", "path", "polygon", "polyline", "rect", "regular-polygon"], "paragraph":["alphabetical-index-entry-template", "h", "illustration-index-entry-template", "index-source-style", "object-index-entry-template", "p", "table-index-entry-template", "table-of-content-entry-template", "user-index-entry- [...]
- "presentation":["caption", "circle", "connector", "control", "custom-shape", "ellipse", "frame", "g", "line", "measure", "page-thumbnail", "path", "polygon", "polyline", "rect", "regular-polygon"], "drawing-page":["caption", "circle", "connector", "control", "page", "custom-shape", "ellipse", "frame", "g", "line", "measure", "page-thumbnail", "path", "polygon", "polyline", "rect", "regular-polygon"], "ruby":["ruby", "ruby-text"], "section":["alphabetical-index", "bibliography", "illus [...]
- "index-title", "object-index", "section", "table-of-content", "table-index", "user-index"], "table":["background", "table"], "table-cell":["body", "covered-table-cell", "even-columns", "even-rows", "first-column", "first-row", "last-column", "last-row", "odd-columns", "odd-rows", "table-cell"], "table-column":["table-column"], "table-row":["table-row"], "text":["a", "index-entry-chapter", "index-entry-link-end", "index-entry-link-start", "index-entry-page-number", "index-entry-span", [...]
- "index-entry-text", "index-title-template", "linenumbering-configuration", "list-level-style-number", "list-level-style-bullet", "outline-level-style", "span"], "list":["list-item"]}, textPropertySimpleMapping = [[fons, "color", "color"], [fons, "background-color", "background-color"], [fons, "font-weight", "font-weight"], [fons, "font-style", "font-style"]], bgImageSimpleMapping = [[stylens, "repeat", "background-repeat"]], paragraphPropertySimpleMapping = [[fons, "background-color", [...]
- [fons, "text-align", "text-align"], [fons, "text-indent", "text-indent"], [fons, "padding", "padding"], [fons, "padding-left", "padding-left"], [fons, "padding-right", "padding-right"], [fons, "padding-top", "padding-top"], [fons, "padding-bottom", "padding-bottom"], [fons, "border-left", "border-left"], [fons, "border-right", "border-right"], [fons, "border-top", "border-top"], [fons, "border-bottom", "border-bottom"], [fons, "margin", "margin"], [fons, "margin-left", "margin-left"], [...]
- "margin-right"], [fons, "margin-top", "margin-top"], [fons, "margin-bottom", "margin-bottom"], [fons, "border", "border"]], graphicPropertySimpleMapping = [[fons, "background-color", "background-color"], [fons, "min-height", "min-height"], [drawns, "stroke", "border"], [svgns, "stroke-color", "border-color"], [svgns, "stroke-width", "border-width"], [fons, "border", "border"], [fons, "border-left", "border-left"], [fons, "border-right", "border-right"], [fons, "border-top", "border-to [...]
- "border-bottom", "border-bottom"]], tablecellPropertySimpleMapping = [[fons, "background-color", "background-color"], [fons, "border-left", "border-left"], [fons, "border-right", "border-right"], [fons, "border-top", "border-top"], [fons, "border-bottom", "border-bottom"], [fons, "border", "border"]], tablecolumnPropertySimpleMapping = [[stylens, "column-width", "width"]], tablerowPropertySimpleMapping = [[stylens, "row-height", "height"], [fons, "keep-together", null]], tableProperty [...]
- [[stylens, "width", "width"], [fons, "margin-left", "margin-left"], [fons, "margin-right", "margin-right"], [fons, "margin-top", "margin-top"], [fons, "margin-bottom", "margin-bottom"]], pageContentPropertySimpleMapping = [[fons, "background-color", "background-color"], [fons, "padding", "padding"], [fons, "padding-left", "padding-left"], [fons, "padding-right", "padding-right"], [fons, "padding-top", "padding-top"], [fons, "padding-bottom", "padding-bottom"], [fons, "border", "border [...]
- "border-left", "border-left"], [fons, "border-right", "border-right"], [fons, "border-top", "border-top"], [fons, "border-bottom", "border-bottom"], [fons, "margin", "margin"], [fons, "margin-left", "margin-left"], [fons, "margin-right", "margin-right"], [fons, "margin-top", "margin-top"], [fons, "margin-bottom", "margin-bottom"]], pageSizePropertySimpleMapping = [[fons, "page-width", "width"], [fons, "page-height", "height"]], borderPropertyMap = {"border":true, "border-left":true, " [...]
- "border-top":true, "border-bottom":true, "stroke-width":true}, fontFaceDeclsMap = {}, utils = new odf.OdfUtils, documentType, odfRoot, defaultFontSize, xpath = new xmldom.XPath, cssUnits = new core.CSSUnits;
- function getStyleMap(stylesnode) {
- var stylemap = {}, node, name, family, style;
- if(!stylesnode) {
- return stylemap
++runtime.loadClass("odf.TextStyleApplicator");
++odf.Formatting = function Formatting() {
++ var self = this, odfContainer, styleInfo = new odf.StyleInfo, svgns = odf.Namespaces.svgns, stylens = odf.Namespaces.stylens, textns = odf.Namespaces.textns, numberns = odf.Namespaces.numberns, fons = odf.Namespaces.fons, odfUtils = new odf.OdfUtils, domUtils = new core.DomUtils, utils = new core.Utils, builtInDefaultStyleAttributesByFamily = {"paragraph":{"style:paragraph-properties":{"fo:text-align":"left"}}}, defaultPageFormatSettings = {width:21.001, height:29.7, margin:2, padding:0};
++ function getSystemDefaultStyleAttributes(styleFamily) {
++ var result, builtInDefaultStyleAttributes = builtInDefaultStyleAttributesByFamily[styleFamily];
++ if(builtInDefaultStyleAttributes) {
++ result = utils.mergeObjects({}, builtInDefaultStyleAttributes)
++ }else {
++ result = {}
+ }
- node = stylesnode.firstChild;
- while(node) {
- if(node.namespaceURI === stylens && (node.localName === "style" || node.localName === "default-style")) {
- family = node.getAttributeNS(stylens, "family")
- }else {
- if(node.namespaceURI === textns && node.localName === "list-style") {
- family = "list"
- }else {
- if(node.namespaceURI === stylens && (node.localName === "page-layout" || node.localName === "default-page-layout")) {
- family = "page"
- }else {
- family = undefined
- }
- }
++ return result
++ }
++ this.getSystemDefaultStyleAttributes = getSystemDefaultStyleAttributes;
++ this.setOdfContainer = function(odfcontainer) {
++ odfContainer = odfcontainer
++ };
++ function getDirectChild(node, ns, name) {
++ var e = node && node.firstElementChild;
++ while(e) {
++ if(e.namespaceURI === ns && e.localName === name) {
++ break
+ }
- if(family) {
- name = node.getAttributeNS && node.getAttributeNS(stylens, "name");
- if(!name) {
- name = ""
++ e = e.nextElementSibling
++ }
++ return e
++ }
++ function getFontMap() {
++ var fontFaceDecls = odfContainer.rootElement.fontFaceDecls, fontFaceDeclsMap = {}, node, name, family;
++ node = fontFaceDecls && fontFaceDecls.firstElementChild;
++ while(node) {
++ name = node.getAttributeNS(stylens, "name");
++ if(name) {
++ family = node.getAttributeNS(svgns, "font-family");
++ if(family || node.getElementsByTagNameNS(svgns, "font-face-uri").length > 0) {
++ fontFaceDeclsMap[name] = family
+ }
- style = stylemap[family] = stylemap[family] || {};
- style[name] = node
+ }
- node = node.nextSibling
++ node = node.nextElementSibling
+ }
- return stylemap
++ return fontFaceDeclsMap
+ }
- function findStyle(stylestree, name) {
- if(!name || !stylestree) {
- return null
++ this.getFontMap = getFontMap;
++ this.getAvailableParagraphStyles = function() {
++ var node = odfContainer.rootElement.styles, p_family, p_name, p_displayName, paragraphStyles = [];
++ node = node && node.firstElementChild;
++ while(node) {
++ if(node.localName === "style" && node.namespaceURI === stylens) {
++ p_family = node.getAttributeNS(stylens, "family");
++ if(p_family === "paragraph") {
++ p_name = node.getAttributeNS(stylens, "name");
++ p_displayName = node.getAttributeNS(stylens, "display-name") || p_name;
++ if(p_name && p_displayName) {
++ paragraphStyles.push({name:p_name, displayName:p_displayName})
++ }
++ }
++ }
++ node = node.nextElementSibling
+ }
- if(stylestree[name]) {
- return stylestree[name]
++ return paragraphStyles
++ };
++ this.isStyleUsed = function(styleElement) {
++ var hasDerivedStyles, isUsed, root = odfContainer.rootElement;
++ hasDerivedStyles = styleInfo.hasDerivedStyles(root, odf.Namespaces.lookupNamespaceURI, styleElement);
++ isUsed = (new styleInfo.UsedStyleList(root.styles)).uses(styleElement) || ((new styleInfo.UsedStyleList(root.automaticStyles)).uses(styleElement) || (new styleInfo.UsedStyleList(root.body)).uses(styleElement));
++ return hasDerivedStyles || isUsed
++ };
++ function getDefaultStyleElement(family) {
++ var node = odfContainer.rootElement.styles.firstElementChild;
++ while(node) {
++ if(node.namespaceURI === stylens && (node.localName === "default-style" && node.getAttributeNS(stylens, "family") === family)) {
++ return node
++ }
++ node = node.nextElementSibling
+ }
- var n, style;
- for(n in stylestree) {
- if(stylestree.hasOwnProperty(n)) {
- style = findStyle(stylestree[n].derivedStyles, name);
- if(style) {
- return style
++ return null
++ }
++ this.getDefaultStyleElement = getDefaultStyleElement;
++ function getStyleElement(styleName, family, styleElements) {
++ var node, nodeStyleName, styleListElement, i;
++ styleElements = styleElements || [odfContainer.rootElement.automaticStyles, odfContainer.rootElement.styles];
++ for(i = 0;i < styleElements.length;i += 1) {
++ styleListElement = (styleElements[i]);
++ node = styleListElement.firstElementChild;
++ while(node) {
++ nodeStyleName = node.getAttributeNS(stylens, "name");
++ if(node.namespaceURI === stylens && (node.localName === "style" && (node.getAttributeNS(stylens, "family") === family && nodeStyleName === styleName))) {
++ return node
++ }
++ if(family === "list-style" && (node.namespaceURI === textns && (node.localName === "list-style" && nodeStyleName === styleName))) {
++ return node
+ }
++ if(family === "data" && (node.namespaceURI === numberns && nodeStyleName === styleName)) {
++ return node
++ }
++ node = node.nextElementSibling
+ }
+ }
+ return null
+ }
- function addStyleToStyleTree(stylename, stylesmap, stylestree) {
- var style = stylesmap[stylename], parentname, parentstyle;
- if(!style) {
- return
- }
- parentname = style.getAttributeNS(stylens, "parent-style-name");
- parentstyle = null;
- if(parentname) {
- parentstyle = findStyle(stylestree, parentname);
- if(!parentstyle && stylesmap[parentname]) {
- addStyleToStyleTree(parentname, stylesmap, stylestree);
- parentstyle = stylesmap[parentname];
- stylesmap[parentname] = null
++ this.getStyleElement = getStyleElement;
++ function getStyleAttributes(styleNode) {
++ var i, a, map, ai, propertiesMap = {}, propertiesNode = styleNode.firstElementChild;
++ while(propertiesNode) {
++ if(propertiesNode.namespaceURI === stylens) {
++ map = propertiesMap[propertiesNode.nodeName] = {};
++ a = propertiesNode.attributes;
++ for(i = 0;i < a.length;i += 1) {
++ ai = (a.item(i));
++ map[ai.name] = ai.value
++ }
+ }
++ propertiesNode = propertiesNode.nextElementSibling
+ }
- if(parentstyle) {
- if(!parentstyle.derivedStyles) {
- parentstyle.derivedStyles = {}
- }
- parentstyle.derivedStyles[stylename] = style
- }else {
- stylestree[stylename] = style
++ a = styleNode.attributes;
++ for(i = 0;i < a.length;i += 1) {
++ ai = (a.item(i));
++ propertiesMap[ai.name] = ai.value
+ }
++ return propertiesMap
+ }
- function addStyleMapToStyleTree(stylesmap, stylestree) {
- var name;
- for(name in stylesmap) {
- if(stylesmap.hasOwnProperty(name)) {
- addStyleToStyleTree(name, stylesmap, stylestree);
- stylesmap[name] = null
++ this.getStyleAttributes = getStyleAttributes;
++ function getInheritedStyleAttributes(styleNode, includeSystemDefault) {
++ var styleListElement = odfContainer.rootElement.styles, parentStyleName, propertiesMap, inheritedPropertiesMap = {}, styleFamily = styleNode.getAttributeNS(stylens, "family"), node = styleNode;
++ while(node) {
++ propertiesMap = getStyleAttributes(node);
++ inheritedPropertiesMap = utils.mergeObjects(propertiesMap, inheritedPropertiesMap);
++ parentStyleName = node.getAttributeNS(stylens, "parent-style-name");
++ if(parentStyleName) {
++ node = getStyleElement(parentStyleName, styleFamily, [styleListElement])
++ }else {
++ node = null
+ }
+ }
- }
- function createSelector(family, name) {
- var prefix = familynamespaceprefixes[family], namepart, selector;
- if(prefix === null) {
- return null
- }
- if(name) {
- namepart = "[" + prefix + '|style-name="' + name + '"]'
- }else {
- namepart = ""
++ node = getDefaultStyleElement(styleFamily);
++ if(node) {
++ propertiesMap = getStyleAttributes(node);
++ inheritedPropertiesMap = utils.mergeObjects(propertiesMap, inheritedPropertiesMap)
+ }
- if(prefix === "presentation") {
- prefix = "draw";
- if(name) {
- namepart = '[presentation|style-name="' + name + '"]'
- }else {
- namepart = ""
++ if(includeSystemDefault) {
++ propertiesMap = getSystemDefaultStyleAttributes(styleFamily);
++ if(propertiesMap) {
++ inheritedPropertiesMap = utils.mergeObjects(propertiesMap, inheritedPropertiesMap)
+ }
+ }
- selector = prefix + "|" + familytagnames[family].join(namepart + "," + prefix + "|") + namepart;
- return selector
++ return inheritedPropertiesMap
+ }
- function getSelectors(family, name, node) {
- var selectors = [], n, ss, s;
- selectors.push(createSelector(family, name));
- for(n in node.derivedStyles) {
- if(node.derivedStyles.hasOwnProperty(n)) {
- ss = getSelectors(family, n, node.derivedStyles[n]);
- for(s in ss) {
- if(ss.hasOwnProperty(s)) {
- selectors.push(ss[s])
- }
- }
- }
++ this.getInheritedStyleAttributes = getInheritedStyleAttributes;
++ this.getFirstCommonParentStyleNameOrSelf = function(styleName) {
++ var automaticStyleElementList = odfContainer.rootElement.automaticStyles, styleElementList = odfContainer.rootElement.styles, styleElement;
++ styleElement = getStyleElement(styleName, "paragraph", [automaticStyleElementList]);
++ while(styleElement) {
++ styleName = styleElement.getAttributeNS(stylens, "parent-style-name");
++ styleElement = getStyleElement(styleName, "paragraph", [automaticStyleElementList])
+ }
- return selectors
- }
- function getDirectChild(node, ns, name) {
- if(!node) {
++ styleElement = getStyleElement(styleName, "paragraph", [styleElementList]);
++ if(!styleElement) {
+ return null
+ }
- var c = node.firstChild, e;
- while(c) {
- if(c.namespaceURI === ns && c.localName === name) {
- e = (c);
- return e
++ return styleName
++ };
++ this.hasParagraphStyle = function(styleName) {
++ return Boolean(getStyleElement(styleName, "paragraph"))
++ };
++ function buildStyleChain(node, collectedChains) {
++ var parent = (node.nodeType === Node.TEXT_NODE ? node.parentNode : node), nodeStyles, appliedStyles = [], chainKey = "", foundContainer = false;
++ while(parent) {
++ if(!foundContainer && odfUtils.isGroupingElement(parent)) {
++ foundContainer = true
+ }
- c = c.nextSibling
++ nodeStyles = styleInfo.determineStylesForNode(parent);
++ if(nodeStyles) {
++ appliedStyles.push(nodeStyles)
++ }
++ parent = parent.parentElement
+ }
- return null
- }
- function fixBorderWidth(value) {
- var index = value.indexOf(" "), width, theRestOfBorderAttributes;
- if(index !== -1) {
- width = value.substring(0, index);
- theRestOfBorderAttributes = value.substring(index)
- }else {
- width = value;
- theRestOfBorderAttributes = ""
++ function chainStyles(usedStyleMap) {
++ Object.keys(usedStyleMap).forEach(function(styleFamily) {
++ Object.keys(usedStyleMap[styleFamily]).forEach(function(styleName) {
++ chainKey += "|" + styleFamily + ":" + styleName + "|"
++ })
++ })
+ }
- width = utils.parseLength(width);
- if(width && (width.unit === "pt" && width.value < 0.75)) {
- value = "0.75pt" + theRestOfBorderAttributes
++ if(foundContainer) {
++ appliedStyles.forEach(chainStyles);
++ if(collectedChains) {
++ collectedChains[chainKey] = appliedStyles
++ }
+ }
- return value
++ return foundContainer ? appliedStyles : undefined
+ }
- function applySimpleMapping(props, mapping) {
- var rule = "", r, value;
- for(r in mapping) {
- if(mapping.hasOwnProperty(r)) {
- r = mapping[r];
- value = props.getAttributeNS(r[0], r[1]);
- if(value) {
- value = value.trim();
- if(borderPropertyMap.hasOwnProperty(r[1])) {
- value = fixBorderWidth(value)
- }
- if(r[2]) {
- rule += r[2] + ":" + value + ";"
- }
++ function calculateAppliedStyle(styleChain) {
++ var mergedChildStyle = {orderedStyles:[]};
++ styleChain.forEach(function(elementStyleSet) {
++ Object.keys((elementStyleSet)).forEach(function(styleFamily) {
++ var styleName = Object.keys(elementStyleSet[styleFamily])[0], styleElement, parentStyle, displayName;
++ styleElement = getStyleElement(styleName, styleFamily);
++ if(styleElement) {
++ parentStyle = getInheritedStyleAttributes((styleElement));
++ mergedChildStyle = utils.mergeObjects(parentStyle, mergedChildStyle);
++ displayName = styleElement.getAttributeNS(stylens, "display-name")
++ }else {
++ runtime.log("No style element found for '" + styleName + "' of family '" + styleFamily + "'")
+ }
- }
- }
- return rule
++ mergedChildStyle.orderedStyles.push({name:styleName, family:styleFamily, displayName:displayName})
++ })
++ });
++ return mergedChildStyle
+ }
- function getFontSize(styleNode) {
- var props = getDirectChild((styleNode), stylens, "text-properties");
- if(props) {
- return utils.parseFoFontSize(props.getAttributeNS(fons, "font-size"))
++ this.getAppliedStyles = function(textNodes) {
++ var styleChains = {}, styles = [];
++ textNodes.forEach(function(n) {
++ buildStyleChain(n, styleChains)
++ });
++ Object.keys(styleChains).forEach(function(key) {
++ styles.push(calculateAppliedStyle(styleChains[key]))
++ });
++ return styles
++ };
++ this.getAppliedStylesForElement = function(node) {
++ var styleChain;
++ styleChain = buildStyleChain(node);
++ return styleChain ? calculateAppliedStyle(styleChain) : undefined
++ };
++ this.applyStyle = function(memberId, textNodes, limits, info) {
++ var textStyles = new odf.TextStyleApplicator(new odf.ObjectNameGenerator((odfContainer), memberId), self, odfContainer.rootElement.automaticStyles);
++ textStyles.applyStyle(textNodes, limits, info)
++ };
++ this.updateStyle = function(styleNode, properties) {
++ var fontName, fontFaceNode;
++ domUtils.mapObjOntoNode(styleNode, properties, odf.Namespaces.lookupNamespaceURI);
++ fontName = properties["style:text-properties"] && properties["style:text-properties"]["style:font-name"];
++ if(fontName && !getFontMap().hasOwnProperty(fontName)) {
++ fontFaceNode = styleNode.ownerDocument.createElementNS(stylens, "style:font-face");
++ fontFaceNode.setAttributeNS(stylens, "style:name", fontName);
++ fontFaceNode.setAttributeNS(svgns, "svg:font-family", fontName);
++ odfContainer.rootElement.fontFaceDecls.appendChild(fontFaceNode)
+ }
- return null
++ };
++ function isAutomaticStyleElement(styleNode) {
++ return styleNode.parentNode === odfContainer.rootElement.automaticStyles
+ }
- function getParentStyleNode(styleNode) {
- var parentStyleName = "", parentStyleFamily = "", parentStyleNode = null, xp;
- if(styleNode.localName === "default-style") {
- return null
- }
- parentStyleName = styleNode.getAttributeNS(stylens, "parent-style-name");
- parentStyleFamily = styleNode.getAttributeNS(stylens, "family");
- if(parentStyleName) {
- xp = "//style:*[@style:name='" + parentStyleName + "'][@style:family='" + parentStyleFamily + "']"
++ this.createDerivedStyleObject = function(parentStyleName, family, overrides) {
++ var originalStyleElement = (getStyleElement(parentStyleName, family)), newStyleObject;
++ runtime.assert(Boolean(originalStyleElement), "No style element found for '" + parentStyleName + "' of family '" + family + "'");
++ if(isAutomaticStyleElement(originalStyleElement)) {
++ newStyleObject = getStyleAttributes(originalStyleElement)
+ }else {
- xp = "//style:default-style[@style:family='" + parentStyleFamily + "']"
- }
- parentStyleNode = xpath.getODFElementsWithXPath((odfRoot), xp, odf.Namespaces.resolvePrefix)[0];
- return parentStyleNode
- }
- function getTextProperties(props) {
- var rule = "", fontName, fontSize, value, textDecoration = "", fontSizeRule = "", sizeMultiplier = 1, parentStyle;
- rule += applySimpleMapping(props, textPropertySimpleMapping);
- value = props.getAttributeNS(stylens, "text-underline-style");
- if(value === "solid") {
- textDecoration += " underline"
- }
- value = props.getAttributeNS(stylens, "text-line-through-style");
- if(value === "solid") {
- textDecoration += " line-through"
- }
- if(textDecoration.length) {
- textDecoration = "text-decoration:" + textDecoration + ";";
- rule += textDecoration
++ newStyleObject = {"style:parent-style-name":parentStyleName}
+ }
- fontName = props.getAttributeNS(stylens, "font-name") || props.getAttributeNS(fons, "font-family");
- if(fontName) {
- value = fontFaceDeclsMap[fontName];
- rule += "font-family: " + (value || fontName) + ";"
++ newStyleObject["style:family"] = family;
++ utils.mergeObjects(newStyleObject, overrides);
++ return newStyleObject
++ };
++ this.getDefaultTabStopDistance = function() {
++ var defaultParagraph = getDefaultStyleElement("paragraph"), paragraphProperties = defaultParagraph && defaultParagraph.firstElementChild, tabStopDistance;
++ while(paragraphProperties) {
++ if(paragraphProperties.namespaceURI === stylens && paragraphProperties.localName === "paragraph-properties") {
++ tabStopDistance = paragraphProperties.getAttributeNS(stylens, "tab-stop-distance")
++ }
++ paragraphProperties = paragraphProperties.nextElementSibling
+ }
- parentStyle = props.parentNode;
- fontSize = getFontSize((parentStyle));
- if(!fontSize) {
- return rule
++ if(!tabStopDistance) {
++ tabStopDistance = "1.25cm"
+ }
- while(parentStyle) {
- fontSize = getFontSize((parentStyle));
- if(fontSize) {
- if(fontSize.unit !== "%") {
- fontSizeRule = "font-size: " + fontSize.value * sizeMultiplier + fontSize.unit + ";";
++ return odfUtils.parseNonNegativeLength(tabStopDistance)
++ };
++ function getPageLayoutStyleElement(styleName, styleFamily) {
++ var masterPageName, layoutName, pageLayoutElements, node, i, styleElement = getStyleElement(styleName, styleFamily);
++ runtime.assert(styleFamily === "paragraph" || styleFamily === "table", "styleFamily has to be either paragraph or table");
++ if(styleElement) {
++ masterPageName = styleElement.getAttributeNS(stylens, "master-page-name") || "Standard";
++ node = odfContainer.rootElement.masterStyles.lastElementChild;
++ while(node) {
++ if(node.getAttributeNS(stylens, "name") === masterPageName) {
+ break
+ }
- sizeMultiplier *= fontSize.value / 100
++ node = node.previousElementSibling
++ }
++ layoutName = node.getAttributeNS(stylens, "page-layout-name");
++ pageLayoutElements = domUtils.getElementsByTagNameNS(odfContainer.rootElement.automaticStyles, stylens, "page-layout");
++ for(i = 0;i < pageLayoutElements.length;i += 1) {
++ node = pageLayoutElements[i];
++ if(node.getAttributeNS(stylens, "name") === layoutName) {
++ return(node)
++ }
+ }
- parentStyle = getParentStyleNode(parentStyle)
- }
- if(!fontSizeRule) {
- fontSizeRule = "font-size: " + parseFloat(defaultFontSize) * sizeMultiplier + cssUnits.getUnits(defaultFontSize) + ";"
+ }
- rule += fontSizeRule;
- return rule
++ return null
+ }
- function getParagraphProperties(props) {
- var rule = "", imageProps, url, element, lineHeight;
- rule += applySimpleMapping(props, paragraphPropertySimpleMapping);
- imageProps = props.getElementsByTagNameNS(stylens, "background-image");
- if(imageProps.length > 0) {
- url = imageProps.item(0).getAttributeNS(xlinkns, "href");
- if(url) {
- rule += "background-image: url('odfkit:" + url + "');";
- element = (imageProps.item(0));
- rule += applySimpleMapping(element, bgImageSimpleMapping)
++ function lengthInCm(length, defaultValue) {
++ var result = odfUtils.parseLength(length), value = defaultValue;
++ if(result) {
++ switch(result.unit) {
++ case "cm":
++ value = result.value;
++ break;
++ case "mm":
++ value = result.value * 0.1;
++ break;
++ case "in":
++ value = result.value * 2.54;
++ break;
++ case "pt":
++ value = result.value * 0.035277778;
++ break;
++ case "pc":
++ ;
++ case "px":
++ ;
++ case "em":
++ break;
++ default:
++ runtime.log("Unit identifier: " + result.unit + " is not supported.");
++ break
+ }
+ }
- lineHeight = props.getAttributeNS(fons, "line-height");
- if(lineHeight && lineHeight !== "normal") {
- lineHeight = utils.parseFoLineHeight(lineHeight);
- if(lineHeight.unit !== "%") {
- rule += "line-height: " + lineHeight.value + lineHeight.unit + ";"
++ return value
++ }
++ this.getContentSize = function(styleName, styleFamily) {
++ var pageLayoutElement, props, printOrientation, defaultOrientedPageWidth, defaultOrientedPageHeight, pageWidth, pageHeight, margin, marginLeft, marginRight, marginTop, marginBottom, padding, paddingLeft, paddingRight, paddingTop, paddingBottom;
++ pageLayoutElement = getPageLayoutStyleElement(styleName, styleFamily);
++ if(!pageLayoutElement) {
++ pageLayoutElement = getDirectChild(odfContainer.rootElement.styles, stylens, "default-page-layout")
++ }
++ props = getDirectChild(pageLayoutElement, stylens, "page-layout-properties");
++ if(props) {
++ printOrientation = props.getAttributeNS(stylens, "print-orientation") || "portrait";
++ if(printOrientation === "portrait") {
++ defaultOrientedPageWidth = defaultPageFormatSettings.width;
++ defaultOrientedPageHeight = defaultPageFormatSettings.height
+ }else {
- rule += "line-height: " + lineHeight.value / 100 + ";"
++ defaultOrientedPageWidth = defaultPageFormatSettings.height;
++ defaultOrientedPageHeight = defaultPageFormatSettings.width
+ }
- }
- return rule
- }
- function hexToRgb(hex) {
- var result, shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
- hex = hex.replace(shorthandRegex, function(m, r, g, b) {
- return r + r + g + g + b + b
- });
- result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
- return result ? {r:parseInt(result[1], 16), g:parseInt(result[2], 16), b:parseInt(result[3], 16)} : null
- }
- function isNumber(n) {
- return!isNaN(parseFloat(n))
- }
- function getGraphicProperties(props) {
- var rule = "", alpha, bgcolor, fill;
- rule += applySimpleMapping(props, graphicPropertySimpleMapping);
- alpha = props.getAttributeNS(drawns, "opacity");
- fill = props.getAttributeNS(drawns, "fill");
- bgcolor = props.getAttributeNS(drawns, "fill-color");
- if(fill === "solid" || fill === "hatch") {
- if(bgcolor && bgcolor !== "none") {
- alpha = isNumber(alpha) ? parseFloat(alpha) / 100 : 1;
- bgcolor = hexToRgb(bgcolor);
- if(bgcolor) {
- rule += "background-color: rgba(" + bgcolor.r + "," + bgcolor.g + "," + bgcolor.b + "," + alpha + ");"
- }
++ pageWidth = lengthInCm(props.getAttributeNS(fons, "page-width"), defaultOrientedPageWidth);
++ pageHeight = lengthInCm(props.getAttributeNS(fons, "page-height"), defaultOrientedPageHeight);
++ margin = lengthInCm(props.getAttributeNS(fons, "margin"), null);
++ if(margin === null) {
++ marginLeft = lengthInCm(props.getAttributeNS(fons, "margin-left"), defaultPageFormatSettings.margin);
++ marginRight = lengthInCm(props.getAttributeNS(fons, "margin-right"), defaultPageFormatSettings.margin);
++ marginTop = lengthInCm(props.getAttributeNS(fons, "margin-top"), defaultPageFormatSettings.margin);
++ marginBottom = lengthInCm(props.getAttributeNS(fons, "margin-bottom"), defaultPageFormatSettings.margin)
+ }else {
- rule += "background: none;"
++ marginLeft = marginRight = marginTop = marginBottom = margin
+ }
- }else {
- if(fill === "none") {
- rule += "background: none;"
++ padding = lengthInCm(props.getAttributeNS(fons, "padding"), null);
++ if(padding === null) {
++ paddingLeft = lengthInCm(props.getAttributeNS(fons, "padding-left"), defaultPageFormatSettings.padding);
++ paddingRight = lengthInCm(props.getAttributeNS(fons, "padding-right"), defaultPageFormatSettings.padding);
++ paddingTop = lengthInCm(props.getAttributeNS(fons, "padding-top"), defaultPageFormatSettings.padding);
++ paddingBottom = lengthInCm(props.getAttributeNS(fons, "padding-bottom"), defaultPageFormatSettings.padding)
++ }else {
++ paddingLeft = paddingRight = paddingTop = paddingBottom = padding
+ }
+ }
- return rule
++ return{width:pageWidth - marginLeft - marginRight - paddingLeft - paddingRight, height:pageHeight - marginTop - marginBottom - paddingTop - paddingBottom}
+ }
- function getDrawingPageProperties(props) {
- var rule = "";
- rule += applySimpleMapping(props, graphicPropertySimpleMapping);
- if(props.getAttributeNS(presentationns, "background-visible") === "true") {
- rule += "background: none;"
++};
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++runtime.loadClass("core.DomUtils");
++runtime.loadClass("odf.OdfContainer");
++runtime.loadClass("odf.Formatting");
++runtime.loadClass("xmldom.XPath");
++runtime.loadClass("odf.FontLoader");
++runtime.loadClass("odf.Style2CSS");
++runtime.loadClass("odf.OdfUtils");
++runtime.loadClass("gui.AnnotationViewManager");
++(function() {
++ function LoadingQueue() {
++ var queue = [], taskRunning = false;
++ function run(task) {
++ taskRunning = true;
++ runtime.setTimeout(function() {
++ try {
++ task()
++ }catch(e) {
++ runtime.log(String(e))
++ }
++ taskRunning = false;
++ if(queue.length > 0) {
++ run(queue.pop())
++ }
++ }, 10)
+ }
- return rule
- }
- function getTableCellProperties(props) {
- var rule = "";
- rule += applySimpleMapping(props, tablecellPropertySimpleMapping);
- return rule
- }
- function getTableRowProperties(props) {
- var rule = "";
- rule += applySimpleMapping(props, tablerowPropertySimpleMapping);
- return rule
- }
- function getTableColumnProperties(props) {
- var rule = "";
- rule += applySimpleMapping(props, tablecolumnPropertySimpleMapping);
- return rule
- }
- function getTableProperties(props) {
- var rule = "", borderModel;
- rule += applySimpleMapping(props, tablePropertySimpleMapping);
- borderModel = props.getAttributeNS(tablens, "border-model");
- if(borderModel === "collapsing") {
- rule += "border-collapse:collapse;"
- }else {
- if(borderModel === "separating") {
- rule += "border-collapse:separate;"
++ this.clearQueue = function() {
++ queue.length = 0
++ };
++ this.addToQueue = function(loadingTask) {
++ if(queue.length === 0 && !taskRunning) {
++ return run(loadingTask)
+ }
++ queue.push(loadingTask)
+ }
- return rule
+ }
- function addStyleRule(sheet, family, name, node) {
- var selectors = getSelectors(family, name, node), selector = selectors.join(","), rule = "", properties = getDirectChild(node, stylens, "text-properties");
- if(properties) {
- rule += getTextProperties(properties)
- }
- properties = getDirectChild(node, stylens, "paragraph-properties");
- if(properties) {
- rule += getParagraphProperties(properties)
- }
- properties = getDirectChild(node, stylens, "graphic-properties");
- if(properties) {
- rule += getGraphicProperties(properties)
- }
- properties = getDirectChild(node, stylens, "drawing-page-properties");
- if(properties) {
- rule += getDrawingPageProperties(properties)
- }
- properties = getDirectChild(node, stylens, "table-cell-properties");
- if(properties) {
- rule += getTableCellProperties(properties)
- }
- properties = getDirectChild(node, stylens, "table-row-properties");
- if(properties) {
- rule += getTableRowProperties(properties)
- }
- properties = getDirectChild(node, stylens, "table-column-properties");
- if(properties) {
- rule += getTableColumnProperties(properties)
- }
- properties = getDirectChild(node, stylens, "table-properties");
- if(properties) {
- rule += getTableProperties(properties)
- }
- if(rule.length === 0) {
- return
++ function PageSwitcher(css) {
++ var sheet = (css.sheet), position = 1;
++ function updateCSS() {
++ while(sheet.cssRules.length > 0) {
++ sheet.deleteRule(0)
++ }
++ sheet.insertRule("#shadowContent draw|page {display:none;}", 0);
++ sheet.insertRule("office|presentation draw|page {display:none;}", 1);
++ sheet.insertRule("#shadowContent draw|page:nth-of-type(" + position + ") {display:block;}", 2);
++ sheet.insertRule("office|presentation draw|page:nth-of-type(" + position + ") {display:block;}", 3)
+ }
- rule = selector + "{" + rule + "}";
- try {
- sheet.insertRule(rule, sheet.cssRules.length)
- }catch(e) {
- throw e;
++ this.showFirstPage = function() {
++ position = 1;
++ updateCSS()
++ };
++ this.showNextPage = function() {
++ position += 1;
++ updateCSS()
++ };
++ this.showPreviousPage = function() {
++ if(position > 1) {
++ position -= 1;
++ updateCSS()
++ }
++ };
++ this.showPage = function(n) {
++ if(n > 0) {
++ position = n;
++ updateCSS()
++ }
++ };
++ this.css = css;
++ this.destroy = function(callback) {
++ css.parentNode.removeChild(css);
++ callback()
+ }
+ }
- function getNumberRule(node) {
- var style = node.getAttributeNS(stylens, "num-format"), suffix = node.getAttributeNS(stylens, "num-suffix"), prefix = node.getAttributeNS(stylens, "num-prefix"), stylemap = {1:"decimal", "a":"lower-latin", "A":"upper-latin", "i":"lower-roman", "I":"upper-roman"}, content = prefix || "";
- if(stylemap.hasOwnProperty(style)) {
- content += " counter(list, " + stylemap[style] + ")"
++ function listenEvent(eventTarget, eventType, eventHandler) {
++ if(eventTarget.addEventListener) {
++ eventTarget.addEventListener(eventType, eventHandler, false)
+ }else {
- if(style) {
- content += "'" + style + "';"
++ if(eventTarget.attachEvent) {
++ eventType = "on" + eventType;
++ eventTarget.attachEvent(eventType, eventHandler)
+ }else {
- content += " ''"
++ eventTarget["on" + eventType] = eventHandler
+ }
+ }
- if(suffix) {
- content += " '" + suffix + "'"
- }
- return"content: " + content + ";"
+ }
- function getImageRule() {
- var rule = "content: none;";
- return rule
++ var drawns = odf.Namespaces.drawns, fons = odf.Namespaces.fons, officens = odf.Namespaces.officens, stylens = odf.Namespaces.stylens, svgns = odf.Namespaces.svgns, tablens = odf.Namespaces.tablens, textns = odf.Namespaces.textns, xlinkns = odf.Namespaces.xlinkns, xmlns = odf.Namespaces.xmlns, presentationns = odf.Namespaces.presentationns, webodfhelperns = "urn:webodf:names:helper", window = runtime.getWindow(), xpath = xmldom.XPath, odfUtils = new odf.OdfUtils, domUtils = new core.DomUtils;
++ function clear(element) {
++ while(element.firstChild) {
++ element.removeChild(element.firstChild)
++ }
+ }
- function getBulletRule(node) {
- var bulletChar = node.getAttributeNS(textns, "bullet-char");
- return"content: '" + bulletChar + "';"
++ function handleStyles(odfcontainer, formatting, stylesxmlcss) {
++ var style2css = new odf.Style2CSS;
++ style2css.style2css(odfcontainer.getDocumentType(), (stylesxmlcss.sheet), formatting.getFontMap(), odfcontainer.rootElement.styles, odfcontainer.rootElement.automaticStyles)
+ }
- function addListStyleRule(sheet, name, node, itemrule) {
- var selector = 'text|list[text|style-name="' + name + '"]', level = node.getAttributeNS(textns, "level"), itemSelector, listItemRule, listLevelProps = utils.getFirstNonWhitespaceChild(node), listLevelLabelAlign = utils.getFirstNonWhitespaceChild(listLevelProps), labelAlignAttr, bulletIndent, listIndent, bulletWidth, rule;
- if(listLevelLabelAlign) {
- labelAlignAttr = listLevelLabelAlign.attributes;
- bulletIndent = labelAlignAttr["fo:text-indent"] ? labelAlignAttr["fo:text-indent"].value : undefined;
- listIndent = labelAlignAttr["fo:margin-left"] ? labelAlignAttr["fo:margin-left"].value : undefined
- }
- if(!bulletIndent) {
- bulletIndent = "-0.6cm"
- }
- if(bulletIndent.charAt(0) === "-") {
- bulletWidth = bulletIndent.substring(1)
- }else {
- bulletWidth = "-" + bulletIndent
- }
- level = level && parseInt(level, 10);
- while(level > 1) {
- selector += " > text|list-item > text|list";
- level -= 1
- }
- itemSelector = selector;
- itemSelector += " > text|list-item > *:not(text|list):first-child";
- if(listIndent !== undefined) {
- listItemRule = itemSelector + "{margin-left:" + listIndent + ";}";
- sheet.insertRule(listItemRule, sheet.cssRules.length)
++ function handleFonts(odfContainer, fontcss) {
++ var fontLoader = new odf.FontLoader;
++ fontLoader.loadFonts(odfContainer, (fontcss.sheet))
++ }
++ function getMasterPageElement(odfContainer, masterPageName) {
++ if(!masterPageName) {
++ return null
+ }
- selector += " > text|list-item > *:not(text|list):first-child:before";
- rule = itemrule;
- rule = selector + "{" + rule + ";";
- rule += "counter-increment:list;";
- rule += "margin-left:" + bulletIndent + ";";
- rule += "width:" + bulletWidth + ";";
- rule += "display:inline-block}";
- try {
- sheet.insertRule(rule, sheet.cssRules.length)
- }catch(e) {
- throw e;
++ var masterStyles = odfContainer.rootElement.masterStyles, masterPageElement = masterStyles.firstElementChild;
++ while(masterPageElement) {
++ if(masterPageElement.getAttributeNS(stylens, "name") === masterPageName && (masterPageElement.localName === "master-page" && masterPageElement.namespaceURI === stylens)) {
++ break
++ }
+ }
++ return masterPageElement
+ }
- function addPageStyleRules(sheet, node) {
- var rule = "", imageProps, url, element, contentLayoutRule = "", pageSizeRule = "", props = node.getElementsByTagNameNS(stylens, "page-layout-properties")[0], masterStyles = props.parentNode.parentNode.parentNode.masterStyles, masterPages, masterStyleName = "", i;
- rule += applySimpleMapping(props, pageContentPropertySimpleMapping);
- imageProps = props.getElementsByTagNameNS(stylens, "background-image");
- if(imageProps.length > 0) {
- url = imageProps.item(0).getAttributeNS(xlinkns, "href");
- if(url) {
- rule += "background-image: url('odfkit:" + url + "');";
- element = (imageProps.item(0));
- rule += applySimpleMapping(element, bgImageSimpleMapping)
++ function dropTemplateDrawFrames(clonedNode) {
++ var i, element, presentationClass, clonedDrawFrameElements = clonedNode.getElementsByTagNameNS(drawns, "frame");
++ for(i = 0;i < clonedDrawFrameElements.length;i += 1) {
++ element = (clonedDrawFrameElements[i]);
++ presentationClass = element.getAttributeNS(presentationns, "class");
++ if(presentationClass && !/^(date-time|footer|header|page-number')$/.test(presentationClass)) {
++ element.parentNode.removeChild(element)
+ }
+ }
- if(documentType === "presentation") {
- if(masterStyles) {
- masterPages = masterStyles.getElementsByTagNameNS(stylens, "master-page");
- for(i = 0;i < masterPages.length;i += 1) {
- if(masterPages[i].getAttributeNS(stylens, "page-layout-name") === props.parentNode.getAttributeNS(stylens, "name")) {
- masterStyleName = masterPages[i].getAttributeNS(stylens, "name");
- contentLayoutRule = "draw|page[draw|master-page-name=" + masterStyleName + "] {" + rule + "}";
- pageSizeRule = "office|body, draw|page[draw|master-page-name=" + masterStyleName + "] {" + applySimpleMapping(props, pageSizePropertySimpleMapping) + " }";
- try {
- sheet.insertRule(contentLayoutRule, sheet.cssRules.length);
- sheet.insertRule(pageSizeRule, sheet.cssRules.length)
- }catch(e1) {
- throw e1;
- }
- }
- }
- }
- }else {
- if(documentType === "text") {
- contentLayoutRule = "office|text {" + rule + "}";
- rule = "";
- pageSizeRule = "office|body {" + "width: " + props.getAttributeNS(fons, "page-width") + ";" + "}";
- try {
- sheet.insertRule(contentLayoutRule, sheet.cssRules.length);
- sheet.insertRule(pageSizeRule, sheet.cssRules.length)
- }catch(e2) {
- throw e2;
++ }
++ function getHeaderFooter(odfContainer, frame, headerFooterId) {
++ var headerFooter = null, i, declElements = odfContainer.rootElement.body.getElementsByTagNameNS(presentationns, headerFooterId + "-decl"), headerFooterName = frame.getAttributeNS(presentationns, "use-" + headerFooterId + "-name"), element;
++ if(headerFooterName && declElements.length > 0) {
++ for(i = 0;i < declElements.length;i += 1) {
++ element = (declElements[i]);
++ if(element.getAttributeNS(presentationns, "name") === headerFooterName) {
++ headerFooter = element.textContent;
++ break
+ }
+ }
+ }
++ return headerFooter
+ }
- function addListStyleRules(sheet, name, node) {
- var n = node.firstChild, e, itemrule;
- while(n) {
- if(n.namespaceURI === textns) {
- e = (n);
- if(n.localName === "list-level-style-number") {
- itemrule = getNumberRule(e);
- addListStyleRule(sheet, name, e, itemrule)
- }else {
- if(n.localName === "list-level-style-image") {
- itemrule = getImageRule();
- addListStyleRule(sheet, name, e, itemrule)
- }else {
- if(n.localName === "list-level-style-bullet") {
- itemrule = getBulletRule(e);
- addListStyleRule(sheet, name, e, itemrule)
- }
- }
- }
++ function setContainerValue(rootElement, ns, localName, value) {
++ var i, containerList, document = rootElement.ownerDocument, e;
++ containerList = rootElement.getElementsByTagNameNS(ns, localName);
++ for(i = 0;i < containerList.length;i += 1) {
++ clear(containerList[i]);
++ if(value) {
++ e = (containerList[i]);
++ e.appendChild(document.createTextNode(value))
+ }
- n = n.nextSibling
+ }
+ }
- function addRule(sheet, family, name, node) {
- if(family === "list") {
- addListStyleRules(sheet, name, node)
++ function setDrawElementPosition(styleid, frame, stylesheet) {
++ frame.setAttributeNS(webodfhelperns, "styleid", styleid);
++ var rule, anchor = frame.getAttributeNS(textns, "anchor-type"), x = frame.getAttributeNS(svgns, "x"), y = frame.getAttributeNS(svgns, "y"), width = frame.getAttributeNS(svgns, "width"), height = frame.getAttributeNS(svgns, "height"), minheight = frame.getAttributeNS(fons, "min-height"), minwidth = frame.getAttributeNS(fons, "min-width");
++ if(anchor === "as-char") {
++ rule = "display: inline-block;"
+ }else {
- if(family === "page") {
- addPageStyleRules(sheet, node)
++ if(anchor || (x || y)) {
++ rule = "position: absolute;"
+ }else {
- addStyleRule(sheet, family, name, node)
++ if(width || (height || (minheight || minwidth))) {
++ rule = "display: block;"
++ }
+ }
+ }
++ if(x) {
++ rule += "left: " + x + ";"
++ }
++ if(y) {
++ rule += "top: " + y + ";"
++ }
++ if(width) {
++ rule += "width: " + width + ";"
++ }
++ if(height) {
++ rule += "height: " + height + ";"
++ }
++ if(minheight) {
++ rule += "min-height: " + minheight + ";"
++ }
++ if(minwidth) {
++ rule += "min-width: " + minwidth + ";"
++ }
++ if(rule) {
++ rule = "draw|" + frame.localName + '[webodfhelper|styleid="' + styleid + '"] {' + rule + "}";
++ stylesheet.insertRule(rule, stylesheet.cssRules.length)
++ }
+ }
- function addRules(sheet, family, name, node) {
- addRule(sheet, family, name, node);
- var n;
- for(n in node.derivedStyles) {
- if(node.derivedStyles.hasOwnProperty(n)) {
- addRules(sheet, family, n, node.derivedStyles[n])
++ function getUrlFromBinaryDataElement(image) {
++ var node = image.firstChild;
++ while(node) {
++ if(node.namespaceURI === officens && node.localName === "binary-data") {
++ return"data:image/png;base64," + node.textContent.replace(/[\r\n\s]/g, "")
+ }
++ node = node.nextSibling
+ }
++ return""
+ }
- this.style2css = function(doctype, stylesheet, fontFaceMap, styles, autostyles) {
- var doc, styletree, tree, name, rule, family, stylenodes, styleautonodes;
- while(stylesheet.cssRules.length) {
- stylesheet.deleteRule(stylesheet.cssRules.length - 1)
- }
- doc = null;
- if(styles) {
- doc = styles.ownerDocument;
- odfRoot = styles.parentNode
- }
- if(autostyles) {
- doc = autostyles.ownerDocument;
- odfRoot = autostyles.parentNode
++ function setImage(id, container, image, stylesheet) {
++ image.setAttributeNS(webodfhelperns, "styleid", id);
++ var url = image.getAttributeNS(xlinkns, "href"), part;
++ function callback(url) {
++ var rule;
++ if(url) {
++ rule = "background-image: url(" + url + ");";
++ rule = 'draw|image[webodfhelper|styleid="' + id + '"] {' + rule + "}";
++ stylesheet.insertRule(rule, stylesheet.cssRules.length)
++ }
+ }
- if(!doc) {
- return
++ function onchange(p) {
++ callback(p.url)
+ }
- odf.Namespaces.forEachPrefix(function(prefix, ns) {
- rule = "@namespace " + prefix + " url(" + ns + ");";
++ if(url) {
+ try {
- stylesheet.insertRule(rule, stylesheet.cssRules.length)
- }catch(ignore) {
++ part = container.getPart(url);
++ part.onchange = onchange;
++ part.load()
++ }catch(e) {
++ runtime.log("slight problem: " + String(e))
+ }
- });
- fontFaceDeclsMap = fontFaceMap;
- documentType = doctype;
- defaultFontSize = runtime.getWindow().getComputedStyle(document.body, null).getPropertyValue("font-size") || "12pt";
- stylenodes = getStyleMap(styles);
- styleautonodes = getStyleMap(autostyles);
- styletree = {};
- for(family in familynamespaceprefixes) {
- if(familynamespaceprefixes.hasOwnProperty(family)) {
- tree = styletree[family] = {};
- addStyleMapToStyleTree(stylenodes[family], tree);
- addStyleMapToStyleTree(styleautonodes[family], tree);
- for(name in tree) {
- if(tree.hasOwnProperty(name)) {
- addRules(stylesheet, family, name, tree[name])
- }
- }
++ }else {
++ url = getUrlFromBinaryDataElement(image);
++ callback(url)
++ }
++ }
++ function formatParagraphAnchors(odfbody) {
++ var n, i, nodes = xpath.getODFElementsWithXPath(odfbody, ".//*[*[@text:anchor-type='paragraph']]", odf.Namespaces.lookupNamespaceURI);
++ for(i = 0;i < nodes.length;i += 1) {
++ n = nodes[i];
++ if(n.setAttributeNS) {
++ n.setAttributeNS(webodfhelperns, "containsparagraphanchor", true)
+ }
+ }
+ }
- };
- /*
-
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- This file is part of WebODF.
-
- WebODF is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License (GNU AGPL)
- as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version.
-
- WebODF is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with WebODF. If not, see <http://www.gnu.org/licenses/>.
- @licend
-
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- runtime.loadClass("odf.Namespaces");
- runtime.loadClass("core.DomUtils");
- odf.MetadataManager = function MetadataManager(metaElement) {
- var domUtils = new core.DomUtils, metadata = {};
- function setMetadata(setProperties, removedProperties) {
- if(setProperties) {
- Object.keys(setProperties).forEach(function(key) {
- metadata[key] = setProperties[key]
- });
- domUtils.mapKeyValObjOntoNode(metaElement, setProperties, odf.Namespaces.resolvePrefix)
++ function modifyTables(odffragment, documentns) {
++ var i, tableCells, node;
++ function modifyTableCell(node) {
++ if(node.hasAttributeNS(tablens, "number-columns-spanned")) {
++ node.setAttributeNS(documentns, "colspan", node.getAttributeNS(tablens, "number-columns-spanned"))
++ }
++ if(node.hasAttributeNS(tablens, "number-rows-spanned")) {
++ node.setAttributeNS(documentns, "rowspan", node.getAttributeNS(tablens, "number-rows-spanned"))
++ }
+ }
- if(removedProperties) {
- removedProperties.forEach(function(name) {
- delete metadata[name]
- });
- domUtils.removeKeyElementsFromNode(metaElement, removedProperties, odf.Namespaces.resolvePrefix)
++ tableCells = odffragment.getElementsByTagNameNS(tablens, "table-cell");
++ for(i = 0;i < tableCells.length;i += 1) {
++ node = (tableCells.item(i));
++ modifyTableCell(node)
+ }
+ }
- this.setMetadata = setMetadata;
- this.incrementEditingCycles = function() {
- var cycles = parseInt(metadata["meta:editing-cycles"] || 0, 10) + 1;
- setMetadata({"meta:editing-cycles":cycles}, null)
- };
- function init() {
- metadata = domUtils.getKeyValRepresentationOfNode(metaElement, odf.Namespaces.lookupPrefix)
- }
- init()
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- runtime.loadClass("core.Base64");
- runtime.loadClass("core.Zip");
- runtime.loadClass("xmldom.LSSerializer");
- runtime.loadClass("odf.StyleInfo");
- runtime.loadClass("odf.Namespaces");
- runtime.loadClass("odf.OdfNodeFilter");
- runtime.loadClass("odf.MetadataManager");
- odf.OdfContainer = function() {
- var styleInfo = new odf.StyleInfo, metadataManager, officens = "urn:oasis:names:tc:opendocument:xmlns:office:1.0", manifestns = "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0", webodfns = "urn:webodf:names:scope", stylens = odf.Namespaces.stylens, nodeorder = ["meta", "settings", "scripts", "font-face-decls", "styles", "automatic-styles", "master-styles", "body"], automaticStylePrefix = (new Date).getTime() + "_webodf_", base64 = new core.Base64, documentStylesScope = "document-s [...]
- "document-content";
- function getDirectChild(node, ns, name) {
- node = node ? node.firstChild : null;
- while(node) {
- if(node.localName === name && node.namespaceURI === ns) {
- return(node)
- }
- node = node.nextSibling
- }
- return null
- }
- function getNodePosition(child) {
- var i, l = nodeorder.length;
- for(i = 0;i < l;i += 1) {
- if(child.namespaceURI === officens && child.localName === nodeorder[i]) {
- return i
++ function modifyLinks(odffragment) {
++ var i, links, node;
++ function modifyLink(node) {
++ var url, clickHandler;
++ if(!node.hasAttributeNS(xlinkns, "href")) {
++ return
+ }
- }
- return-1
- }
- function OdfStylesFilter(styleUsingElementsRoot, automaticStyles) {
- var usedStyleList = new styleInfo.UsedStyleList(styleUsingElementsRoot, automaticStyles), odfNodeFilter = new odf.OdfNodeFilter;
- this.acceptNode = function(node) {
- var result = odfNodeFilter.acceptNode(node);
- if(result === NodeFilter.FILTER_ACCEPT && (node.parentNode === automaticStyles && node.nodeType === Node.ELEMENT_NODE)) {
- if(usedStyleList.uses((node))) {
- result = NodeFilter.FILTER_ACCEPT
- }else {
- result = NodeFilter.FILTER_REJECT
++ url = node.getAttributeNS(xlinkns, "href");
++ if(url[0] === "#") {
++ url = url.substring(1);
++ clickHandler = function() {
++ var bookmarks = xpath.getODFElementsWithXPath(odffragment, "//text:bookmark-start[@text:name='" + url + "']", odf.Namespaces.lookupNamespaceURI);
++ if(bookmarks.length === 0) {
++ bookmarks = xpath.getODFElementsWithXPath(odffragment, "//text:bookmark[@text:name='" + url + "']", odf.Namespaces.lookupNamespaceURI)
++ }
++ if(bookmarks.length > 0) {
++ bookmarks[0].scrollIntoView(true)
++ }
++ return false
++ }
++ }else {
++ clickHandler = function() {
++ window.open(url)
+ }
+ }
- return result
++ node.onclick = clickHandler
++ }
++ links = odffragment.getElementsByTagNameNS(textns, "a");
++ for(i = 0;i < links.length;i += 1) {
++ node = (links.item(i));
++ modifyLink(node)
+ }
+ }
- function OdfContentFilter(styleUsingElementsRoot, automaticStyles) {
- var odfStylesFilter = new OdfStylesFilter(styleUsingElementsRoot, automaticStyles);
- this.acceptNode = function(node) {
- var result = odfStylesFilter.acceptNode(node);
- if(result === NodeFilter.FILTER_ACCEPT && (node.parentNode && (node.parentNode.namespaceURI === odf.Namespaces.textns && (node.parentNode.localName === "s" || node.parentNode.localName === "tab")))) {
- result = NodeFilter.FILTER_REJECT
++ function modifyLineBreakElements(odffragment) {
++ var document = odffragment.ownerDocument, lineBreakElements = domUtils.getElementsByTagNameNS(odffragment, textns, "line-break");
++ lineBreakElements.forEach(function(lineBreak) {
++ if(!lineBreak.hasChildNodes()) {
++ lineBreak.appendChild(document.createElement("br"))
+ }
- return result
- }
++ })
+ }
- function setChild(node, child) {
- if(!child) {
- return
- }
- var childpos = getNodePosition(child), pos, c = node.firstChild;
- if(childpos === -1) {
- return
- }
- while(c) {
- pos = getNodePosition(c);
- if(pos !== -1 && pos > childpos) {
- break
++ function expandSpaceElements(odffragment) {
++ var spaces, doc = odffragment.ownerDocument;
++ function expandSpaceElement(space) {
++ var j, count;
++ while(space.firstChild) {
++ space.removeChild(space.firstChild)
++ }
++ space.appendChild(doc.createTextNode(" "));
++ count = parseInt(space.getAttributeNS(textns, "c"), 10);
++ if(count > 1) {
++ space.removeAttributeNS(textns, "c");
++ for(j = 1;j < count;j += 1) {
++ space.parentNode.insertBefore(space.cloneNode(true), space)
++ }
+ }
- c = c.nextSibling
+ }
- node.insertBefore(child, c)
- }
- function ODFElement() {
++ spaces = domUtils.getElementsByTagNameNS(odffragment, textns, "s");
++ spaces.forEach(expandSpaceElement)
+ }
- function ODFDocumentElement(odfcontainer) {
- this.OdfContainer = odfcontainer
++ function expandTabElements(odffragment) {
++ var tabs;
++ tabs = domUtils.getElementsByTagNameNS(odffragment, textns, "tab");
++ tabs.forEach(function(tab) {
++ tab.textContent = "\t"
++ })
+ }
- ODFDocumentElement.prototype = new ODFElement;
- ODFDocumentElement.prototype.constructor = ODFDocumentElement;
- ODFDocumentElement.namespaceURI = officens;
- ODFDocumentElement.localName = "document";
- function OdfPart(name, mimetype, container, zip) {
- var self = this;
- this.size = 0;
- this.type = null;
- this.name = name;
- this.container = container;
- this.url = null;
- this.mimetype = null;
- this.document = null;
- this.onreadystatechange = null;
- this.onchange = null;
- this.EMPTY = 0;
- this.LOADING = 1;
- this.DONE = 2;
- this.state = this.EMPTY;
- this.load = function() {
- if(zip === null) {
- return
++ function modifyDrawElements(odfbody, stylesheet) {
++ var node, drawElements = [], i;
++ node = odfbody.firstElementChild;
++ while(node && node !== odfbody) {
++ if(node.namespaceURI === drawns) {
++ drawElements[drawElements.length] = node
+ }
- this.mimetype = mimetype;
- zip.loadAsDataURL(name, mimetype, function(err, url) {
- if(err) {
- runtime.log(err)
- }
- self.url = url;
- if(self.onchange) {
- self.onchange(self)
++ if(node.firstElementChild) {
++ node = node.firstElementChild
++ }else {
++ while(node && (node !== odfbody && !node.nextElementSibling)) {
++ node = node.parentElement
+ }
- if(self.onstatereadychange) {
- self.onstatereadychange(self)
++ if(node && node.nextElementSibling) {
++ node = node.nextElementSibling
+ }
- })
++ }
++ }
++ for(i = 0;i < drawElements.length;i += 1) {
++ node = drawElements[i];
++ setDrawElementPosition("frame" + String(i), node, stylesheet)
+ }
++ formatParagraphAnchors(odfbody)
+ }
- OdfPart.prototype.load = function() {
- };
- OdfPart.prototype.getUrl = function() {
- if(this.data) {
- return"data:;base64," + base64.toBase64(this.data)
++ function cloneMasterPages(odfContainer, shadowContent, odfbody, stylesheet) {
++ var masterPageName, masterPageElement, styleId, clonedPageElement, clonedElement, pageNumber = 0, i, element, elementToClone, document = odfContainer.rootElement.ownerDocument;
++ element = odfbody.firstElementChild;
++ if(!(element && (element.namespaceURI === officens && (element.localName === "presentation" || element.localName === "drawing")))) {
++ return
+ }
- return null
- };
- odf.OdfContainer = function OdfContainer(url, onstatereadychange) {
- var self = this, zip, partMimetypes = {}, contentElement;
- this.onstatereadychange = onstatereadychange;
- this.onchange = null;
- this.state = null;
- this.rootElement = null;
- function removeProcessingInstructions(element) {
- var n = element.firstChild, next, e;
- while(n) {
- next = n.nextSibling;
- if(n.nodeType === Node.ELEMENT_NODE) {
- e = (n);
- removeProcessingInstructions(e)
- }else {
- if(n.nodeType === Node.PROCESSING_INSTRUCTION_NODE) {
- element.removeChild(n)
++ element = element.firstElementChild;
++ while(element) {
++ masterPageName = element.getAttributeNS(drawns, "master-page-name");
++ masterPageElement = getMasterPageElement(odfContainer, masterPageName);
++ if(masterPageElement) {
++ styleId = element.getAttributeNS(webodfhelperns, "styleid");
++ clonedPageElement = document.createElementNS(drawns, "draw:page");
++ elementToClone = masterPageElement.firstElementChild;
++ i = 0;
++ while(elementToClone) {
++ if(elementToClone.getAttributeNS(presentationns, "placeholder") !== "true") {
++ clonedElement = (elementToClone.cloneNode(true));
++ clonedPageElement.appendChild(clonedElement);
++ setDrawElementPosition(styleId + "_" + i, clonedElement, stylesheet)
+ }
++ elementToClone = elementToClone.nextElementSibling;
++ i += 1
+ }
- n = next
++ dropTemplateDrawFrames(clonedPageElement);
++ shadowContent.appendChild(clonedPageElement);
++ pageNumber = String(shadowContent.getElementsByTagNameNS(drawns, "page").length);
++ setContainerValue(clonedPageElement, textns, "page-number", pageNumber);
++ setContainerValue(clonedPageElement, presentationns, "header", getHeaderFooter(odfContainer, (element), "header"));
++ setContainerValue(clonedPageElement, presentationns, "footer", getHeaderFooter(odfContainer, (element), "footer"));
++ setDrawElementPosition(styleId, clonedPageElement, stylesheet);
++ clonedPageElement.setAttributeNS(drawns, "draw:master-page-name", masterPageElement.getAttributeNS(stylens, "name"))
+ }
++ element = element.nextElementSibling
+ }
- function setAutomaticStylesScope(stylesRootElement, scope) {
- var n = stylesRootElement && stylesRootElement.firstChild;
- while(n) {
- if(n.nodeType === Node.ELEMENT_NODE) {
- n.setAttributeNS(webodfns, "scope", scope)
++ }
++ function setVideo(container, plugin) {
++ var video, source, url, doc = plugin.ownerDocument, part;
++ url = plugin.getAttributeNS(xlinkns, "href");
++ function callback(url, mimetype) {
++ var ns = doc.documentElement.namespaceURI;
++ if(mimetype.substr(0, 6) === "video/") {
++ video = doc.createElementNS(ns, "video");
++ video.setAttribute("controls", "controls");
++ source = doc.createElementNS(ns, "source");
++ if(url) {
++ source.setAttribute("src", url)
+ }
- n = n.nextSibling
++ source.setAttribute("type", mimetype);
++ video.appendChild(source);
++ plugin.parentNode.appendChild(video)
++ }else {
++ plugin.innerHtml = "Unrecognised Plugin"
+ }
+ }
- function mergeFontFaceDecls(targetFontFaceDeclsRootElement, sourceFontFaceDeclsRootElement) {
- var n, s, fontFaceName, newFontFaceName, targetFontFaceDeclsMap, sourceFontFaceDeclsMap, fontFaceNameChangeMap = {};
- function unusedKey(key, map1, map2) {
- var i = 0, postFixedKey;
- key = key.replace(/\d+$/, "");
- postFixedKey = key;
- while(map1.hasOwnProperty(postFixedKey) || map2.hasOwnProperty(postFixedKey)) {
- i += 1;
- postFixedKey = key + i
- }
- return postFixedKey
++ function onchange(p) {
++ callback(p.url, p.mimetype)
++ }
++ if(url) {
++ try {
++ part = container.getPart(url);
++ part.onchange = onchange;
++ part.load()
++ }catch(e) {
++ runtime.log("slight problem: " + String(e))
+ }
- function mapByFontFaceName(fontFaceDecls) {
- var fn, result = {};
- fn = fontFaceDecls.firstChild;
- while(fn) {
- if(fn.nodeType === Node.ELEMENT_NODE && (fn.namespaceURI === stylens && fn.localName === "font-face")) {
- fontFaceName = fn.getAttributeNS(stylens, "name");
- result[fontFaceName] = fn
- }
- fn = fn.nextSibling
- }
- return result
++ }else {
++ runtime.log("using MP4 data fallback");
++ url = getUrlFromBinaryDataElement(plugin);
++ callback(url, "video/mp4")
++ }
++ }
++ function getNumberRule(node) {
++ var style = node.getAttributeNS(stylens, "num-format"), suffix = node.getAttributeNS(stylens, "num-suffix") || "", prefix = node.getAttributeNS(stylens, "num-prefix") || "", rule = "", stylemap = {1:"decimal", "a":"lower-latin", "A":"upper-latin", "i":"lower-roman", "I":"upper-roman"}, content;
++ content = prefix;
++ if(stylemap.hasOwnProperty(style)) {
++ content += " counter(list, " + stylemap[style] + ")"
++ }else {
++ if(style) {
++ content += "'" + style + "';"
++ }else {
++ content += " ''"
+ }
- targetFontFaceDeclsMap = mapByFontFaceName(targetFontFaceDeclsRootElement);
- sourceFontFaceDeclsMap = mapByFontFaceName(sourceFontFaceDeclsRootElement);
- n = sourceFontFaceDeclsRootElement.firstChild;
- while(n) {
- s = n.nextSibling;
- if(n.nodeType === Node.ELEMENT_NODE && (n.namespaceURI === stylens && n.localName === "font-face")) {
- fontFaceName = n.getAttributeNS(stylens, "name");
- if(targetFontFaceDeclsMap.hasOwnProperty(fontFaceName)) {
- if(!n.isEqualNode(targetFontFaceDeclsMap[fontFaceName])) {
- newFontFaceName = unusedKey(fontFaceName, targetFontFaceDeclsMap, sourceFontFaceDeclsMap);
- n.setAttributeNS(stylens, "style:name", newFontFaceName);
- targetFontFaceDeclsRootElement.appendChild(n);
- targetFontFaceDeclsMap[newFontFaceName] = (n);
- delete sourceFontFaceDeclsMap[fontFaceName];
- fontFaceNameChangeMap[fontFaceName] = newFontFaceName
- }
- }else {
- targetFontFaceDeclsRootElement.appendChild(n);
- targetFontFaceDeclsMap[fontFaceName] = (n);
- delete sourceFontFaceDeclsMap[fontFaceName]
++ }
++ if(suffix) {
++ content += " '" + suffix + "'"
++ }
++ rule = "content: " + content + ";";
++ return rule
++ }
++ function getImageRule() {
++ var rule = "content: none;";
++ return rule
++ }
++ function getBulletRule(node) {
++ var bulletChar = node.getAttributeNS(textns, "bullet-char");
++ return"content: '" + bulletChar + "';"
++ }
++ function getBulletsRule(node) {
++ var itemrule;
++ if(node) {
++ if(node.localName === "list-level-style-number") {
++ itemrule = getNumberRule(node)
++ }else {
++ if(node.localName === "list-level-style-image") {
++ itemrule = getImageRule()
++ }else {
++ if(node.localName === "list-level-style-bullet") {
++ itemrule = getBulletRule(node)
+ }
+ }
- n = s
+ }
- return fontFaceNameChangeMap
+ }
- function cloneStylesInScope(stylesRootElement, scope) {
- var copy = null, n, s, scopeAttrValue;
- if(stylesRootElement) {
- copy = stylesRootElement.cloneNode(true);
- n = copy.firstChild;
- while(n) {
- s = n.nextSibling;
- if(n.nodeType === Node.ELEMENT_NODE) {
- scopeAttrValue = n.getAttributeNS(webodfns, "scope");
- if(scopeAttrValue && scopeAttrValue !== scope) {
- copy.removeChild(n)
- }
- }
- n = s
- }
++ return itemrule
++ }
++ function loadLists(odffragment, stylesheet, documentns) {
++ var i, lists, node, id, continueList, styleName, rule, listMap = {}, parentList, listStyles, listStyleMap = {}, bulletRule;
++ listStyles = window.document.getElementsByTagNameNS(textns, "list-style");
++ for(i = 0;i < listStyles.length;i += 1) {
++ node = (listStyles.item(i));
++ styleName = node.getAttributeNS(stylens, "name");
++ if(styleName) {
++ listStyleMap[styleName] = node
+ }
- return copy
+ }
- function cloneFontFaceDeclsUsedInStyles(fontFaceDeclsRootElement, stylesRootElementList) {
- var copy = null, n, nextSibling, fontFaceName, usedFontFaceDeclMap = {};
- if(fontFaceDeclsRootElement) {
- stylesRootElementList.forEach(function(stylesRootElement) {
- styleInfo.collectUsedFontFaces(usedFontFaceDeclMap, stylesRootElement)
- });
- copy = fontFaceDeclsRootElement.cloneNode(true);
- n = copy.firstChild;
- while(n) {
- nextSibling = n.nextSibling;
- if(n.nodeType === Node.ELEMENT_NODE) {
- fontFaceName = n.getAttributeNS(stylens, "name");
- if(!usedFontFaceDeclMap[fontFaceName]) {
- copy.removeChild(n)
- }
++ lists = odffragment.getElementsByTagNameNS(textns, "list");
++ for(i = 0;i < lists.length;i += 1) {
++ node = (lists.item(i));
++ id = node.getAttributeNS(xmlns, "id");
++ if(id) {
++ continueList = node.getAttributeNS(textns, "continue-list");
++ node.setAttributeNS(documentns, "id", id);
++ rule = "text|list#" + id + " > text|list-item > *:first-child:before {";
++ styleName = node.getAttributeNS(textns, "style-name");
++ if(styleName) {
++ node = listStyleMap[styleName];
++ bulletRule = getBulletsRule((odfUtils.getFirstNonWhitespaceChild(node)))
++ }
++ if(continueList) {
++ parentList = listMap[continueList];
++ while(parentList) {
++ parentList = listMap[parentList]
++ }
++ rule += "counter-increment:" + continueList + ";";
++ if(bulletRule) {
++ bulletRule = bulletRule.replace("list", continueList);
++ rule += bulletRule
++ }else {
++ rule += "content:counter(" + continueList + ");"
++ }
++ }else {
++ continueList = "";
++ if(bulletRule) {
++ bulletRule = bulletRule.replace("list", id);
++ rule += bulletRule
++ }else {
++ rule += "content: counter(" + id + ");"
+ }
- n = nextSibling
++ rule += "counter-increment:" + id + ";";
++ stylesheet.insertRule("text|list#" + id + " {counter-reset:" + id + "}", stylesheet.cssRules.length)
++ }
++ rule += "}";
++ listMap[id] = continueList;
++ if(rule) {
++ stylesheet.insertRule(rule, stylesheet.cssRules.length)
+ }
+ }
- return copy
- }
- function initializeMetadataManager(metaRootElement) {
- metadataManager = new odf.MetadataManager(metaRootElement)
+ }
- function importRootNode(xmldoc) {
- var doc = self.rootElement.ownerDocument, node;
- if(xmldoc) {
- removeProcessingInstructions(xmldoc.documentElement);
- try {
- node = doc.importNode(xmldoc.documentElement, true)
- }catch(ignore) {
- }
++ }
++ function addWebODFStyleSheet(document) {
++ var head = (document.getElementsByTagName("head")[0]), style, href;
++ if(String(typeof webodf_css) !== "undefined") {
++ style = document.createElementNS(head.namespaceURI, "style");
++ style.setAttribute("media", "screen, print, handheld, projection");
++ style.appendChild(document.createTextNode(webodf_css))
++ }else {
++ style = document.createElementNS(head.namespaceURI, "link");
++ href = "webodf.css";
++ if(runtime.currentDirectory) {
++ href = runtime.currentDirectory() + "/../" + href
+ }
- return node
++ style.setAttribute("href", href);
++ style.setAttribute("rel", "stylesheet")
+ }
- function setState(state) {
- self.state = state;
- if(self.onchange) {
- self.onchange(self)
++ style.setAttribute("type", "text/css");
++ head.appendChild(style);
++ return(style)
++ }
++ function addStyleSheet(document) {
++ var head = (document.getElementsByTagName("head")[0]), style = document.createElementNS(head.namespaceURI, "style"), text = "";
++ style.setAttribute("type", "text/css");
++ style.setAttribute("media", "screen, print, handheld, projection");
++ odf.Namespaces.forEachPrefix(function(prefix, ns) {
++ text += "@namespace " + prefix + " url(" + ns + ");\n"
++ });
++ text += "@namespace webodfhelper url(" + webodfhelperns + ");\n";
++ style.appendChild(document.createTextNode(text));
++ head.appendChild(style);
++ return(style)
++ }
++ odf.OdfCanvas = function OdfCanvas(element) {
++ runtime.assert(element !== null && element !== undefined, "odf.OdfCanvas constructor needs DOM element");
++ runtime.assert(element.ownerDocument !== null && element.ownerDocument !== undefined, "odf.OdfCanvas constructor needs DOM");
++ var self = this, doc = (element.ownerDocument), odfcontainer, formatting = new odf.Formatting, pageSwitcher, sizer = null, annotationsPane = null, allowAnnotations = false, annotationViewManager = null, webodfcss, fontcss, stylesxmlcss, positioncss, shadowContent, zoomLevel = 1, eventHandlers = {}, loadingQueue = new LoadingQueue;
++ function loadImages(container, odffragment, stylesheet) {
++ var i, images, node;
++ function loadImage(name, container, node, stylesheet) {
++ loadingQueue.addToQueue(function() {
++ setImage(name, container, node, stylesheet)
++ })
+ }
- if(self.onstatereadychange) {
- self.onstatereadychange(self)
++ images = odffragment.getElementsByTagNameNS(drawns, "image");
++ for(i = 0;i < images.length;i += 1) {
++ node = (images.item(i));
++ loadImage("image" + String(i), container, node, stylesheet)
+ }
+ }
- function setRootElement(root) {
- contentElement = null;
- self.rootElement = root;
- root.fontFaceDecls = getDirectChild(root, officens, "font-face-decls");
- root.styles = getDirectChild(root, officens, "styles");
- root.automaticStyles = getDirectChild(root, officens, "automatic-styles");
- root.masterStyles = getDirectChild(root, officens, "master-styles");
- root.body = getDirectChild(root, officens, "body");
- root.meta = getDirectChild(root, officens, "meta")
++ function loadVideos(container, odffragment) {
++ var i, plugins, node;
++ function loadVideo(container, node) {
++ loadingQueue.addToQueue(function() {
++ setVideo(container, node)
++ })
++ }
++ plugins = odffragment.getElementsByTagNameNS(drawns, "plugin");
++ for(i = 0;i < plugins.length;i += 1) {
++ node = (plugins.item(i));
++ loadVideo(container, node)
++ }
+ }
- function handleFlatXml(xmldoc) {
- var root = importRootNode(xmldoc);
- if(!root || (root.localName !== "document" || root.namespaceURI !== officens)) {
- setState(OdfContainer.INVALID);
- return
++ function addEventListener(eventType, eventHandler) {
++ var handlers;
++ if(eventHandlers.hasOwnProperty(eventType)) {
++ handlers = eventHandlers[eventType]
++ }else {
++ handlers = eventHandlers[eventType] = []
++ }
++ if(eventHandler && handlers.indexOf(eventHandler) === -1) {
++ handlers.push(eventHandler)
+ }
- setRootElement((root));
- setState(OdfContainer.DONE)
+ }
- function handleStylesXml(xmldoc) {
- var node = importRootNode(xmldoc), root = self.rootElement;
- if(!node || (node.localName !== "document-styles" || node.namespaceURI !== officens)) {
- setState(OdfContainer.INVALID);
++ function fireEvent(eventType, args) {
++ if(!eventHandlers.hasOwnProperty(eventType)) {
+ return
+ }
- root.fontFaceDecls = getDirectChild(node, officens, "font-face-decls");
- setChild(root, root.fontFaceDecls);
- root.styles = getDirectChild(node, officens, "styles");
- setChild(root, root.styles);
- root.automaticStyles = getDirectChild(node, officens, "automatic-styles");
- setAutomaticStylesScope(root.automaticStyles, documentStylesScope);
- setChild(root, root.automaticStyles);
- root.masterStyles = getDirectChild(node, officens, "master-styles");
- setChild(root, root.masterStyles);
- styleInfo.prefixStyleNames(root.automaticStyles, automaticStylePrefix, root.masterStyles)
++ var handlers = eventHandlers[eventType], i;
++ for(i = 0;i < handlers.length;i += 1) {
++ handlers[i].apply(null, args)
++ }
+ }
- function handleContentXml(xmldoc) {
- var node = importRootNode(xmldoc), root, automaticStyles, fontFaceDecls, fontFaceNameChangeMap, c;
- if(!node || (node.localName !== "document-content" || node.namespaceURI !== officens)) {
- setState(OdfContainer.INVALID);
++ function fixContainerSize() {
++ var odfdoc = sizer.firstChild;
++ if(!odfdoc) {
+ return
+ }
- root = self.rootElement;
- fontFaceDecls = getDirectChild(node, officens, "font-face-decls");
- if(root.fontFaceDecls && fontFaceDecls) {
- fontFaceNameChangeMap = mergeFontFaceDecls(root.fontFaceDecls, fontFaceDecls)
++ if(zoomLevel > 1) {
++ sizer.style.MozTransformOrigin = "center top";
++ sizer.style.WebkitTransformOrigin = "center top";
++ sizer.style.OTransformOrigin = "center top";
++ sizer.style.msTransformOrigin = "center top"
+ }else {
- if(fontFaceDecls) {
- root.fontFaceDecls = fontFaceDecls;
- setChild(root, fontFaceDecls)
- }
- }
- automaticStyles = getDirectChild(node, officens, "automatic-styles");
- setAutomaticStylesScope(automaticStyles, documentContentScope);
- if(fontFaceNameChangeMap) {
- styleInfo.changeFontFaceNames(automaticStyles, fontFaceNameChangeMap)
- }
- if(root.automaticStyles && automaticStyles) {
- c = automaticStyles.firstChild;
- while(c) {
- root.automaticStyles.appendChild(c);
- c = automaticStyles.firstChild
- }
- }else {
- if(automaticStyles) {
- root.automaticStyles = automaticStyles;
- setChild(root, automaticStyles)
- }
- }
- root.body = getDirectChild(node, officens, "body");
- setChild(root, root.body)
- }
- function handleMetaXml(xmldoc) {
- var node = importRootNode(xmldoc), root;
- if(!node || (node.localName !== "document-meta" || node.namespaceURI !== officens)) {
- return
++ sizer.style.MozTransformOrigin = "left top";
++ sizer.style.WebkitTransformOrigin = "left top";
++ sizer.style.OTransformOrigin = "left top";
++ sizer.style.msTransformOrigin = "left top"
+ }
- root = self.rootElement;
- root.meta = getDirectChild(node, officens, "meta");
- setChild(root, root.meta);
- initializeMetadataManager(root.meta)
++ sizer.style.WebkitTransform = "scale(" + zoomLevel + ")";
++ sizer.style.MozTransform = "scale(" + zoomLevel + ")";
++ sizer.style.OTransform = "scale(" + zoomLevel + ")";
++ sizer.style.msTransform = "scale(" + zoomLevel + ")";
++ element.style.width = Math.round(zoomLevel * sizer.offsetWidth) + "px";
++ element.style.height = Math.round(zoomLevel * sizer.offsetHeight) + "px"
+ }
- function handleSettingsXml(xmldoc) {
- var node = importRootNode(xmldoc), root;
- if(!node || (node.localName !== "document-settings" || node.namespaceURI !== officens)) {
- return
- }
- root = self.rootElement;
- root.settings = getDirectChild(node, officens, "settings");
- setChild(root, root.settings)
++ function handleContent(container, odfnode) {
++ var css = (positioncss.sheet);
++ clear(element);
++ sizer = (doc.createElementNS(element.namespaceURI, "div"));
++ sizer.style.display = "inline-block";
++ sizer.style.background = "white";
++ sizer.appendChild(odfnode);
++ element.appendChild(sizer);
++ annotationsPane = (doc.createElementNS(element.namespaceURI, "div"));
++ annotationsPane.id = "annotationsPane";
++ shadowContent = doc.createElementNS(element.namespaceURI, "div");
++ shadowContent.id = "shadowContent";
++ shadowContent.style.position = "absolute";
++ shadowContent.style.top = 0;
++ shadowContent.style.left = 0;
++ container.getContentElement().appendChild(shadowContent);
++ modifyDrawElements(odfnode.body, css);
++ cloneMasterPages(container, shadowContent, odfnode.body, css);
++ modifyTables(odfnode.body, element.namespaceURI);
++ modifyLinks(odfnode.body);
++ modifyLineBreakElements(odfnode.body);
++ expandSpaceElements(odfnode.body);
++ expandTabElements(odfnode.body);
++ loadImages(container, odfnode.body, css);
++ loadVideos(container, odfnode.body);
++ loadLists(odfnode.body, css, element.namespaceURI);
++ sizer.insertBefore(shadowContent, sizer.firstChild);
++ fixContainerSize()
+ }
- function handleManifestXml(xmldoc) {
- var node = importRootNode(xmldoc), root, n;
- if(!node || (node.localName !== "manifest" || node.namespaceURI !== manifestns)) {
- return
++ function modifyAnnotations(odffragment) {
++ var annotationNodes = domUtils.getElementsByTagNameNS(odffragment, officens, "annotation"), annotationEnds = domUtils.getElementsByTagNameNS(odffragment, officens, "annotation-end"), currentAnnotationName, i;
++ function matchAnnotationEnd(element) {
++ return currentAnnotationName === element.getAttributeNS(officens, "name")
+ }
- root = self.rootElement;
- root.manifest = node;
- n = root.manifest.firstChild;
- while(n) {
- if(n.nodeType === Node.ELEMENT_NODE && (n.localName === "file-entry" && n.namespaceURI === manifestns)) {
- partMimetypes[n.getAttributeNS(manifestns, "full-path")] = n.getAttributeNS(manifestns, "media-type")
- }
- n = n.nextSibling
++ for(i = 0;i < annotationNodes.length;i += 1) {
++ currentAnnotationName = annotationNodes[i].getAttributeNS(officens, "name");
++ annotationViewManager.addAnnotation({node:annotationNodes[i], end:annotationEnds.filter(matchAnnotationEnd)[0] || null})
+ }
++ annotationViewManager.rerenderAnnotations()
+ }
- function loadNextComponent(remainingComponents) {
- var component = remainingComponents.shift(), filepath, callback;
- if(component) {
- filepath = (component[0]);
- callback = (component[1]);
- zip.loadAsDOM(filepath, function(err, xmldoc) {
- callback(xmldoc);
- if(err || self.state === OdfContainer.INVALID) {
- return
- }
- loadNextComponent(remainingComponents)
- })
++ function handleAnnotations(odfnode) {
++ if(allowAnnotations) {
++ if(!annotationsPane.parentNode) {
++ sizer.appendChild(annotationsPane);
++ fixContainerSize()
++ }
++ if(annotationViewManager) {
++ annotationViewManager.forgetAnnotations()
++ }
++ annotationViewManager = new gui.AnnotationViewManager(self, odfnode.body, annotationsPane);
++ modifyAnnotations(odfnode.body)
+ }else {
- setState(OdfContainer.DONE)
- }
- }
- function loadComponents() {
- var componentOrder = [["styles.xml", handleStylesXml], ["content.xml", handleContentXml], ["meta.xml", handleMetaXml], ["settings.xml", handleSettingsXml], ["META-INF/manifest.xml", handleManifestXml]];
- loadNextComponent(componentOrder)
- }
- function createDocumentElement(name) {
- var s = "";
- odf.Namespaces.forEachPrefix(function(prefix, ns) {
- s += " xmlns:" + prefix + '="' + ns + '"'
- });
- return'<?xml version="1.0" encoding="UTF-8"?><office:' + name + " " + s + ' office:version="1.2">'
- }
- function serializeMetaXml() {
- var serializer = new xmldom.LSSerializer, s = createDocumentElement("document-meta");
- serializer.filter = new odf.OdfNodeFilter;
- s += serializer.writeToString(self.rootElement.meta, odf.Namespaces.namespaceMap);
- s += "</office:document-meta>";
- return s
- }
- function createManifestEntry(fullPath, mediaType) {
- var element = document.createElementNS(manifestns, "manifest:file-entry");
- element.setAttributeNS(manifestns, "manifest:full-path", fullPath);
- element.setAttributeNS(manifestns, "manifest:media-type", mediaType);
- return element
- }
- function serializeManifestXml() {
- var header = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n', xml = '<manifest:manifest xmlns:manifest="' + manifestns + '" manifest:version="1.2"></manifest:manifest>', manifest = (runtime.parseXML(xml)), manifestRoot = getDirectChild(manifest, manifestns, "manifest"), serializer = new xmldom.LSSerializer, fullPath;
- for(fullPath in partMimetypes) {
- if(partMimetypes.hasOwnProperty(fullPath)) {
- manifestRoot.appendChild(createManifestEntry(fullPath, partMimetypes[fullPath]))
++ if(annotationsPane.parentNode) {
++ sizer.removeChild(annotationsPane);
++ annotationViewManager.forgetAnnotations();
++ fixContainerSize()
+ }
+ }
- serializer.filter = new odf.OdfNodeFilter;
- return header + serializer.writeToString(manifest, odf.Namespaces.namespaceMap)
- }
- function serializeSettingsXml() {
- var serializer = new xmldom.LSSerializer, s = createDocumentElement("document-settings");
- serializer.filter = new odf.OdfNodeFilter;
- s += serializer.writeToString(self.rootElement.settings, odf.Namespaces.namespaceMap);
- s += "</office:document-settings>";
- return s
- }
- function serializeStylesXml() {
- var nsmap = odf.Namespaces.namespaceMap, serializer = new xmldom.LSSerializer, fontFaceDecls, automaticStyles, masterStyles, s = createDocumentElement("document-styles");
- automaticStyles = cloneStylesInScope(self.rootElement.automaticStyles, documentStylesScope);
- masterStyles = self.rootElement.masterStyles && self.rootElement.masterStyles.cloneNode(true);
- fontFaceDecls = cloneFontFaceDeclsUsedInStyles(self.rootElement.fontFaceDecls, [masterStyles, self.rootElement.styles, automaticStyles]);
- styleInfo.removePrefixFromStyleNames(automaticStyles, automaticStylePrefix, masterStyles);
- serializer.filter = new OdfStylesFilter(masterStyles, automaticStyles);
- s += serializer.writeToString(fontFaceDecls, nsmap);
- s += serializer.writeToString(self.rootElement.styles, nsmap);
- s += serializer.writeToString(automaticStyles, nsmap);
- s += serializer.writeToString(masterStyles, nsmap);
- s += "</office:document-styles>";
- return s
- }
- function serializeContentXml() {
- var nsmap = odf.Namespaces.namespaceMap, serializer = new xmldom.LSSerializer, fontFaceDecls, automaticStyles, s = createDocumentElement("document-content");
- automaticStyles = cloneStylesInScope(self.rootElement.automaticStyles, documentContentScope);
- fontFaceDecls = cloneFontFaceDeclsUsedInStyles(self.rootElement.fontFaceDecls, [automaticStyles]);
- serializer.filter = new OdfContentFilter(self.rootElement.body, automaticStyles);
- s += serializer.writeToString(fontFaceDecls, nsmap);
- s += serializer.writeToString(automaticStyles, nsmap);
- s += serializer.writeToString(self.rootElement.body, nsmap);
- s += "</office:document-content>";
- return s
+ }
- function createElement(Type) {
- var original = document.createElementNS(Type.namespaceURI, Type.localName), method, iface = new Type;
- for(method in iface) {
- if(iface.hasOwnProperty(method)) {
- original[method] = iface[method]
++ function refreshOdf(suppressEvent) {
++ function callback() {
++ clear(element);
++ element.style.display = "inline-block";
++ var odfnode = odfcontainer.rootElement;
++ element.ownerDocument.importNode(odfnode, true);
++ formatting.setOdfContainer(odfcontainer);
++ handleFonts(odfcontainer, fontcss);
++ handleStyles(odfcontainer, formatting, stylesxmlcss);
++ handleContent(odfcontainer, odfnode);
++ handleAnnotations(odfnode);
++ if(!suppressEvent) {
++ fireEvent("statereadychange", [odfcontainer])
+ }
+ }
- return original
++ if(odfcontainer.state === odf.OdfContainer.DONE) {
++ callback()
++ }else {
++ runtime.log("WARNING: refreshOdf called but ODF was not DONE.");
++ runtime.setTimeout(function later_cb() {
++ if(odfcontainer.state === odf.OdfContainer.DONE) {
++ callback()
++ }else {
++ runtime.log("will be back later...");
++ runtime.setTimeout(later_cb, 500)
++ }
++ }, 100)
++ }
+ }
- function loadFromXML(url, callback) {
- runtime.loadXML(url, function(err, dom) {
- if(err) {
- callback(err)
- }else {
- handleFlatXml(dom)
- }
++ this.refreshCSS = function() {
++ handleStyles(odfcontainer, formatting, stylesxmlcss);
++ fixContainerSize()
++ };
++ this.refreshSize = function() {
++ fixContainerSize()
++ };
++ this.odfContainer = function() {
++ return odfcontainer
++ };
++ this.setOdfContainer = function(container, suppressEvent) {
++ odfcontainer = container;
++ refreshOdf(suppressEvent === true)
++ };
++ function load(url) {
++ loadingQueue.clearQueue();
++ element.innerHTML = runtime.tr("Loading") + " " + url + "...";
++ element.removeAttribute("style");
++ odfcontainer = new odf.OdfContainer(url, function(container) {
++ odfcontainer = container;
++ refreshOdf(false)
+ })
+ }
- this.setRootElement = setRootElement;
- this.getContentElement = function() {
- var body;
- if(!contentElement) {
- body = self.rootElement.body;
- contentElement = body.getElementsByTagNameNS(officens, "text")[0] || (body.getElementsByTagNameNS(officens, "presentation")[0] || body.getElementsByTagNameNS(officens, "spreadsheet")[0])
++ this["load"] = load;
++ this.load = load;
++ this.save = function(callback) {
++ odfcontainer.save(callback)
++ };
++ this.addListener = function(eventName, handler) {
++ switch(eventName) {
++ case "click":
++ listenEvent(element, eventName, handler);
++ break;
++ default:
++ addEventListener(eventName, handler);
++ break
+ }
- return contentElement
+ };
- this.getDocumentType = function() {
- var content = self.getContentElement();
- return content && content.localName
++ this.getFormatting = function() {
++ return formatting
+ };
- this.getMetadataManager = function() {
- return metadataManager
++ this.getAnnotationViewManager = function() {
++ return annotationViewManager
+ };
- this.getPart = function(partname) {
- return new OdfPart(partname, partMimetypes[partname], self, zip)
++ this.refreshAnnotations = function() {
++ handleAnnotations(odfcontainer.rootElement)
+ };
- this.getPartData = function(url, callback) {
- zip.load(url, callback)
- };
- function updateMetadataForSaving() {
- var generatorString, window = runtime.getWindow();
- generatorString = "WebODF/" + (String(typeof webodf_version) !== "undefined" ? webodf_version : "FromSource");
- if(window) {
- generatorString = generatorString + " " + window.navigator.userAgent
++ this.rerenderAnnotations = function() {
++ if(annotationViewManager) {
++ annotationViewManager.rerenderAnnotations()
+ }
- metadataManager.setMetadata({"meta:generator":generatorString})
- }
- function createEmptyTextDocument() {
- var emptyzip = new core.Zip("", null), data = runtime.byteArrayFromString("application/vnd.oasis.opendocument.text", "utf8"), root = self.rootElement, text = document.createElementNS(officens, "text");
- emptyzip.save("mimetype", data, false, new Date);
- function addToplevelElement(memberName, realLocalName) {
- var element;
- if(!realLocalName) {
- realLocalName = memberName
++ };
++ this.getSizer = function() {
++ return sizer
++ };
++ this.enableAnnotations = function(allow) {
++ if(allow !== allowAnnotations) {
++ allowAnnotations = allow;
++ if(odfcontainer) {
++ handleAnnotations(odfcontainer.rootElement)
+ }
- element = document.createElementNS(officens, realLocalName);
- root[memberName] = element;
- root.appendChild(element)
+ }
- addToplevelElement("meta");
- addToplevelElement("settings");
- addToplevelElement("scripts");
- addToplevelElement("fontFaceDecls", "font-face-decls");
- addToplevelElement("styles");
- addToplevelElement("automaticStyles", "automatic-styles");
- addToplevelElement("masterStyles", "master-styles");
- addToplevelElement("body");
- root.body.appendChild(text);
- initializeMetadataManager(root.meta);
- setState(OdfContainer.DONE);
- return emptyzip
- }
- function fillZip() {
- var data, date = new Date;
- updateMetadataForSaving();
- data = runtime.byteArrayFromString(serializeSettingsXml(), "utf8");
- zip.save("settings.xml", data, true, date);
- data = runtime.byteArrayFromString(serializeMetaXml(), "utf8");
- zip.save("meta.xml", data, true, date);
- data = runtime.byteArrayFromString(serializeStylesXml(), "utf8");
- zip.save("styles.xml", data, true, date);
- data = runtime.byteArrayFromString(serializeContentXml(), "utf8");
- zip.save("content.xml", data, true, date);
- data = runtime.byteArrayFromString(serializeManifestXml(), "utf8");
- zip.save("META-INF/manifest.xml", data, true, date)
- }
- function createByteArray(successCallback, errorCallback) {
- fillZip();
- zip.createByteArray(successCallback, errorCallback)
- }
- this.createByteArray = createByteArray;
- function saveAs(newurl, callback) {
- fillZip();
- zip.writeAs(newurl, function(err) {
- callback(err)
- })
- }
- this.saveAs = saveAs;
- this.save = function(callback) {
- saveAs(url, callback)
+ };
- this.getUrl = function() {
- return url
++ this.addAnnotation = function(annotation) {
++ if(annotationViewManager) {
++ annotationViewManager.addAnnotation(annotation)
++ }
+ };
- this.setBlob = function(filename, mimetype, content) {
- var data = base64.convertBase64ToByteArray(content), date = new Date;
- zip.save(filename, data, false, date);
- if(partMimetypes.hasOwnProperty(filename)) {
- runtime.log(filename + " has been overwritten.")
++ this.forgetAnnotations = function() {
++ if(annotationViewManager) {
++ annotationViewManager.forgetAnnotations()
+ }
- partMimetypes[filename] = mimetype
+ };
- this.removeBlob = function(filename) {
- var foundAndRemoved = zip.remove(filename);
- runtime.assert(foundAndRemoved, "file is not found: " + filename);
- delete partMimetypes[filename]
++ this.setZoomLevel = function(zoom) {
++ zoomLevel = zoom;
++ fixContainerSize()
+ };
- this.state = OdfContainer.LOADING;
- this.rootElement = createElement(ODFDocumentElement);
- if(url) {
- zip = new core.Zip(url, function(err, zipobject) {
- zip = zipobject;
- if(err) {
- loadFromXML(url, function(xmlerr) {
- if(err) {
- zip.error = err + "\n" + xmlerr;
- setState(OdfContainer.INVALID)
- }
- })
- }else {
- loadComponents()
++ this.getZoomLevel = function() {
++ return zoomLevel
++ };
++ this.fitToContainingElement = function(width, height) {
++ var realWidth = element.offsetWidth / zoomLevel, realHeight = element.offsetHeight / zoomLevel;
++ zoomLevel = width / realWidth;
++ if(height / realHeight < zoomLevel) {
++ zoomLevel = height / realHeight
++ }
++ fixContainerSize()
++ };
++ this.fitToWidth = function(width) {
++ var realWidth = element.offsetWidth / zoomLevel;
++ zoomLevel = width / realWidth;
++ fixContainerSize()
++ };
++ this.fitSmart = function(width, height) {
++ var realWidth, realHeight, newScale;
++ realWidth = element.offsetWidth / zoomLevel;
++ realHeight = element.offsetHeight / zoomLevel;
++ newScale = width / realWidth;
++ if(height !== undefined) {
++ if(height / realHeight < newScale) {
++ newScale = height / realHeight
+ }
- })
- }else {
- zip = createEmptyTextDocument()
++ }
++ zoomLevel = Math.min(1, newScale);
++ fixContainerSize()
++ };
++ this.fitToHeight = function(height) {
++ var realHeight = element.offsetHeight / zoomLevel;
++ zoomLevel = height / realHeight;
++ fixContainerSize()
++ };
++ this.showFirstPage = function() {
++ pageSwitcher.showFirstPage()
++ };
++ this.showNextPage = function() {
++ pageSwitcher.showNextPage()
++ };
++ this.showPreviousPage = function() {
++ pageSwitcher.showPreviousPage()
++ };
++ this.showPage = function(n) {
++ pageSwitcher.showPage(n);
++ fixContainerSize()
++ };
++ this.getElement = function() {
++ return element
++ };
++ this.addCssForFrameWithImage = function(frame) {
++ var frameName = frame.getAttributeNS(drawns, "name"), fc = frame.firstElementChild;
++ setDrawElementPosition(frameName, frame, (positioncss.sheet));
++ if(fc) {
++ setImage(frameName + "img", odfcontainer, fc, (positioncss.sheet))
++ }
++ };
++ this.destroy = function(callback) {
++ var head = (doc.getElementsByTagName("head")[0]);
++ if(annotationsPane && annotationsPane.parentNode) {
++ annotationsPane.parentNode.removeChild(annotationsPane)
++ }
++ if(sizer) {
++ element.removeChild(sizer);
++ sizer = null
++ }
++ head.removeChild(webodfcss);
++ head.removeChild(fontcss);
++ head.removeChild(stylesxmlcss);
++ head.removeChild(positioncss);
++ pageSwitcher.destroy(callback)
++ };
++ function init() {
++ webodfcss = addWebODFStyleSheet(doc);
++ pageSwitcher = new PageSwitcher(addStyleSheet(doc));
++ fontcss = addStyleSheet(doc);
++ stylesxmlcss = addStyleSheet(doc);
++ positioncss = addStyleSheet(doc)
+ }
- };
- odf.OdfContainer.EMPTY = 0;
- odf.OdfContainer.LOADING = 1;
- odf.OdfContainer.DONE = 2;
- odf.OdfContainer.INVALID = 3;
- odf.OdfContainer.SAVING = 4;
- odf.OdfContainer.MODIFIED = 5;
- odf.OdfContainer.getContainer = function(url) {
- return new odf.OdfContainer(url, null)
- };
- return odf.OdfContainer
- }();
++ init()
++ }
++})();
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.Base64");
- runtime.loadClass("xmldom.XPath");
- runtime.loadClass("odf.OdfContainer");
- odf.FontLoader = function() {
- var xpath = new xmldom.XPath, base64 = new core.Base64;
- function getEmbeddedFontDeclarations(fontFaceDecls) {
- var decls = {}, fonts, i, font, name, uris, href, family;
- if(!fontFaceDecls) {
- return decls
- }
- fonts = xpath.getODFElementsWithXPath(fontFaceDecls, "style:font-face[svg:font-face-src]", odf.Namespaces.resolvePrefix);
- for(i = 0;i < fonts.length;i += 1) {
- font = fonts[i];
- name = font.getAttributeNS(odf.Namespaces.stylens, "name");
- family = font.getAttributeNS(odf.Namespaces.svgns, "font-family");
- uris = xpath.getODFElementsWithXPath(font, "svg:font-face-src/svg:font-face-uri", odf.Namespaces.resolvePrefix);
- if(uris.length > 0) {
- href = uris[0].getAttributeNS(odf.Namespaces.xlinkns, "href");
- decls[name] = {href:href, family:family}
++runtime.loadClass("core.DomUtils");
++runtime.loadClass("odf.Namespaces");
++runtime.loadClass("odf.OdfUtils");
++gui.StyleHelper = function StyleHelper(formatting) {
++ var domUtils = new core.DomUtils, odfUtils = new odf.OdfUtils, textns = odf.Namespaces.textns;
++ function getAppliedStyles(range) {
++ var container, nodes;
++ if(range.collapsed) {
++ container = range.startContainer;
++ if(container.hasChildNodes() && range.startOffset < container.childNodes.length) {
++ container = container.childNodes.item(range.startOffset)
+ }
++ nodes = [container]
++ }else {
++ nodes = odfUtils.getTextNodes(range, true)
+ }
- return decls
- }
- function addFontToCSS(name, font, fontdata, stylesheet) {
- var cssFamily = font.family || name, rule = "@font-face { font-family: '" + cssFamily + "'; src: " + "url(data:application/x-font-ttf;charset=binary;base64," + base64.convertUTF8ArrayToBase64(fontdata) + ') format("truetype"); }';
- try {
- stylesheet.insertRule(rule, stylesheet.cssRules.length)
- }catch(e) {
- runtime.log("Problem inserting rule in CSS: " + runtime.toJson(e) + "\nRule: " + rule)
- }
++ return formatting.getAppliedStyles(nodes)
+ }
- function loadFontIntoCSS(embeddedFontDeclarations, odfContainer, pos, stylesheet, callback) {
- var name, i = 0, n;
- for(n in embeddedFontDeclarations) {
- if(embeddedFontDeclarations.hasOwnProperty(n)) {
- if(i === pos) {
- name = n;
- break
- }
- i += 1
++ this.getAppliedStyles = getAppliedStyles;
++ this.applyStyle = function(memberId, range, info) {
++ var nextTextNodes = domUtils.splitBoundaries(range), textNodes = odfUtils.getTextNodes(range, false), limits;
++ limits = {startContainer:range.startContainer, startOffset:range.startOffset, endContainer:range.endContainer, endOffset:range.endOffset};
++ formatting.applyStyle(memberId, textNodes, limits, info);
++ nextTextNodes.forEach(domUtils.normalizeTextNodes)
++ };
++ function hasTextPropertyValue(appliedStyles, propertyName, propertyValue) {
++ var hasOtherValue = true, properties, i;
++ for(i = 0;i < appliedStyles.length;i += 1) {
++ properties = appliedStyles[i]["style:text-properties"];
++ hasOtherValue = !properties || properties[propertyName] !== propertyValue;
++ if(hasOtherValue) {
++ break
+ }
+ }
- if(!name) {
- if(callback) {
- callback()
++ return!hasOtherValue
++ }
++ this.isBold = function(appliedStyles) {
++ return hasTextPropertyValue(appliedStyles, "fo:font-weight", "bold")
++ };
++ this.isItalic = function(appliedStyles) {
++ return hasTextPropertyValue(appliedStyles, "fo:font-style", "italic")
++ };
++ this.hasUnderline = function(appliedStyles) {
++ return hasTextPropertyValue(appliedStyles, "style:text-underline-style", "solid")
++ };
++ this.hasStrikeThrough = function(appliedStyles) {
++ return hasTextPropertyValue(appliedStyles, "style:text-line-through-style", "solid")
++ };
++ function hasParagraphPropertyValue(range, propertyName, propertyValues) {
++ var paragraphStyleName, paragraphStyleElement, paragraphStyleAttributes, properties, nodes = odfUtils.getParagraphElements(range), isStyleChecked = {}, isDefaultParagraphStyleChecked = false;
++ function pickDefaultParagraphStyleElement() {
++ isDefaultParagraphStyleChecked = true;
++ paragraphStyleElement = formatting.getDefaultStyleElement("paragraph");
++ if(!paragraphStyleElement) {
++ paragraphStyleElement = null
+ }
- return
+ }
- odfContainer.getPartData(embeddedFontDeclarations[name].href, function(err, fontdata) {
- if(err) {
- runtime.log(err)
++ while(nodes.length > 0) {
++ paragraphStyleName = nodes[0].getAttributeNS(textns, "style-name");
++ if(paragraphStyleName) {
++ if(!isStyleChecked[paragraphStyleName]) {
++ paragraphStyleElement = formatting.getStyleElement(paragraphStyleName, "paragraph");
++ isStyleChecked[paragraphStyleName] = true;
++ if(!paragraphStyleElement && !isDefaultParagraphStyleChecked) {
++ pickDefaultParagraphStyleElement()
++ }
++ }
+ }else {
- if(!fontdata) {
- runtime.log("missing font data for " + embeddedFontDeclarations[name].href)
++ if(!isDefaultParagraphStyleChecked) {
++ pickDefaultParagraphStyleElement()
+ }else {
- addFontToCSS(name, embeddedFontDeclarations[name], fontdata, stylesheet)
++ paragraphStyleElement = undefined
+ }
+ }
- loadFontIntoCSS(embeddedFontDeclarations, odfContainer, pos + 1, stylesheet, callback)
- })
- }
- function loadFontsIntoCSS(embeddedFontDeclarations, odfContainer, stylesheet) {
- loadFontIntoCSS(embeddedFontDeclarations, odfContainer, 0, stylesheet)
- }
- odf.FontLoader = function FontLoader() {
- this.loadFonts = function(odfContainer, stylesheet) {
- var embeddedFontDeclarations, fontFaceDecls = odfContainer.rootElement.fontFaceDecls;
- while(stylesheet.cssRules.length) {
- stylesheet.deleteRule(stylesheet.cssRules.length - 1)
- }
- if(fontFaceDecls) {
- embeddedFontDeclarations = getEmbeddedFontDeclarations(fontFaceDecls);
- loadFontsIntoCSS(embeddedFontDeclarations, odfContainer, stylesheet)
- }
- }
- };
- return odf.FontLoader
- }();
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- runtime.loadClass("core.DomUtils");
- runtime.loadClass("core.Utils");
- odf.ObjectNameGenerator = function ObjectNameGenerator(odfContainer, memberId) {
- var stylens = odf.Namespaces.stylens, drawns = odf.Namespaces.drawns, xlinkns = odf.Namespaces.xlinkns, domUtils = new core.DomUtils, utils = new core.Utils, memberIdHash = utils.hashString(memberId), styleNameGenerator = null, frameNameGenerator = null, imageNameGenerator = null, existingFrameNames = {}, existingImageNames = {};
- function NameGenerator(prefix, findExistingNames) {
- var reportedNames = {};
- this.generateName = function() {
- var existingNames = findExistingNames(), startIndex = 0, name;
- do {
- name = prefix + startIndex;
- startIndex += 1
- }while(reportedNames[name] || existingNames[name]);
- reportedNames[name] = true;
- return name
- }
- }
- function getAllStyleNames() {
- var styleElements = [odfContainer.rootElement.automaticStyles, odfContainer.rootElement.styles], node, styleNames = {};
- styleElements.forEach(function(styleListElement) {
- node = styleListElement.firstChild;
- while(node) {
- if(node.nodeType === Node.ELEMENT_NODE && (node.namespaceURI === stylens && node.localName === "style")) {
- styleNames[node.getAttributeNS(stylens, "name")] = true
++ if(paragraphStyleElement !== undefined) {
++ if(paragraphStyleElement === null) {
++ paragraphStyleAttributes = formatting.getSystemDefaultStyleAttributes("paragraph")
++ }else {
++ paragraphStyleAttributes = formatting.getInheritedStyleAttributes((paragraphStyleElement), true)
++ }
++ properties = paragraphStyleAttributes["style:paragraph-properties"];
++ if(properties && propertyValues.indexOf(properties[propertyName]) === -1) {
++ return false
+ }
- node = node.nextSibling
+ }
- });
- return styleNames
- }
- this.generateStyleName = function() {
- if(styleNameGenerator === null) {
- styleNameGenerator = new NameGenerator("auto" + memberIdHash + "_", function() {
- return getAllStyleNames()
- })
++ nodes.pop()
+ }
- return styleNameGenerator.generateName()
++ return true
++ }
++ this.isAlignedLeft = function(range) {
++ return hasParagraphPropertyValue(range, "fo:text-align", ["left", "start"])
+ };
- this.generateFrameName = function() {
- if(frameNameGenerator === null) {
- var nodes = domUtils.getElementsByTagNameNS(odfContainer.rootElement.body, drawns, "frame");
- nodes.forEach(function(frame) {
- existingFrameNames[frame.getAttributeNS(drawns, "name")] = true
- });
- frameNameGenerator = new NameGenerator("fr" + memberIdHash + "_", function() {
- return existingFrameNames
- })
- }
- return frameNameGenerator.generateName()
++ this.isAlignedCenter = function(range) {
++ return hasParagraphPropertyValue(range, "fo:text-align", ["center"])
+ };
- this.generateImageName = function() {
- if(imageNameGenerator === null) {
- var nodes = domUtils.getElementsByTagNameNS(odfContainer.rootElement.body, drawns, "image");
- nodes.forEach(function(image) {
- var path = image.getAttributeNS(xlinkns, "href");
- path = path.substring("Pictures/".length, path.lastIndexOf("."));
- existingImageNames[path] = true
- });
- imageNameGenerator = new NameGenerator("img" + memberIdHash + "_", function() {
- return existingImageNames
- })
- }
- return imageNameGenerator.generateName()
++ this.isAlignedRight = function(range) {
++ return hasParagraphPropertyValue(range, "fo:text-align", ["right", "end"])
++ };
++ this.isAlignedJustified = function(range) {
++ return hasParagraphPropertyValue(range, "fo:text-align", ["justify"])
+ }
+};
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- runtime.loadClass("core.Utils");
- runtime.loadClass("odf.ObjectNameGenerator");
- runtime.loadClass("odf.Namespaces");
- runtime.loadClass("odf.OdfContainer");
- runtime.loadClass("odf.StyleInfo");
- runtime.loadClass("odf.OdfUtils");
- runtime.loadClass("odf.TextStyleApplicator");
- odf.Formatting = function Formatting() {
- var self = this, odfContainer, styleInfo = new odf.StyleInfo, svgns = odf.Namespaces.svgns, stylens = odf.Namespaces.stylens, textns = odf.Namespaces.textns, numberns = odf.Namespaces.numberns, fons = odf.Namespaces.fons, odfUtils = new odf.OdfUtils, domUtils = new core.DomUtils, utils = new core.Utils, builtInDefaultStyleAttributesByFamily = {"paragraph":{"style:paragraph-properties":{"fo:text-align":"left"}}}, defaultPageFormatSettings = {width:21.001, height:29.7, margin:2, padding:0};
- function getSystemDefaultStyleAttributes(styleFamily) {
- var result, builtInDefaultStyleAttributes = builtInDefaultStyleAttributesByFamily[styleFamily];
- if(builtInDefaultStyleAttributes) {
- result = utils.mergeObjects({}, builtInDefaultStyleAttributes)
- }else {
- result = null
- }
- return result
++core.RawDeflate = function() {
++ var zip_WSIZE = 32768, zip_STORED_BLOCK = 0, zip_STATIC_TREES = 1, zip_DYN_TREES = 2, zip_DEFAULT_LEVEL = 6, zip_FULL_SEARCH = true, zip_INBUFSIZ = 32768, zip_INBUF_EXTRA = 64, zip_OUTBUFSIZ = 1024 * 8, zip_window_size = 2 * zip_WSIZE, zip_MIN_MATCH = 3, zip_MAX_MATCH = 258, zip_BITS = 16, zip_LIT_BUFSIZE = 8192, zip_HASH_BITS = 13, zip_DIST_BUFSIZE = zip_LIT_BUFSIZE, zip_HASH_SIZE = 1 << zip_HASH_BITS, zip_HASH_MASK = zip_HASH_SIZE - 1, zip_WMASK = zip_WSIZE - 1, zip_NIL = 0, zip_TOO [...]
++ zip_MIN_LOOKAHEAD = zip_MAX_MATCH + zip_MIN_MATCH + 1, zip_MAX_DIST = zip_WSIZE - zip_MIN_LOOKAHEAD, zip_SMALLEST = 1, zip_MAX_BITS = 15, zip_MAX_BL_BITS = 7, zip_LENGTH_CODES = 29, zip_LITERALS = 256, zip_END_BLOCK = 256, zip_L_CODES = zip_LITERALS + 1 + zip_LENGTH_CODES, zip_D_CODES = 30, zip_BL_CODES = 19, zip_REP_3_6 = 16, zip_REPZ_3_10 = 17, zip_REPZ_11_138 = 18, zip_HEAP_SIZE = 2 * zip_L_CODES + 1, zip_H_SHIFT = parseInt((zip_HASH_BITS + zip_MIN_MATCH - 1) / zip_MIN_MATCH, 10), [...]
++ zip_qhead, zip_qtail, zip_initflag, zip_outbuf = null, zip_outcnt, zip_outoff, zip_complete, zip_window, zip_d_buf, zip_l_buf, zip_prev, zip_bi_buf, zip_bi_valid, zip_block_start, zip_ins_h, zip_hash_head, zip_prev_match, zip_match_available, zip_match_length, zip_prev_length, zip_strstart, zip_match_start, zip_eofile, zip_lookahead, zip_max_chain_length, zip_max_lazy_match, zip_compr_level, zip_good_match, zip_nice_match, zip_dyn_ltree, zip_dyn_dtree, zip_static_ltree, zip_static_dtr [...]
++ zip_l_desc, zip_d_desc, zip_bl_desc, zip_bl_count, zip_heap, zip_heap_len, zip_heap_max, zip_depth, zip_length_code, zip_dist_code, zip_base_length, zip_base_dist, zip_flag_buf, zip_last_lit, zip_last_dist, zip_last_flags, zip_flags, zip_flag_bit, zip_opt_len, zip_static_len, zip_deflate_data, zip_deflate_pos, zip_extra_lbits = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0], zip_extra_dbits = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, [...]
++ 9, 10, 10, 11, 11, 12, 12, 13, 13], zip_extra_blbits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7], zip_bl_order = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15], zip_configuration_table;
++ if(zip_LIT_BUFSIZE > zip_INBUFSIZ) {
++ runtime.log("error: zip_INBUFSIZ is too small")
+ }
- this.getSystemDefaultStyleAttributes = getSystemDefaultStyleAttributes;
- this.setOdfContainer = function(odfcontainer) {
- odfContainer = odfcontainer
- };
- function getFontMap() {
- var fontFaceDecls = odfContainer.rootElement.fontFaceDecls, fontFaceDeclsMap = {}, node, name, family;
- node = fontFaceDecls && fontFaceDecls.firstChild;
- while(node) {
- if(node.nodeType === Node.ELEMENT_NODE) {
- name = node.getAttributeNS(stylens, "name");
- if(name) {
- family = node.getAttributeNS(svgns, "font-family");
- if(family || node.getElementsByTagNameNS(svgns, "font-face-uri")[0]) {
- fontFaceDeclsMap[name] = family
- }
- }
- }
- node = node.nextSibling
- }
- return fontFaceDeclsMap
++ if(zip_WSIZE << 1 > 1 << zip_BITS) {
++ runtime.log("error: zip_WSIZE is too large")
+ }
- this.getFontMap = getFontMap;
- this.getAvailableParagraphStyles = function() {
- var node = odfContainer.rootElement.styles && odfContainer.rootElement.styles.firstChild, p_family, p_name, p_displayName, paragraphStyles = [], style;
- while(node) {
- if(node.nodeType === Node.ELEMENT_NODE && (node.localName === "style" && node.namespaceURI === stylens)) {
- style = node;
- p_family = style.getAttributeNS(stylens, "family");
- if(p_family === "paragraph") {
- p_name = style.getAttributeNS(stylens, "name");
- p_displayName = style.getAttributeNS(stylens, "display-name") || p_name;
- if(p_name && p_displayName) {
- paragraphStyles.push({name:p_name, displayName:p_displayName})
- }
- }
- }
- node = node.nextSibling
- }
- return paragraphStyles
- };
- this.isStyleUsed = function(styleElement) {
- var hasDerivedStyles, isUsed;
- hasDerivedStyles = styleInfo.hasDerivedStyles(odfContainer.rootElement, odf.Namespaces.resolvePrefix, styleElement);
- isUsed = (new styleInfo.UsedStyleList(odfContainer.rootElement.styles)).uses(styleElement) || ((new styleInfo.UsedStyleList(odfContainer.rootElement.automaticStyles)).uses(styleElement) || (new styleInfo.UsedStyleList(odfContainer.rootElement.body)).uses(styleElement));
- return hasDerivedStyles || isUsed
- };
- function getDefaultStyleElement(family) {
- var node = odfContainer.rootElement.styles.firstChild;
- while(node) {
- if(node.nodeType === Node.ELEMENT_NODE && (node.namespaceURI === stylens && (node.localName === "default-style" && node.getAttributeNS(stylens, "family") === family))) {
- return node
- }
- node = node.nextSibling
- }
- return null
++ if(zip_HASH_BITS > zip_BITS - 1) {
++ runtime.log("error: zip_HASH_BITS is too large")
+ }
- this.getDefaultStyleElement = getDefaultStyleElement;
- function getStyleElement(styleName, family, styleElements) {
- var node, nodeStyleName, styleListElement;
- styleElements = styleElements || [odfContainer.rootElement.automaticStyles, odfContainer.rootElement.styles];
- styleListElement = styleElements.shift();
- while(styleListElement) {
- node = styleListElement.firstChild;
- while(node) {
- if(node.nodeType === Node.ELEMENT_NODE) {
- nodeStyleName = node.getAttributeNS(stylens, "name");
- if(node.namespaceURI === stylens && (node.localName === "style" && (node.getAttributeNS(stylens, "family") === family && nodeStyleName === styleName))) {
- return node
- }
- if(family === "list-style" && (node.namespaceURI === textns && (node.localName === "list-style" && nodeStyleName === styleName))) {
- return node
- }
- if(family === "data" && (node.namespaceURI === numberns && nodeStyleName === styleName)) {
- return node
- }
- }
- node = node.nextSibling
- }
- styleListElement = styleElements.shift()
- }
- return null
++ if(zip_HASH_BITS < 8 || zip_MAX_MATCH !== 258) {
++ runtime.log("error: Code too clever")
+ }
- this.getStyleElement = getStyleElement;
- function getStyleAttributes(styleNode) {
- var i, propertiesMap = {}, propertiesNode = styleNode.firstChild;
- while(propertiesNode) {
- if(propertiesNode.nodeType === Node.ELEMENT_NODE && propertiesNode.namespaceURI === stylens) {
- propertiesMap[propertiesNode.nodeName] = {};
- for(i = 0;i < propertiesNode.attributes.length;i += 1) {
- propertiesMap[propertiesNode.nodeName][propertiesNode.attributes[i].name] = propertiesNode.attributes[i].value
++ function Zip_DeflateCT() {
++ this.fc = 0;
++ this.dl = 0
++ }
++ function Zip_DeflateTreeDesc() {
++ this.dyn_tree = null;
++ this.static_tree = null;
++ this.extra_bits = null;
++ this.extra_base = 0;
++ this.elems = 0;
++ this.max_length = 0;
++ this.max_code = 0
++ }
++ function Zip_DeflateConfiguration(a, b, c, d) {
++ this.good_length = a;
++ this.max_lazy = b;
++ this.nice_length = c;
++ this.max_chain = d
++ }
++ function Zip_DeflateBuffer() {
++ this.next = null;
++ this.len = 0;
++ this.ptr = [];
++ this.ptr.length = zip_OUTBUFSIZ;
++ this.off = 0
++ }
++ zip_configuration_table = [new Zip_DeflateConfiguration(0, 0, 0, 0), new Zip_DeflateConfiguration(4, 4, 8, 4), new Zip_DeflateConfiguration(4, 5, 16, 8), new Zip_DeflateConfiguration(4, 6, 32, 32), new Zip_DeflateConfiguration(4, 4, 16, 16), new Zip_DeflateConfiguration(8, 16, 32, 32), new Zip_DeflateConfiguration(8, 16, 128, 128), new Zip_DeflateConfiguration(8, 32, 128, 256), new Zip_DeflateConfiguration(32, 128, 258, 1024), new Zip_DeflateConfiguration(32, 258, 258, 4096)];
++ function zip_deflate_start(level) {
++ var i;
++ if(!level) {
++ level = zip_DEFAULT_LEVEL
++ }else {
++ if(level < 1) {
++ level = 1
++ }else {
++ if(level > 9) {
++ level = 9
+ }
+ }
- propertiesNode = propertiesNode.nextSibling
+ }
- for(i = 0;i < styleNode.attributes.length;i += 1) {
- propertiesMap[styleNode.attributes[i].name] = styleNode.attributes[i].value
++ zip_compr_level = level;
++ zip_initflag = false;
++ zip_eofile = false;
++ if(zip_outbuf !== null) {
++ return
+ }
- return propertiesMap
- }
- this.getStyleAttributes = getStyleAttributes;
- function getInheritedStyleAttributes(styleNode, includeSystemDefault) {
- var styleListElement = odfContainer.rootElement.styles, parentStyleName, propertiesMap, inheritedPropertiesMap = {}, styleFamily = styleNode.getAttributeNS(stylens, "family"), node = styleNode;
- while(node) {
- propertiesMap = getStyleAttributes(node);
- inheritedPropertiesMap = utils.mergeObjects(propertiesMap, inheritedPropertiesMap);
- parentStyleName = node.getAttributeNS(stylens, "parent-style-name");
- if(parentStyleName) {
- node = getStyleElement(parentStyleName, styleFamily, [styleListElement])
- }else {
- node = null
- }
++ zip_free_queue = zip_qhead = zip_qtail = null;
++ zip_outbuf = [];
++ zip_outbuf.length = zip_OUTBUFSIZ;
++ zip_window = [];
++ zip_window.length = zip_window_size;
++ zip_d_buf = [];
++ zip_d_buf.length = zip_DIST_BUFSIZE;
++ zip_l_buf = [];
++ zip_l_buf.length = zip_INBUFSIZ + zip_INBUF_EXTRA;
++ zip_prev = [];
++ zip_prev.length = 1 << zip_BITS;
++ zip_dyn_ltree = [];
++ zip_dyn_ltree.length = zip_HEAP_SIZE;
++ for(i = 0;i < zip_HEAP_SIZE;i++) {
++ zip_dyn_ltree[i] = new Zip_DeflateCT
+ }
- node = getDefaultStyleElement(styleFamily);
- if(node) {
- propertiesMap = getStyleAttributes(node);
- inheritedPropertiesMap = utils.mergeObjects(propertiesMap, inheritedPropertiesMap)
++ zip_dyn_dtree = [];
++ zip_dyn_dtree.length = 2 * zip_D_CODES + 1;
++ for(i = 0;i < 2 * zip_D_CODES + 1;i++) {
++ zip_dyn_dtree[i] = new Zip_DeflateCT
+ }
- if(includeSystemDefault) {
- propertiesMap = getSystemDefaultStyleAttributes(styleFamily);
- if(propertiesMap) {
- inheritedPropertiesMap = utils.mergeObjects(propertiesMap, inheritedPropertiesMap)
- }
++ zip_static_ltree = [];
++ zip_static_ltree.length = zip_L_CODES + 2;
++ for(i = 0;i < zip_L_CODES + 2;i++) {
++ zip_static_ltree[i] = new Zip_DeflateCT
+ }
- return inheritedPropertiesMap
- }
- this.getInheritedStyleAttributes = getInheritedStyleAttributes;
- this.getFirstCommonParentStyleNameOrSelf = function(styleName) {
- var automaticStyleElementList = odfContainer.rootElement.automaticStyles, styleElementList = odfContainer.rootElement.styles, styleElement;
- styleElement = getStyleElement(styleName, "paragraph", [automaticStyleElementList]);
- while(styleElement) {
- styleName = styleElement.getAttributeNS(stylens, "parent-style-name");
- styleElement = getStyleElement(styleName, "paragraph", [automaticStyleElementList])
++ zip_static_dtree = [];
++ zip_static_dtree.length = zip_D_CODES;
++ for(i = 0;i < zip_D_CODES;i++) {
++ zip_static_dtree[i] = new Zip_DeflateCT
+ }
- styleElement = getStyleElement(styleName, "paragraph", [styleElementList]);
- if(!styleElement) {
- return null
++ zip_bl_tree = [];
++ zip_bl_tree.length = 2 * zip_BL_CODES + 1;
++ for(i = 0;i < 2 * zip_BL_CODES + 1;i++) {
++ zip_bl_tree[i] = new Zip_DeflateCT
+ }
- return styleName
++ zip_l_desc = new Zip_DeflateTreeDesc;
++ zip_d_desc = new Zip_DeflateTreeDesc;
++ zip_bl_desc = new Zip_DeflateTreeDesc;
++ zip_bl_count = [];
++ zip_bl_count.length = zip_MAX_BITS + 1;
++ zip_heap = [];
++ zip_heap.length = 2 * zip_L_CODES + 1;
++ zip_depth = [];
++ zip_depth.length = 2 * zip_L_CODES + 1;
++ zip_length_code = [];
++ zip_length_code.length = zip_MAX_MATCH - zip_MIN_MATCH + 1;
++ zip_dist_code = [];
++ zip_dist_code.length = 512;
++ zip_base_length = [];
++ zip_base_length.length = zip_LENGTH_CODES;
++ zip_base_dist = [];
++ zip_base_dist.length = zip_D_CODES;
++ zip_flag_buf = [];
++ zip_flag_buf.length = parseInt(zip_LIT_BUFSIZE / 8, 10)
++ }
++ var zip_reuse_queue = function(p) {
++ p.next = zip_free_queue;
++ zip_free_queue = p
+ };
- this.hasParagraphStyle = function(styleName) {
- return Boolean(getStyleElement(styleName, "paragraph"))
++ var zip_new_queue = function() {
++ var p;
++ if(zip_free_queue !== null) {
++ p = zip_free_queue;
++ zip_free_queue = zip_free_queue.next
++ }else {
++ p = new Zip_DeflateBuffer
++ }
++ p.next = null;
++ p.len = p.off = 0;
++ return p
+ };
- function buildStyleChain(node, collectedChains) {
- var parent = node.nodeType === Node.TEXT_NODE ? node.parentNode : node, nodeStyles, appliedStyles = [], chainKey = "", foundContainer = false;
- while(parent) {
- if(!foundContainer && odfUtils.isGroupingElement(parent)) {
- foundContainer = true
- }
- nodeStyles = styleInfo.determineStylesForNode((parent));
- if(nodeStyles) {
- appliedStyles.push(nodeStyles)
++ var zip_head1 = function(i) {
++ return zip_prev[zip_WSIZE + i]
++ };
++ var zip_head2 = function(i, val) {
++ zip_prev[zip_WSIZE + i] = val;
++ return val
++ };
++ var zip_qoutbuf = function() {
++ var q, i;
++ if(zip_outcnt !== 0) {
++ q = zip_new_queue();
++ if(zip_qhead === null) {
++ zip_qhead = zip_qtail = q
++ }else {
++ zip_qtail = zip_qtail.next = q
+ }
- parent = parent.parentNode
- }
- if(foundContainer) {
- appliedStyles.forEach(function(usedStyleMap) {
- Object.keys(usedStyleMap).forEach(function(styleFamily) {
- Object.keys(usedStyleMap[styleFamily]).forEach(function(styleName) {
- chainKey += "|" + styleFamily + ":" + styleName + "|"
- })
- })
- });
- if(collectedChains) {
- collectedChains[chainKey] = appliedStyles
++ q.len = zip_outcnt - zip_outoff;
++ for(i = 0;i < q.len;i++) {
++ q.ptr[i] = zip_outbuf[zip_outoff + i]
+ }
++ zip_outcnt = zip_outoff = 0
+ }
- return foundContainer ? appliedStyles : undefined
- }
- function calculateAppliedStyle(styleChain) {
- var mergedChildStyle = {orderedStyles:[]};
- styleChain.forEach(function(elementStyleSet) {
- Object.keys((elementStyleSet)).forEach(function(styleFamily) {
- var styleName = Object.keys(elementStyleSet[styleFamily])[0], styleElement, parentStyle, displayName;
- styleElement = getStyleElement(styleName, styleFamily);
- if(styleElement) {
- parentStyle = getInheritedStyleAttributes((styleElement));
- mergedChildStyle = utils.mergeObjects(parentStyle, mergedChildStyle);
- displayName = styleElement.getAttributeNS(stylens, "display-name")
- }else {
- runtime.log("No style element found for '" + styleName + "' of family '" + styleFamily + "'")
- }
- mergedChildStyle.orderedStyles.push({name:styleName, family:styleFamily, displayName:displayName})
- })
- });
- return mergedChildStyle
- }
- this.getAppliedStyles = function(textNodes) {
- var styleChains = {}, styles = [];
- textNodes.forEach(function(n) {
- buildStyleChain(n, styleChains)
- });
- Object.keys(styleChains).forEach(function(key) {
- styles.push(calculateAppliedStyle(styleChains[key]))
- });
- return styles
+ };
- this.getAppliedStylesForElement = function(node) {
- var styleChain;
- styleChain = buildStyleChain(node);
- return styleChain ? calculateAppliedStyle(styleChain) : undefined
++ var zip_put_byte = function(c) {
++ zip_outbuf[zip_outoff + zip_outcnt++] = c;
++ if(zip_outoff + zip_outcnt === zip_OUTBUFSIZ) {
++ zip_qoutbuf()
++ }
+ };
- this.applyStyle = function(memberId, textNodes, limits, info) {
- var textStyles = new odf.TextStyleApplicator(new odf.ObjectNameGenerator((odfContainer), memberId), self, odfContainer.rootElement.automaticStyles);
- textStyles.applyStyle(textNodes, limits, info)
- };
- this.updateStyle = function(styleNode, properties) {
- var fontName, fontFaceNode;
- domUtils.mapObjOntoNode(styleNode, properties, odf.Namespaces.resolvePrefix);
- fontName = properties["style:text-properties"] && properties["style:text-properties"]["style:font-name"];
- if(fontName && !getFontMap().hasOwnProperty(fontName)) {
- fontFaceNode = styleNode.ownerDocument.createElementNS(stylens, "style:font-face");
- fontFaceNode.setAttributeNS(stylens, "style:name", fontName);
- fontFaceNode.setAttributeNS(svgns, "svg:font-family", fontName);
- odfContainer.rootElement.fontFaceDecls.appendChild(fontFaceNode)
++ var zip_put_short = function(w) {
++ w &= 65535;
++ if(zip_outoff + zip_outcnt < zip_OUTBUFSIZ - 2) {
++ zip_outbuf[zip_outoff + zip_outcnt++] = w & 255;
++ zip_outbuf[zip_outoff + zip_outcnt++] = w >>> 8
++ }else {
++ zip_put_byte(w & 255);
++ zip_put_byte(w >>> 8)
+ }
+ };
- function isAutomaticStyleElement(styleNode) {
- return styleNode.parentNode === odfContainer.rootElement.automaticStyles
- }
- this.createDerivedStyleObject = function(parentStyleName, family, overrides) {
- var originalStyleElement = (getStyleElement(parentStyleName, family)), newStyleObject;
- runtime.assert(Boolean(originalStyleElement), "No style element found for '" + parentStyleName + "' of family '" + family + "'");
- if(isAutomaticStyleElement(originalStyleElement)) {
- newStyleObject = getStyleAttributes(originalStyleElement)
++ var zip_INSERT_STRING = function() {
++ zip_ins_h = (zip_ins_h << zip_H_SHIFT ^ zip_window[zip_strstart + zip_MIN_MATCH - 1] & 255) & zip_HASH_MASK;
++ zip_hash_head = zip_head1(zip_ins_h);
++ zip_prev[zip_strstart & zip_WMASK] = zip_hash_head;
++ zip_head2(zip_ins_h, zip_strstart)
++ };
++ var zip_Buf_size = 16;
++ var zip_send_bits = function(value, length) {
++ if(zip_bi_valid > zip_Buf_size - length) {
++ zip_bi_buf |= value << zip_bi_valid;
++ zip_put_short(zip_bi_buf);
++ zip_bi_buf = value >> zip_Buf_size - zip_bi_valid;
++ zip_bi_valid += length - zip_Buf_size
+ }else {
- newStyleObject = {"style:parent-style-name":parentStyleName}
++ zip_bi_buf |= value << zip_bi_valid;
++ zip_bi_valid += length
+ }
- newStyleObject["style:family"] = family;
- utils.mergeObjects(newStyleObject, overrides);
- return newStyleObject
+ };
- this.getDefaultTabStopDistance = function() {
- var defaultParagraph = getDefaultStyleElement("paragraph"), paragraphProperties = defaultParagraph && defaultParagraph.getAttributeNS(stylens, "paragraph-properties"), tabStopDistance = paragraphProperties && paragraphProperties.getAttributeNS(stylens, "tab-stop-distance");
- if(!tabStopDistance) {
- tabStopDistance = "1.25cm"
++ var zip_SEND_CODE = function(c, tree) {
++ zip_send_bits(tree[c].fc, tree[c].dl)
++ };
++ var zip_D_CODE = function(dist) {
++ return(dist < 256 ? zip_dist_code[dist] : zip_dist_code[256 + (dist >> 7)]) & 255
++ };
++ var zip_SMALLER = function(tree, n, m) {
++ return tree[n].fc < tree[m].fc || tree[n].fc === tree[m].fc && zip_depth[n] <= zip_depth[m]
++ };
++ var zip_read_buff = function(buff, offset, n) {
++ var i;
++ for(i = 0;i < n && zip_deflate_pos < zip_deflate_data.length;i++) {
++ buff[offset + i] = zip_deflate_data.charCodeAt(zip_deflate_pos++) & 255
+ }
- return odfUtils.parseNonNegativeLength(tabStopDistance)
++ return i
+ };
- function getPageLayoutStyleElement(styleName, styleFamily) {
- var styleElement = getStyleElement(styleName, styleFamily), masterPageName, layoutName, pageLayoutElements, node, i;
- runtime.assert(styleFamily === "paragraph" || styleFamily === "table", "styleFamily has to be either paragraph or table");
- if(styleElement) {
- masterPageName = styleElement.getAttributeNS(stylens, "master-page-name") || "Standard";
- node = odfContainer.rootElement.masterStyles.lastChild;
- while(node && node.previousSibling) {
- if(node.getAttributeNS(stylens, "name") === masterPageName) {
- break
++ var zip_fill_window = function() {
++ var n, m;
++ var more = zip_window_size - zip_lookahead - zip_strstart;
++ if(more === -1) {
++ more--
++ }else {
++ if(zip_strstart >= zip_WSIZE + zip_MAX_DIST) {
++ for(n = 0;n < zip_WSIZE;n++) {
++ zip_window[n] = zip_window[n + zip_WSIZE]
+ }
- node = node.previousSibling
- }
- layoutName = node.getAttributeNS(stylens, "page-layout-name");
- pageLayoutElements = domUtils.getElementsByTagNameNS(odfContainer.rootElement.automaticStyles, stylens, "page-layout");
- for(i = 0;i < pageLayoutElements.length;i += 1) {
- node = pageLayoutElements[i];
- if(node.getAttributeNS(stylens, "name") === layoutName) {
- return(node)
++ zip_match_start -= zip_WSIZE;
++ zip_strstart -= zip_WSIZE;
++ zip_block_start -= zip_WSIZE;
++ for(n = 0;n < zip_HASH_SIZE;n++) {
++ m = zip_head1(n);
++ zip_head2(n, m >= zip_WSIZE ? m - zip_WSIZE : zip_NIL)
++ }
++ for(n = 0;n < zip_WSIZE;n++) {
++ m = zip_prev[n];
++ zip_prev[n] = m >= zip_WSIZE ? m - zip_WSIZE : zip_NIL
+ }
++ more += zip_WSIZE
+ }
+ }
- return null
- }
- function lengthInCm(length, defaultValue) {
- var result = odfUtils.parseLength(length), value = defaultValue;
- if(result) {
- switch(result.unit) {
- case "cm":
- value = result.value;
- break;
- case "mm":
- value = result.value * 0.1;
- break;
- case "in":
- value = result.value * 2.54;
- break;
- case "pt":
- value = result.value * 0.035277778;
- break;
- case "pc":
- ;
- case "px":
- ;
- case "em":
- break;
- default:
- runtime.log("Unit identifier: " + result.unit + " is not supported.");
- break
++ if(!zip_eofile) {
++ n = zip_read_buff(zip_window, zip_strstart + zip_lookahead, more);
++ if(n <= 0) {
++ zip_eofile = true
++ }else {
++ zip_lookahead += n
+ }
+ }
- return value
- }
- this.getContentSize = function(styleName, styleFamily) {
- var pageLayoutElement, props, printOrientation, defaultOrientedPageWidth, defaultOrientedPageHeight, pageWidth, pageHeight, margin, marginLeft, marginRight, marginTop, marginBottom, padding, paddingLeft, paddingRight, paddingTop, paddingBottom;
- pageLayoutElement = getPageLayoutStyleElement(styleName, styleFamily);
- if(!pageLayoutElement) {
- pageLayoutElement = odfContainer.rootElement.styles.getElementsByTagNameNS(stylens, "default-page-layout")[0]
++ };
++ var zip_lm_init = function() {
++ var j;
++ for(j = 0;j < zip_HASH_SIZE;j++) {
++ zip_prev[zip_WSIZE + j] = 0
+ }
- if(pageLayoutElement) {
- props = pageLayoutElement.getElementsByTagNameNS(stylens, "page-layout-properties")[0]
++ zip_max_lazy_match = zip_configuration_table[zip_compr_level].max_lazy;
++ zip_good_match = zip_configuration_table[zip_compr_level].good_length;
++ if(!zip_FULL_SEARCH) {
++ zip_nice_match = zip_configuration_table[zip_compr_level].nice_length
+ }
- if(props) {
- printOrientation = props.getAttributeNS(stylens, "print-orientation") || "portrait";
- if(printOrientation === "portrait") {
- defaultOrientedPageWidth = defaultPageFormatSettings.width;
- defaultOrientedPageHeight = defaultPageFormatSettings.height
- }else {
- defaultOrientedPageWidth = defaultPageFormatSettings.height;
- defaultOrientedPageHeight = defaultPageFormatSettings.width
++ zip_max_chain_length = zip_configuration_table[zip_compr_level].max_chain;
++ zip_strstart = 0;
++ zip_block_start = 0;
++ zip_lookahead = zip_read_buff(zip_window, 0, 2 * zip_WSIZE);
++ if(zip_lookahead <= 0) {
++ zip_eofile = true;
++ zip_lookahead = 0;
++ return
++ }
++ zip_eofile = false;
++ while(zip_lookahead < zip_MIN_LOOKAHEAD && !zip_eofile) {
++ zip_fill_window()
++ }
++ zip_ins_h = 0;
++ for(j = 0;j < zip_MIN_MATCH - 1;j++) {
++ zip_ins_h = (zip_ins_h << zip_H_SHIFT ^ zip_window[j] & 255) & zip_HASH_MASK
++ }
++ };
++ var zip_longest_match = function(cur_match) {
++ var chain_length = zip_max_chain_length;
++ var scanp = zip_strstart;
++ var matchp;
++ var len;
++ var best_len = zip_prev_length;
++ var limit = zip_strstart > zip_MAX_DIST ? zip_strstart - zip_MAX_DIST : zip_NIL;
++ var strendp = zip_strstart + zip_MAX_MATCH;
++ var scan_end1 = zip_window[scanp + best_len - 1];
++ var scan_end = zip_window[scanp + best_len];
++ if(zip_prev_length >= zip_good_match) {
++ chain_length >>= 2
++ }
++ do {
++ matchp = cur_match;
++ if(zip_window[matchp + best_len] !== scan_end || (zip_window[matchp + best_len - 1] !== scan_end1 || (zip_window[matchp] !== zip_window[scanp] || zip_window[++matchp] !== zip_window[scanp + 1]))) {
++ continue
+ }
- pageWidth = lengthInCm(props.getAttributeNS(fons, "page-width"), defaultOrientedPageWidth);
- pageHeight = lengthInCm(props.getAttributeNS(fons, "page-height"), defaultOrientedPageHeight);
- margin = lengthInCm(props.getAttributeNS(fons, "margin"), null);
- if(margin === null) {
- marginLeft = lengthInCm(props.getAttributeNS(fons, "margin-left"), defaultPageFormatSettings.margin);
- marginRight = lengthInCm(props.getAttributeNS(fons, "margin-right"), defaultPageFormatSettings.margin);
- marginTop = lengthInCm(props.getAttributeNS(fons, "margin-top"), defaultPageFormatSettings.margin);
- marginBottom = lengthInCm(props.getAttributeNS(fons, "margin-bottom"), defaultPageFormatSettings.margin)
- }else {
- marginLeft = marginRight = marginTop = marginBottom = margin
++ scanp += 2;
++ matchp++;
++ do {
++ ++scanp
++ }while(zip_window[scanp] === zip_window[++matchp] && (zip_window[++scanp] === zip_window[++matchp] && (zip_window[++scanp] === zip_window[++matchp] && (zip_window[++scanp] === zip_window[++matchp] && (zip_window[++scanp] === zip_window[++matchp] && (zip_window[++scanp] === zip_window[++matchp] && (zip_window[++scanp] === zip_window[++matchp] && (zip_window[++scanp] === zip_window[++matchp] && scanp < strendp))))))));
++ len = zip_MAX_MATCH - (strendp - scanp);
++ scanp = strendp - zip_MAX_MATCH;
++ if(len > best_len) {
++ zip_match_start = cur_match;
++ best_len = len;
++ if(zip_FULL_SEARCH) {
++ if(len >= zip_MAX_MATCH) {
++ break
++ }
++ }else {
++ if(len >= zip_nice_match) {
++ break
++ }
++ }
++ scan_end1 = zip_window[scanp + best_len - 1];
++ scan_end = zip_window[scanp + best_len]
+ }
- padding = lengthInCm(props.getAttributeNS(fons, "padding"), null);
- if(padding === null) {
- paddingLeft = lengthInCm(props.getAttributeNS(fons, "padding-left"), defaultPageFormatSettings.padding);
- paddingRight = lengthInCm(props.getAttributeNS(fons, "padding-right"), defaultPageFormatSettings.padding);
- paddingTop = lengthInCm(props.getAttributeNS(fons, "padding-top"), defaultPageFormatSettings.padding);
- paddingBottom = lengthInCm(props.getAttributeNS(fons, "padding-bottom"), defaultPageFormatSettings.padding)
- }else {
- paddingLeft = paddingRight = paddingTop = paddingBottom = padding
++ cur_match = zip_prev[cur_match & zip_WMASK]
++ }while(cur_match > limit && --chain_length !== 0);
++ return best_len
++ };
++ var zip_ct_tally = function(dist, lc) {
++ zip_l_buf[zip_last_lit++] = lc;
++ if(dist === 0) {
++ zip_dyn_ltree[lc].fc++
++ }else {
++ dist--;
++ zip_dyn_ltree[zip_length_code[lc] + zip_LITERALS + 1].fc++;
++ zip_dyn_dtree[zip_D_CODE(dist)].fc++;
++ zip_d_buf[zip_last_dist++] = dist;
++ zip_flags |= zip_flag_bit
++ }
++ zip_flag_bit <<= 1;
++ if((zip_last_lit & 7) === 0) {
++ zip_flag_buf[zip_last_flags++] = zip_flags;
++ zip_flags = 0;
++ zip_flag_bit = 1
++ }
++ if(zip_compr_level > 2 && (zip_last_lit & 4095) === 0) {
++ var out_length = zip_last_lit * 8;
++ var in_length = zip_strstart - zip_block_start;
++ var dcode;
++ for(dcode = 0;dcode < zip_D_CODES;dcode++) {
++ out_length += zip_dyn_dtree[dcode].fc * (5 + zip_extra_dbits[dcode])
++ }
++ out_length >>= 3;
++ if(zip_last_dist < parseInt(zip_last_lit / 2, 10) && out_length < parseInt(in_length / 2, 10)) {
++ return true
+ }
+ }
- return{width:pageWidth - marginLeft - marginRight - paddingLeft - paddingRight, height:pageHeight - marginTop - marginBottom - paddingTop - paddingBottom}
- }
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- runtime.loadClass("core.DomUtils");
- runtime.loadClass("odf.OdfContainer");
- runtime.loadClass("odf.Formatting");
- runtime.loadClass("xmldom.XPath");
- runtime.loadClass("odf.FontLoader");
- runtime.loadClass("odf.Style2CSS");
- runtime.loadClass("odf.OdfUtils");
- runtime.loadClass("gui.AnnotationViewManager");
- odf.OdfCanvas = function() {
- function LoadingQueue() {
- var queue = [], taskRunning = false;
- function run(task) {
- taskRunning = true;
- runtime.setTimeout(function() {
- try {
- task()
- }catch(e) {
- runtime.log(e)
- }
- taskRunning = false;
- if(queue.length > 0) {
- run(queue.pop())
- }
- }, 10)
- }
- this.clearQueue = function() {
- queue.length = 0
- };
- this.addToQueue = function(loadingTask) {
- if(queue.length === 0 && !taskRunning) {
- return run(loadingTask)
++ return zip_last_lit === zip_LIT_BUFSIZE - 1 || zip_last_dist === zip_DIST_BUFSIZE
++ };
++ var zip_pqdownheap = function(tree, k) {
++ var v = zip_heap[k];
++ var j = k << 1;
++ while(j <= zip_heap_len) {
++ if(j < zip_heap_len && zip_SMALLER(tree, zip_heap[j + 1], zip_heap[j])) {
++ j++
+ }
- queue.push(loadingTask)
- }
- }
- function PageSwitcher(css) {
- var sheet = css.sheet, position = 1;
- function updateCSS() {
- while(sheet.cssRules.length > 0) {
- sheet.deleteRule(0)
++ if(zip_SMALLER(tree, v, zip_heap[j])) {
++ break
+ }
- sheet.insertRule("#shadowContent draw|page {display:none;}", 0);
- sheet.insertRule("office|presentation draw|page {display:none;}", 1);
- sheet.insertRule("#shadowContent draw|page:nth-of-type(" + position + ") {display:block;}", 2);
- sheet.insertRule("office|presentation draw|page:nth-of-type(" + position + ") {display:block;}", 3)
++ zip_heap[k] = zip_heap[j];
++ k = j;
++ j <<= 1
+ }
- this.showFirstPage = function() {
- position = 1;
- updateCSS()
- };
- this.showNextPage = function() {
- position += 1;
- updateCSS()
- };
- this.showPreviousPage = function() {
- if(position > 1) {
- position -= 1;
- updateCSS()
- }
- };
- this.showPage = function(n) {
- if(n > 0) {
- position = n;
- updateCSS()
- }
- };
- this.css = css;
- this.destroy = function(callback) {
- css.parentNode.removeChild(css);
- callback()
++ zip_heap[k] = v
++ };
++ var zip_gen_bitlen = function(desc) {
++ var tree = desc.dyn_tree;
++ var extra = desc.extra_bits;
++ var base = desc.extra_base;
++ var max_code = desc.max_code;
++ var max_length = desc.max_length;
++ var stree = desc.static_tree;
++ var h;
++ var n, m;
++ var bits;
++ var xbits;
++ var f;
++ var overflow = 0;
++ for(bits = 0;bits <= zip_MAX_BITS;bits++) {
++ zip_bl_count[bits] = 0
+ }
- }
- function listenEvent(eventTarget, eventType, eventHandler) {
- if(eventTarget.addEventListener) {
- eventTarget.addEventListener(eventType, eventHandler, false)
- }else {
- if(eventTarget.attachEvent) {
- eventType = "on" + eventType;
- eventTarget.attachEvent(eventType, eventHandler)
- }else {
- eventTarget["on" + eventType] = eventHandler
++ tree[zip_heap[zip_heap_max]].dl = 0;
++ for(h = zip_heap_max + 1;h < zip_HEAP_SIZE;h++) {
++ n = zip_heap[h];
++ bits = tree[tree[n].dl].dl + 1;
++ if(bits > max_length) {
++ bits = max_length;
++ overflow++
+ }
- }
- }
- function removeEvent(eventTarget, eventType, eventHandler) {
- var onVariant = "on" + eventType;
- if(eventTarget.removeEventListener) {
- eventTarget.removeEventListener(eventType, eventHandler, false)
- }else {
- if(eventTarget.detachEvent) {
- eventTarget.detachEvent(onVariant, eventHandler)
- }else {
- if(eventTarget[onVariant] === eventHandler) {
- eventTarget[onVariant] = null
- }
++ tree[n].dl = bits;
++ if(n > max_code) {
++ continue
+ }
- }
- }
- function SelectionWatcher(element) {
- var selection = [], listeners = [];
- function isAncestorOf(ancestor, descendant) {
- while(descendant) {
- if(descendant === ancestor) {
- return true
- }
- descendant = descendant.parentNode
++ zip_bl_count[bits]++;
++ xbits = 0;
++ if(n >= base) {
++ xbits = extra[n - base]
++ }
++ f = tree[n].fc;
++ zip_opt_len += f * (bits + xbits);
++ if(stree !== null) {
++ zip_static_len += f * (stree[n].dl + xbits)
+ }
- return false
+ }
- function fallsWithin(element, range) {
- return isAncestorOf(element, range.startContainer) && isAncestorOf(element, range.endContainer)
++ if(overflow === 0) {
++ return
+ }
- function getCurrentSelection() {
- var s = [], current = runtime.getWindow().getSelection(), i, r;
- for(i = 0;i < current.rangeCount;i += 1) {
- r = current.getRangeAt(i);
- if(r !== null && fallsWithin(element, r)) {
- s.push(r)
++ do {
++ bits = max_length - 1;
++ while(zip_bl_count[bits] === 0) {
++ bits--
++ }
++ zip_bl_count[bits]--;
++ zip_bl_count[bits + 1] += 2;
++ zip_bl_count[max_length]--;
++ overflow -= 2
++ }while(overflow > 0);
++ for(bits = max_length;bits !== 0;bits--) {
++ n = zip_bl_count[bits];
++ while(n !== 0) {
++ m = zip_heap[--h];
++ if(m > max_code) {
++ continue
++ }
++ if(tree[m].dl !== bits) {
++ zip_opt_len += (bits - tree[m].dl) * tree[m].fc;
++ tree[m].fc = bits
+ }
++ n--
+ }
- return s
+ }
- function rangesNotEqual(rangeA, rangeB) {
- if(rangeA === rangeB) {
- return false
- }
- if(rangeA === null || rangeB === null) {
- return true
++ };
++ var zip_bi_reverse = function(code, len) {
++ var res = 0;
++ do {
++ res |= code & 1;
++ code >>= 1;
++ res <<= 1
++ }while(--len > 0);
++ return res >> 1
++ };
++ var zip_gen_codes = function(tree, max_code) {
++ var next_code = [];
++ next_code.length = zip_MAX_BITS + 1;
++ var code = 0;
++ var bits;
++ var n;
++ for(bits = 1;bits <= zip_MAX_BITS;bits++) {
++ code = code + zip_bl_count[bits - 1] << 1;
++ next_code[bits] = code
++ }
++ var len;
++ for(n = 0;n <= max_code;n++) {
++ len = tree[n].dl;
++ if(len === 0) {
++ continue
+ }
- return rangeA.startContainer !== rangeB.startContainer || (rangeA.startOffset !== rangeB.startOffset || (rangeA.endContainer !== rangeB.endContainer || rangeA.endOffset !== rangeB.endOffset))
++ tree[n].fc = zip_bi_reverse(next_code[len]++, len)
+ }
- function emitNewSelection() {
- var i, l = listeners.length;
- for(i = 0;i < l;i += 1) {
- listeners[i](element, selection)
++ };
++ var zip_build_tree = function(desc) {
++ var tree = desc.dyn_tree;
++ var stree = desc.static_tree;
++ var elems = desc.elems;
++ var n, m;
++ var max_code = -1;
++ var node = elems;
++ zip_heap_len = 0;
++ zip_heap_max = zip_HEAP_SIZE;
++ for(n = 0;n < elems;n++) {
++ if(tree[n].fc !== 0) {
++ zip_heap[++zip_heap_len] = max_code = n;
++ zip_depth[n] = 0
++ }else {
++ tree[n].dl = 0
+ }
+ }
- function copySelection(selection) {
- var s = [selection.length], i, oldr, r, doc = element.ownerDocument;
- for(i = 0;i < selection.length;i += 1) {
- oldr = selection[i];
- r = doc.createRange();
- r.setStart(oldr.startContainer, oldr.startOffset);
- r.setEnd(oldr.endContainer, oldr.endOffset);
- s[i] = r
++ var xnew;
++ while(zip_heap_len < 2) {
++ xnew = zip_heap[++zip_heap_len] = max_code < 2 ? ++max_code : 0;
++ tree[xnew].fc = 1;
++ zip_depth[xnew] = 0;
++ zip_opt_len--;
++ if(stree !== null) {
++ zip_static_len -= stree[xnew].dl
+ }
- return s
+ }
- function checkSelection() {
- var s = getCurrentSelection(), i;
- if(s.length === selection.length) {
- for(i = 0;i < s.length;i += 1) {
- if(rangesNotEqual(s[i], selection[i])) {
- break
++ desc.max_code = max_code;
++ for(n = zip_heap_len >> 1;n >= 1;n--) {
++ zip_pqdownheap(tree, n)
++ }
++ do {
++ n = zip_heap[zip_SMALLEST];
++ zip_heap[zip_SMALLEST] = zip_heap[zip_heap_len--];
++ zip_pqdownheap(tree, zip_SMALLEST);
++ m = zip_heap[zip_SMALLEST];
++ zip_heap[--zip_heap_max] = n;
++ zip_heap[--zip_heap_max] = m;
++ tree[node].fc = tree[n].fc + tree[m].fc;
++ if(zip_depth[n] > zip_depth[m] + 1) {
++ zip_depth[node] = zip_depth[n]
++ }else {
++ zip_depth[node] = zip_depth[m] + 1
++ }
++ tree[n].dl = tree[m].dl = node;
++ zip_heap[zip_SMALLEST] = node++;
++ zip_pqdownheap(tree, zip_SMALLEST)
++ }while(zip_heap_len >= 2);
++ zip_heap[--zip_heap_max] = zip_heap[zip_SMALLEST];
++ zip_gen_bitlen(desc);
++ zip_gen_codes(tree, max_code)
++ };
++ var zip_scan_tree = function(tree, max_code) {
++ var n;
++ var prevlen = -1;
++ var curlen;
++ var nextlen = tree[0].dl;
++ var count = 0;
++ var max_count = 7;
++ var min_count = 4;
++ if(nextlen === 0) {
++ max_count = 138;
++ min_count = 3
++ }
++ tree[max_code + 1].dl = 65535;
++ for(n = 0;n <= max_code;n++) {
++ curlen = nextlen;
++ nextlen = tree[n + 1].dl;
++ if(++count < max_count && curlen === nextlen) {
++ continue
++ }
++ if(count < min_count) {
++ zip_bl_tree[curlen].fc += count
++ }else {
++ if(curlen !== 0) {
++ if(curlen !== prevlen) {
++ zip_bl_tree[curlen].fc++
++ }
++ zip_bl_tree[zip_REP_3_6].fc++
++ }else {
++ if(count <= 10) {
++ zip_bl_tree[zip_REPZ_3_10].fc++
++ }else {
++ zip_bl_tree[zip_REPZ_11_138].fc++
+ }
- }
- if(i === s.length) {
- return
+ }
+ }
- selection = s;
- selection = copySelection(s);
- emitNewSelection()
- }
- this.addListener = function(eventName, handler) {
- var i, l = listeners.length;
- for(i = 0;i < l;i += 1) {
- if(listeners[i] === handler) {
- return
++ count = 0;
++ prevlen = curlen;
++ if(nextlen === 0) {
++ max_count = 138;
++ min_count = 3
++ }else {
++ if(curlen === nextlen) {
++ max_count = 6;
++ min_count = 3
++ }else {
++ max_count = 7;
++ min_count = 4
+ }
+ }
- listeners.push(handler)
- };
- this.destroy = function(callback) {
- removeEvent(element, "mouseup", checkSelection);
- removeEvent(element, "keyup", checkSelection);
- removeEvent(element, "keydown", checkSelection);
- callback()
- };
- listenEvent(element, "mouseup", checkSelection);
- listenEvent(element, "keyup", checkSelection);
- listenEvent(element, "keydown", checkSelection)
- }
- var drawns = odf.Namespaces.drawns, fons = odf.Namespaces.fons, officens = odf.Namespaces.officens, stylens = odf.Namespaces.stylens, svgns = odf.Namespaces.svgns, tablens = odf.Namespaces.tablens, textns = odf.Namespaces.textns, xlinkns = odf.Namespaces.xlinkns, xmlns = odf.Namespaces.xmlns, presentationns = odf.Namespaces.presentationns, webodfhelperns = "urn:webodf:names:helper", window = runtime.getWindow(), xpath = new xmldom.XPath, odfUtils = new odf.OdfUtils, domUtils = new cor [...]
- function clear(element) {
- while(element.firstChild) {
- element.removeChild(element.firstChild)
- }
- }
- function handleStyles(odfcontainer, formatting, stylesxmlcss) {
- var style2css = new odf.Style2CSS;
- style2css.style2css(odfcontainer.getDocumentType(), stylesxmlcss.sheet, formatting.getFontMap(), odfcontainer.rootElement.styles, odfcontainer.rootElement.automaticStyles)
- }
- function handleFonts(odfContainer, fontcss) {
- var fontLoader = new odf.FontLoader;
- fontLoader.loadFonts(odfContainer, fontcss.sheet)
- }
- function getMasterPageElement(odfContainer, masterPageName) {
- if(!masterPageName) {
- return null
+ }
- var masterStyles = odfContainer.rootElement.masterStyles, masterPageElements = masterStyles.getElementsByTagNameNS(stylens, "master-page"), masterPageElement = null, i;
- for(i = 0;i < masterPageElements.length;i += 1) {
- if(masterPageElements[i].getAttributeNS(stylens, "name") === masterPageName) {
- masterPageElement = masterPageElements[i];
++ };
++ var zip_build_bl_tree = function() {
++ var max_blindex;
++ zip_scan_tree(zip_dyn_ltree, zip_l_desc.max_code);
++ zip_scan_tree(zip_dyn_dtree, zip_d_desc.max_code);
++ zip_build_tree(zip_bl_desc);
++ for(max_blindex = zip_BL_CODES - 1;max_blindex >= 3;max_blindex--) {
++ if(zip_bl_tree[zip_bl_order[max_blindex]].dl !== 0) {
+ break
+ }
+ }
- return masterPageElement
- }
- function dropTemplateDrawFrames(clonedNode) {
- var i, element, presentationClass, clonedDrawFrameElements = clonedNode.getElementsByTagNameNS(drawns, "frame");
- for(i = 0;i < clonedDrawFrameElements.length;i += 1) {
- element = clonedDrawFrameElements[i];
- presentationClass = element.getAttributeNS(presentationns, "class");
- if(presentationClass && !/^(date-time|footer|header|page-number')$/.test(presentationClass)) {
- element.parentNode.removeChild(element)
++ zip_opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
++ return max_blindex
++ };
++ var zip_bi_windup = function() {
++ if(zip_bi_valid > 8) {
++ zip_put_short(zip_bi_buf)
++ }else {
++ if(zip_bi_valid > 0) {
++ zip_put_byte(zip_bi_buf)
+ }
+ }
- }
- function getHeaderFooter(odfContainer, frame, headerFooterId) {
- var headerFooter = null, i, declElements = odfContainer.rootElement.body.getElementsByTagNameNS(presentationns, headerFooterId + "-decl"), headerFooterName = frame.getAttributeNS(presentationns, "use-" + headerFooterId + "-name");
- if(headerFooterName && declElements.length > 0) {
- for(i = 0;i < declElements.length;i += 1) {
- if(declElements[i].getAttributeNS(presentationns, "name") === headerFooterName) {
- headerFooter = declElements[i].textContent;
- break
++ zip_bi_buf = 0;
++ zip_bi_valid = 0
++ };
++ var zip_compress_block = function(ltree, dtree) {
++ var dist;
++ var lc;
++ var lx = 0;
++ var dx = 0;
++ var fx = 0;
++ var flag = 0;
++ var code;
++ var extra;
++ if(zip_last_lit !== 0) {
++ do {
++ if((lx & 7) === 0) {
++ flag = zip_flag_buf[fx++]
+ }
- }
++ lc = zip_l_buf[lx++] & 255;
++ if((flag & 1) === 0) {
++ zip_SEND_CODE(lc, ltree)
++ }else {
++ code = zip_length_code[lc];
++ zip_SEND_CODE(code + zip_LITERALS + 1, ltree);
++ extra = zip_extra_lbits[code];
++ if(extra !== 0) {
++ lc -= zip_base_length[code];
++ zip_send_bits(lc, extra)
++ }
++ dist = zip_d_buf[dx++];
++ code = zip_D_CODE(dist);
++ zip_SEND_CODE(code, dtree);
++ extra = zip_extra_dbits[code];
++ if(extra !== 0) {
++ dist -= zip_base_dist[code];
++ zip_send_bits(dist, extra)
++ }
++ }
++ flag >>= 1
++ }while(lx < zip_last_lit)
+ }
- return headerFooter
- }
- function setContainerValue(rootElement, ns, localName, value) {
- var i, containerList, document = rootElement.ownerDocument;
- containerList = rootElement.getElementsByTagNameNS(ns, localName);
- for(i = 0;i < containerList.length;i += 1) {
- clear(containerList[i]);
- if(value) {
- containerList[i].appendChild(document.createTextNode(value))
- }
++ zip_SEND_CODE(zip_END_BLOCK, ltree)
++ };
++ var zip_send_tree = function(tree, max_code) {
++ var n;
++ var prevlen = -1;
++ var curlen;
++ var nextlen = tree[0].dl;
++ var count = 0;
++ var max_count = 7;
++ var min_count = 4;
++ if(nextlen === 0) {
++ max_count = 138;
++ min_count = 3
+ }
- }
- function setDrawElementPosition(styleid, frame, stylesheet) {
- frame.setAttributeNS(webodfhelperns, "styleid", styleid);
- var rule, anchor = frame.getAttributeNS(textns, "anchor-type"), x = frame.getAttributeNS(svgns, "x"), y = frame.getAttributeNS(svgns, "y"), width = frame.getAttributeNS(svgns, "width"), height = frame.getAttributeNS(svgns, "height"), minheight = frame.getAttributeNS(fons, "min-height"), minwidth = frame.getAttributeNS(fons, "min-width");
- if(anchor === "as-char") {
- rule = "display: inline-block;"
- }else {
- if(anchor || (x || y)) {
- rule = "position: absolute;"
++ for(n = 0;n <= max_code;n++) {
++ curlen = nextlen;
++ nextlen = tree[n + 1].dl;
++ if(++count < max_count && curlen === nextlen) {
++ continue
++ }
++ if(count < min_count) {
++ do {
++ zip_SEND_CODE(curlen, zip_bl_tree)
++ }while(--count !== 0)
+ }else {
- if(width || (height || (minheight || minwidth))) {
- rule = "display: block;"
++ if(curlen !== 0) {
++ if(curlen !== prevlen) {
++ zip_SEND_CODE(curlen, zip_bl_tree);
++ count--
++ }
++ zip_SEND_CODE(zip_REP_3_6, zip_bl_tree);
++ zip_send_bits(count - 3, 2)
++ }else {
++ if(count <= 10) {
++ zip_SEND_CODE(zip_REPZ_3_10, zip_bl_tree);
++ zip_send_bits(count - 3, 3)
++ }else {
++ zip_SEND_CODE(zip_REPZ_11_138, zip_bl_tree);
++ zip_send_bits(count - 11, 7)
++ }
++ }
++ }
++ count = 0;
++ prevlen = curlen;
++ if(nextlen === 0) {
++ max_count = 138;
++ min_count = 3
++ }else {
++ if(curlen === nextlen) {
++ max_count = 6;
++ min_count = 3
++ }else {
++ max_count = 7;
++ min_count = 4
+ }
+ }
+ }
- if(x) {
- rule += "left: " + x + ";"
++ };
++ var zip_send_all_trees = function(lcodes, dcodes, blcodes) {
++ var rank;
++ zip_send_bits(lcodes - 257, 5);
++ zip_send_bits(dcodes - 1, 5);
++ zip_send_bits(blcodes - 4, 4);
++ for(rank = 0;rank < blcodes;rank++) {
++ zip_send_bits(zip_bl_tree[zip_bl_order[rank]].dl, 3)
+ }
- if(y) {
- rule += "top: " + y + ";"
++ zip_send_tree(zip_dyn_ltree, lcodes - 1);
++ zip_send_tree(zip_dyn_dtree, dcodes - 1)
++ };
++ var zip_init_block = function() {
++ var n;
++ for(n = 0;n < zip_L_CODES;n++) {
++ zip_dyn_ltree[n].fc = 0
+ }
- if(width) {
- rule += "width: " + width + ";"
- }
- if(height) {
- rule += "height: " + height + ";"
- }
- if(minheight) {
- rule += "min-height: " + minheight + ";"
- }
- if(minwidth) {
- rule += "min-width: " + minwidth + ";"
- }
- if(rule) {
- rule = "draw|" + frame.localName + '[webodfhelper|styleid="' + styleid + '"] {' + rule + "}";
- stylesheet.insertRule(rule, stylesheet.cssRules.length)
++ for(n = 0;n < zip_D_CODES;n++) {
++ zip_dyn_dtree[n].fc = 0
+ }
- }
- function getUrlFromBinaryDataElement(image) {
- var node = image.firstChild;
- while(node) {
- if(node.namespaceURI === officens && node.localName === "binary-data") {
- return"data:image/png;base64," + node.textContent.replace(/[\r\n\s]/g, "")
- }
- node = node.nextSibling
++ for(n = 0;n < zip_BL_CODES;n++) {
++ zip_bl_tree[n].fc = 0
+ }
- return""
- }
- function setImage(id, container, image, stylesheet) {
- image.setAttributeNS(webodfhelperns, "styleid", id);
- var url = image.getAttributeNS(xlinkns, "href"), part;
- function callback(url) {
- var rule;
- if(url) {
- rule = "background-image: url(" + url + ");";
- rule = 'draw|image[webodfhelper|styleid="' + id + '"] {' + rule + "}";
- stylesheet.insertRule(rule, stylesheet.cssRules.length)
- }
++ zip_dyn_ltree[zip_END_BLOCK].fc = 1;
++ zip_opt_len = zip_static_len = 0;
++ zip_last_lit = zip_last_dist = zip_last_flags = 0;
++ zip_flags = 0;
++ zip_flag_bit = 1
++ };
++ var zip_flush_block = function(eof) {
++ var opt_lenb, static_lenb;
++ var max_blindex;
++ var stored_len;
++ stored_len = zip_strstart - zip_block_start;
++ zip_flag_buf[zip_last_flags] = zip_flags;
++ zip_build_tree(zip_l_desc);
++ zip_build_tree(zip_d_desc);
++ max_blindex = zip_build_bl_tree();
++ opt_lenb = zip_opt_len + 3 + 7 >> 3;
++ static_lenb = zip_static_len + 3 + 7 >> 3;
++ if(static_lenb <= opt_lenb) {
++ opt_lenb = static_lenb
+ }
- if(url) {
- try {
- part = container.getPart(url);
- part.onchange = function(part) {
- callback(part.url)
- };
- part.load()
- }catch(e) {
- runtime.log("slight problem: " + e)
++ if(stored_len + 4 <= opt_lenb && zip_block_start >= 0) {
++ var i;
++ zip_send_bits((zip_STORED_BLOCK << 1) + eof, 3);
++ zip_bi_windup();
++ zip_put_short(stored_len);
++ zip_put_short(~stored_len);
++ for(i = 0;i < stored_len;i++) {
++ zip_put_byte(zip_window[zip_block_start + i])
+ }
+ }else {
- url = getUrlFromBinaryDataElement(image);
- callback(url)
- }
- }
- function formatParagraphAnchors(odfbody) {
- var n, i, nodes = xpath.getODFElementsWithXPath(odfbody, ".//*[*[@text:anchor-type='paragraph']]", odf.Namespaces.resolvePrefix);
- for(i = 0;i < nodes.length;i += 1) {
- n = nodes[i];
- if(n.setAttributeNS) {
- n.setAttributeNS(webodfhelperns, "containsparagraphanchor", true)
- }
- }
- }
- function modifyTables(odffragment) {
- var i, tableCells, node;
- function modifyTableCell(node) {
- if(node.hasAttributeNS(tablens, "number-columns-spanned")) {
- node.setAttribute("colspan", node.getAttributeNS(tablens, "number-columns-spanned"))
- }
- if(node.hasAttributeNS(tablens, "number-rows-spanned")) {
- node.setAttribute("rowspan", node.getAttributeNS(tablens, "number-rows-spanned"))
++ if(static_lenb === opt_lenb) {
++ zip_send_bits((zip_STATIC_TREES << 1) + eof, 3);
++ zip_compress_block(zip_static_ltree, zip_static_dtree)
++ }else {
++ zip_send_bits((zip_DYN_TREES << 1) + eof, 3);
++ zip_send_all_trees(zip_l_desc.max_code + 1, zip_d_desc.max_code + 1, max_blindex + 1);
++ zip_compress_block(zip_dyn_ltree, zip_dyn_dtree)
+ }
+ }
- tableCells = odffragment.getElementsByTagNameNS(tablens, "table-cell");
- for(i = 0;i < tableCells.length;i += 1) {
- node = (tableCells.item(i));
- modifyTableCell(node)
++ zip_init_block();
++ if(eof !== 0) {
++ zip_bi_windup()
+ }
- }
- function modifyLinks(odffragment) {
- var i, links, node;
- function modifyLink(node) {
- var url, clickHandler;
- if(!node.hasAttributeNS(xlinkns, "href")) {
- return
++ };
++ var zip_deflate_fast = function() {
++ var flush;
++ while(zip_lookahead !== 0 && zip_qhead === null) {
++ zip_INSERT_STRING();
++ if(zip_hash_head !== zip_NIL && zip_strstart - zip_hash_head <= zip_MAX_DIST) {
++ zip_match_length = zip_longest_match(zip_hash_head);
++ if(zip_match_length > zip_lookahead) {
++ zip_match_length = zip_lookahead
++ }
+ }
- url = node.getAttributeNS(xlinkns, "href");
- if(url[0] === "#") {
- url = url.substring(1);
- clickHandler = function() {
- var bookmarks = xpath.getODFElementsWithXPath(odffragment, "//text:bookmark-start[@text:name='" + url + "']", odf.Namespaces.resolvePrefix);
- if(bookmarks.length === 0) {
- bookmarks = xpath.getODFElementsWithXPath(odffragment, "//text:bookmark[@text:name='" + url + "']", odf.Namespaces.resolvePrefix)
- }
- if(bookmarks.length > 0) {
- bookmarks[0].scrollIntoView(true)
- }
- return false
++ if(zip_match_length >= zip_MIN_MATCH) {
++ flush = zip_ct_tally(zip_strstart - zip_match_start, zip_match_length - zip_MIN_MATCH);
++ zip_lookahead -= zip_match_length;
++ if(zip_match_length <= zip_max_lazy_match) {
++ zip_match_length--;
++ do {
++ zip_strstart++;
++ zip_INSERT_STRING()
++ }while(--zip_match_length !== 0);
++ zip_strstart++
++ }else {
++ zip_strstart += zip_match_length;
++ zip_match_length = 0;
++ zip_ins_h = zip_window[zip_strstart] & 255;
++ zip_ins_h = (zip_ins_h << zip_H_SHIFT ^ zip_window[zip_strstart + 1] & 255) & zip_HASH_MASK
+ }
+ }else {
- clickHandler = function() {
- window.open(url)
- }
- }
- node.onclick = clickHandler
- }
- links = odffragment.getElementsByTagNameNS(textns, "a");
- for(i = 0;i < links.length;i += 1) {
- node = (links.item(i));
- modifyLink(node)
- }
- }
- function modifyLineBreakElements(odffragment) {
- var document = odffragment.ownerDocument, lineBreakElements = domUtils.getElementsByTagNameNS(odffragment, textns, "line-break");
- lineBreakElements.forEach(function(lineBreak) {
- if(!lineBreak.hasChildNodes()) {
- lineBreak.appendChild(document.createElement("br"))
++ flush = zip_ct_tally(0, zip_window[zip_strstart] & 255);
++ zip_lookahead--;
++ zip_strstart++
+ }
- })
- }
- function expandSpaceElements(odffragment) {
- var spaces, doc = odffragment.ownerDocument;
- function expandSpaceElement(space) {
- var j, count;
- while(space.firstChild) {
- space.removeChild(space.firstChild)
++ if(flush) {
++ zip_flush_block(0);
++ zip_block_start = zip_strstart
+ }
- space.appendChild(doc.createTextNode(" "));
- count = parseInt(space.getAttributeNS(textns, "c"), 10);
- if(count > 1) {
- space.removeAttributeNS(textns, "c");
- for(j = 1;j < count;j += 1) {
- space.parentNode.insertBefore(space.cloneNode(true), space)
- }
++ while(zip_lookahead < zip_MIN_LOOKAHEAD && !zip_eofile) {
++ zip_fill_window()
+ }
+ }
- spaces = domUtils.getElementsByTagNameNS(odffragment, textns, "s");
- spaces.forEach(expandSpaceElement)
- }
- function expandTabElements(odffragment) {
- var tabs;
- tabs = domUtils.getElementsByTagNameNS(odffragment, textns, "tab");
- tabs.forEach(function(tab) {
- tab.textContent = "\t"
- })
- }
- function modifyDrawElements(odfbody, stylesheet) {
- var node, drawElements, i;
- drawElements = [];
- node = odfbody.firstChild;
- while(node && node !== odfbody) {
- if(node.namespaceURI === drawns) {
- drawElements[drawElements.length] = node
++ };
++ var zip_deflate_better = function() {
++ var flush;
++ while(zip_lookahead !== 0 && zip_qhead === null) {
++ zip_INSERT_STRING();
++ zip_prev_length = zip_match_length;
++ zip_prev_match = zip_match_start;
++ zip_match_length = zip_MIN_MATCH - 1;
++ if(zip_hash_head !== zip_NIL && (zip_prev_length < zip_max_lazy_match && zip_strstart - zip_hash_head <= zip_MAX_DIST)) {
++ zip_match_length = zip_longest_match(zip_hash_head);
++ if(zip_match_length > zip_lookahead) {
++ zip_match_length = zip_lookahead
++ }
++ if(zip_match_length === zip_MIN_MATCH && zip_strstart - zip_match_start > zip_TOO_FAR) {
++ zip_match_length--
++ }
+ }
- if(node.firstChild) {
- node = node.firstChild
- }else {
- while(node && (node !== odfbody && !node.nextSibling)) {
- node = node.parentNode
++ if(zip_prev_length >= zip_MIN_MATCH && zip_match_length <= zip_prev_length) {
++ flush = zip_ct_tally(zip_strstart - 1 - zip_prev_match, zip_prev_length - zip_MIN_MATCH);
++ zip_lookahead -= zip_prev_length - 1;
++ zip_prev_length -= 2;
++ do {
++ zip_strstart++;
++ zip_INSERT_STRING()
++ }while(--zip_prev_length !== 0);
++ zip_match_available = 0;
++ zip_match_length = zip_MIN_MATCH - 1;
++ zip_strstart++;
++ if(flush) {
++ zip_flush_block(0);
++ zip_block_start = zip_strstart
+ }
- if(node && node.nextSibling) {
- node = node.nextSibling
++ }else {
++ if(zip_match_available !== 0) {
++ if(zip_ct_tally(0, zip_window[zip_strstart - 1] & 255)) {
++ zip_flush_block(0);
++ zip_block_start = zip_strstart
++ }
++ zip_strstart++;
++ zip_lookahead--
++ }else {
++ zip_match_available = 1;
++ zip_strstart++;
++ zip_lookahead--
+ }
+ }
++ while(zip_lookahead < zip_MIN_LOOKAHEAD && !zip_eofile) {
++ zip_fill_window()
++ }
+ }
- for(i = 0;i < drawElements.length;i += 1) {
- node = drawElements[i];
- setDrawElementPosition("frame" + String(i), node, stylesheet)
++ };
++ var zip_ct_init = function() {
++ var n;
++ var bits;
++ var length;
++ var code;
++ var dist;
++ if(zip_static_dtree[0].dl !== 0) {
++ return
+ }
- formatParagraphAnchors(odfbody)
- }
- function cloneMasterPages(odfContainer, shadowContent, odfbody, stylesheet) {
- var masterPageName, masterPageElement, styleId, clonedPageElement, clonedElement, pageNumber = 0, i, element, elementToClone, document = odfContainer.rootElement.ownerDocument;
- element = odfbody.firstElementChild;
- if(!(element && (element.namespaceURI === officens && (element.localName === "presentation" || element.localName === "drawing")))) {
- return
- }
- element = element.firstElementChild;
- while(element) {
- masterPageName = element.getAttributeNS(drawns, "master-page-name");
- masterPageElement = getMasterPageElement(odfContainer, masterPageName);
- if(masterPageElement) {
- styleId = element.getAttributeNS(webodfhelperns, "styleid");
- clonedPageElement = document.createElementNS(drawns, "draw:page");
- elementToClone = masterPageElement.firstElementChild;
- i = 0;
- while(elementToClone) {
- if(elementToClone.getAttributeNS(presentationns, "placeholder") !== "true") {
- clonedElement = elementToClone.cloneNode(true);
- clonedPageElement.appendChild(clonedElement);
- setDrawElementPosition(styleId + "_" + i, (clonedElement), stylesheet)
- }
- elementToClone = elementToClone.nextElementSibling;
- i += 1
- }
- dropTemplateDrawFrames(clonedPageElement);
- shadowContent.appendChild(clonedPageElement);
- pageNumber = String(shadowContent.getElementsByTagNameNS(drawns, "page").length);
- setContainerValue(clonedPageElement, textns, "page-number", pageNumber);
- setContainerValue(clonedPageElement, presentationns, "header", getHeaderFooter(odfContainer, (element), "header"));
- setContainerValue(clonedPageElement, presentationns, "footer", getHeaderFooter(odfContainer, (element), "footer"));
- setDrawElementPosition(styleId, clonedPageElement, stylesheet);
- clonedPageElement.setAttributeNS(drawns, "draw:master-page-name", masterPageElement.getAttributeNS(stylens, "name"))
++ zip_l_desc.dyn_tree = zip_dyn_ltree;
++ zip_l_desc.static_tree = zip_static_ltree;
++ zip_l_desc.extra_bits = zip_extra_lbits;
++ zip_l_desc.extra_base = zip_LITERALS + 1;
++ zip_l_desc.elems = zip_L_CODES;
++ zip_l_desc.max_length = zip_MAX_BITS;
++ zip_l_desc.max_code = 0;
++ zip_d_desc.dyn_tree = zip_dyn_dtree;
++ zip_d_desc.static_tree = zip_static_dtree;
++ zip_d_desc.extra_bits = zip_extra_dbits;
++ zip_d_desc.extra_base = 0;
++ zip_d_desc.elems = zip_D_CODES;
++ zip_d_desc.max_length = zip_MAX_BITS;
++ zip_d_desc.max_code = 0;
++ zip_bl_desc.dyn_tree = zip_bl_tree;
++ zip_bl_desc.static_tree = null;
++ zip_bl_desc.extra_bits = zip_extra_blbits;
++ zip_bl_desc.extra_base = 0;
++ zip_bl_desc.elems = zip_BL_CODES;
++ zip_bl_desc.max_length = zip_MAX_BL_BITS;
++ zip_bl_desc.max_code = 0;
++ length = 0;
++ for(code = 0;code < zip_LENGTH_CODES - 1;code++) {
++ zip_base_length[code] = length;
++ for(n = 0;n < 1 << zip_extra_lbits[code];n++) {
++ zip_length_code[length++] = code
+ }
- element = element.nextElementSibling
+ }
- }
- function setVideo(container, plugin) {
- var video, source, url, doc = plugin.ownerDocument, part;
- url = plugin.getAttributeNS(xlinkns, "href");
- function callback(url, mimetype) {
- var ns = doc.documentElement.namespaceURI;
- if(mimetype.substr(0, 6) === "video/") {
- video = doc.createElementNS(ns, "video");
- video.setAttribute("controls", "controls");
- source = doc.createElementNS(ns, "source");
- source.setAttribute("src", url);
- source.setAttribute("type", mimetype);
- video.appendChild(source);
- plugin.parentNode.appendChild(video)
- }else {
- plugin.innerHtml = "Unrecognised Plugin"
++ zip_length_code[length - 1] = code;
++ dist = 0;
++ for(code = 0;code < 16;code++) {
++ zip_base_dist[code] = dist;
++ for(n = 0;n < 1 << zip_extra_dbits[code];n++) {
++ zip_dist_code[dist++] = code
+ }
+ }
- if(url) {
- try {
- part = container.getPart(url);
- part.onchange = function(part) {
- callback(part.url, part.mimetype)
- };
- part.load()
- }catch(e) {
- runtime.log("slight problem: " + e)
++ dist >>= 7;
++ n = code;
++ for(code = n;code < zip_D_CODES;code++) {
++ zip_base_dist[code] = dist << 7;
++ for(n = 0;n < 1 << zip_extra_dbits[code] - 7;n++) {
++ zip_dist_code[256 + dist++] = code
+ }
- }else {
- runtime.log("using MP4 data fallback");
- url = getUrlFromBinaryDataElement(plugin);
- callback(url, "video/mp4")
+ }
- }
- function getNumberRule(node) {
- var style = node.getAttributeNS(stylens, "num-format"), suffix = node.getAttributeNS(stylens, "num-suffix"), prefix = node.getAttributeNS(stylens, "num-prefix"), rule = "", stylemap = {1:"decimal", "a":"lower-latin", "A":"upper-latin", "i":"lower-roman", "I":"upper-roman"}, content;
- content = prefix || "";
- if(stylemap.hasOwnProperty(style)) {
- content += " counter(list, " + stylemap[style] + ")"
- }else {
- if(style) {
- content += "'" + style + "';"
- }else {
- content += " ''"
- }
++ for(bits = 0;bits <= zip_MAX_BITS;bits++) {
++ zip_bl_count[bits] = 0
+ }
- if(suffix) {
- content += " '" + suffix + "'"
++ n = 0;
++ while(n <= 143) {
++ zip_static_ltree[n++].dl = 8;
++ zip_bl_count[8]++
+ }
- rule = "content: " + content + ";";
- return rule
- }
- function getImageRule() {
- var rule = "content: none;";
- return rule
- }
- function getBulletRule(node) {
- var bulletChar = node.getAttributeNS(textns, "bullet-char");
- return"content: '" + bulletChar + "';"
- }
- function getBulletsRule(node) {
- var itemrule;
- if(node) {
- if(node.localName === "list-level-style-number") {
- itemrule = getNumberRule(node)
- }else {
- if(node.localName === "list-level-style-image") {
- itemrule = getImageRule()
- }else {
- if(node.localName === "list-level-style-bullet") {
- itemrule = getBulletRule(node)
- }
- }
- }
++ while(n <= 255) {
++ zip_static_ltree[n++].dl = 9;
++ zip_bl_count[9]++
+ }
- return itemrule
- }
- function loadLists(odffragment, stylesheet) {
- var i, lists, node, id, continueList, styleName, rule, listMap = {}, parentList, listStyles, listStyleMap = {}, bulletRule;
- listStyles = window.document.getElementsByTagNameNS(textns, "list-style");
- for(i = 0;i < listStyles.length;i += 1) {
- node = (listStyles.item(i));
- styleName = node.getAttributeNS(stylens, "name");
- if(styleName) {
- listStyleMap[styleName] = node
- }
++ while(n <= 279) {
++ zip_static_ltree[n++].dl = 7;
++ zip_bl_count[7]++
+ }
- lists = odffragment.getElementsByTagNameNS(textns, "list");
- for(i = 0;i < lists.length;i += 1) {
- node = (lists.item(i));
- id = node.getAttributeNS(xmlns, "id");
- if(id) {
- continueList = node.getAttributeNS(textns, "continue-list");
- node.setAttribute("id", id);
- rule = "text|list#" + id + " > text|list-item > *:first-child:before {";
- styleName = node.getAttributeNS(textns, "style-name");
- if(styleName) {
- node = listStyleMap[styleName];
- bulletRule = getBulletsRule((odfUtils.getFirstNonWhitespaceChild(node)))
- }
- if(continueList) {
- parentList = listMap[continueList];
- while(parentList) {
- continueList = parentList;
- parentList = listMap[continueList]
- }
- rule += "counter-increment:" + continueList + ";";
- if(bulletRule) {
- bulletRule = bulletRule.replace("list", continueList);
- rule += bulletRule
- }else {
- rule += "content:counter(" + continueList + ");"
- }
- }else {
- continueList = "";
- if(bulletRule) {
- bulletRule = bulletRule.replace("list", id);
- rule += bulletRule
- }else {
- rule += "content: counter(" + id + ");"
- }
- rule += "counter-increment:" + id + ";";
- stylesheet.insertRule("text|list#" + id + " {counter-reset:" + id + "}", stylesheet.cssRules.length)
- }
- rule += "}";
- listMap[id] = continueList;
- if(rule) {
- stylesheet.insertRule(rule, stylesheet.cssRules.length)
- }
- }
++ while(n <= 287) {
++ zip_static_ltree[n++].dl = 8;
++ zip_bl_count[8]++
+ }
- }
- function addWebODFStyleSheet(document) {
- var head = document.getElementsByTagName("head")[0], style, href;
- if(String(typeof webodf_css) !== "undefined") {
- style = document.createElementNS(head.namespaceURI, "style");
- style.setAttribute("media", "screen, print, handheld, projection");
- style.appendChild(document.createTextNode(webodf_css))
++ zip_gen_codes(zip_static_ltree, zip_L_CODES + 1);
++ for(n = 0;n < zip_D_CODES;n++) {
++ zip_static_dtree[n].dl = 5;
++ zip_static_dtree[n].fc = zip_bi_reverse(n, 5)
++ }
++ zip_init_block()
++ };
++ var zip_init_deflate = function() {
++ if(zip_eofile) {
++ return
++ }
++ zip_bi_buf = 0;
++ zip_bi_valid = 0;
++ zip_ct_init();
++ zip_lm_init();
++ zip_qhead = null;
++ zip_outcnt = 0;
++ zip_outoff = 0;
++ if(zip_compr_level <= 3) {
++ zip_prev_length = zip_MIN_MATCH - 1;
++ zip_match_length = 0
+ }else {
- style = document.createElementNS(head.namespaceURI, "link");
- href = "webodf.css";
- if(runtime.currentDirectory) {
- href = runtime.currentDirectory() + "/../" + href
++ zip_match_length = zip_MIN_MATCH - 1;
++ zip_match_available = 0
++ }
++ zip_complete = false
++ };
++ var zip_qcopy = function(buff, off, buff_size) {
++ var n, i, j, p;
++ n = 0;
++ while(zip_qhead !== null && n < buff_size) {
++ i = buff_size - n;
++ if(i > zip_qhead.len) {
++ i = zip_qhead.len
++ }
++ for(j = 0;j < i;j++) {
++ buff[off + n + j] = zip_qhead.ptr[zip_qhead.off + j]
++ }
++ zip_qhead.off += i;
++ zip_qhead.len -= i;
++ n += i;
++ if(zip_qhead.len === 0) {
++ p = zip_qhead;
++ zip_qhead = zip_qhead.next;
++ zip_reuse_queue(p)
+ }
- style.setAttribute("href", href);
- style.setAttribute("rel", "stylesheet")
+ }
- style.setAttribute("type", "text/css");
- head.appendChild(style);
- return(style)
- }
- function addStyleSheet(document) {
- var head = document.getElementsByTagName("head")[0], style = document.createElementNS(head.namespaceURI, "style"), text = "";
- style.setAttribute("type", "text/css");
- style.setAttribute("media", "screen, print, handheld, projection");
- odf.Namespaces.forEachPrefix(function(prefix, ns) {
- text += "@namespace " + prefix + " url(" + ns + ");\n"
- });
- text += "@namespace webodfhelper url(" + webodfhelperns + ");\n";
- style.appendChild(document.createTextNode(text));
- head.appendChild(style);
- return(style)
- }
- odf.OdfCanvas = function OdfCanvas(element) {
- runtime.assert(element !== null && element !== undefined, "odf.OdfCanvas constructor needs DOM element");
- runtime.assert(element.ownerDocument !== null && element.ownerDocument !== undefined, "odf.OdfCanvas constructor needs DOM");
- var self = this, doc = (element.ownerDocument), odfcontainer, formatting = new odf.Formatting, selectionWatcher = new SelectionWatcher(element), pageSwitcher, sizer, annotationsPane, allowAnnotations = false, annotationViewManager, webodfcss, fontcss, stylesxmlcss, positioncss, shadowContent, zoomLevel = 1, eventHandlers = {}, loadingQueue = new LoadingQueue;
- function loadImages(container, odffragment, stylesheet) {
- var i, images, node;
- function loadImage(name, container, node, stylesheet) {
- loadingQueue.addToQueue(function() {
- setImage(name, container, node, stylesheet)
- })
- }
- images = odffragment.getElementsByTagNameNS(drawns, "image");
- for(i = 0;i < images.length;i += 1) {
- node = (images.item(i));
- loadImage("image" + String(i), container, node, stylesheet)
- }
++ if(n === buff_size) {
++ return n
+ }
- function loadVideos(container, odffragment) {
- var i, plugins, node;
- function loadVideo(container, node) {
- loadingQueue.addToQueue(function() {
- setVideo(container, node)
- })
- }
- plugins = odffragment.getElementsByTagNameNS(drawns, "plugin");
- for(i = 0;i < plugins.length;i += 1) {
- node = (plugins.item(i));
- loadVideo(container, node)
++ if(zip_outoff < zip_outcnt) {
++ i = buff_size - n;
++ if(i > zip_outcnt - zip_outoff) {
++ i = zip_outcnt - zip_outoff
+ }
- }
- function addEventListener(eventType, eventHandler) {
- var handlers = eventHandlers[eventType];
- if(handlers === undefined) {
- handlers = eventHandlers[eventType] = []
++ for(j = 0;j < i;j++) {
++ buff[off + n + j] = zip_outbuf[zip_outoff + j]
+ }
- if(eventHandler && handlers.indexOf(eventHandler) === -1) {
- handlers.push(eventHandler)
++ zip_outoff += i;
++ n += i;
++ if(zip_outcnt === zip_outoff) {
++ zip_outcnt = zip_outoff = 0
+ }
+ }
- function fireEvent(eventType, args) {
- if(!eventHandlers.hasOwnProperty(eventType)) {
- return
- }
- var handlers = eventHandlers[eventType], i;
- for(i = 0;i < handlers.length;i += 1) {
- handlers[i].apply(null, args)
++ return n
++ };
++ var zip_deflate_internal = function(buff, off, buff_size) {
++ var n;
++ if(!zip_initflag) {
++ zip_init_deflate();
++ zip_initflag = true;
++ if(zip_lookahead === 0) {
++ zip_complete = true;
++ return 0
+ }
+ }
- function fixContainerSize() {
- var odfdoc = sizer.firstChild;
- if(!odfdoc) {
- return
- }
- if(zoomLevel > 1) {
- sizer.style.MozTransformOrigin = "center top";
- sizer.style.WebkitTransformOrigin = "center top";
- sizer.style.OTransformOrigin = "center top";
- sizer.style.msTransformOrigin = "center top"
- }else {
- sizer.style.MozTransformOrigin = "left top";
- sizer.style.WebkitTransformOrigin = "left top";
- sizer.style.OTransformOrigin = "left top";
- sizer.style.msTransformOrigin = "left top"
- }
- sizer.style.WebkitTransform = "scale(" + zoomLevel + ")";
- sizer.style.MozTransform = "scale(" + zoomLevel + ")";
- sizer.style.OTransform = "scale(" + zoomLevel + ")";
- sizer.style.msTransform = "scale(" + zoomLevel + ")";
- element.style.width = Math.round(zoomLevel * sizer.offsetWidth) + "px";
- element.style.height = Math.round(zoomLevel * sizer.offsetHeight) + "px"
++ n = zip_qcopy(buff, off, buff_size);
++ if(n === buff_size) {
++ return buff_size
+ }
- function handleContent(container, odfnode) {
- var css = positioncss.sheet;
- clear(element);
- sizer = doc.createElementNS(element.namespaceURI, "div");
- sizer.style.display = "inline-block";
- sizer.style.background = "white";
- sizer.appendChild(odfnode);
- element.appendChild(sizer);
- annotationsPane = doc.createElementNS(element.namespaceURI, "div");
- annotationsPane.id = "annotationsPane";
- shadowContent = doc.createElementNS(element.namespaceURI, "div");
- shadowContent.id = "shadowContent";
- shadowContent.style.position = "absolute";
- shadowContent.style.top = 0;
- shadowContent.style.left = 0;
- container.getContentElement().appendChild(shadowContent);
- modifyDrawElements(odfnode.body, css);
- cloneMasterPages(container, shadowContent, odfnode.body, css);
- modifyTables(odfnode.body);
- modifyLinks(odfnode.body);
- modifyLineBreakElements(odfnode.body);
- expandSpaceElements(odfnode.body);
- expandTabElements(odfnode.body);
- loadImages(container, odfnode.body, css);
- loadVideos(container, odfnode.body);
- loadLists(odfnode.body, css);
- sizer.insertBefore(shadowContent, sizer.firstChild);
- fixContainerSize()
++ if(zip_complete) {
++ return n
+ }
- function modifyAnnotations(odffragment) {
- var annotationNodes = domUtils.getElementsByTagNameNS(odffragment, officens, "annotation"), annotationEnds = domUtils.getElementsByTagNameNS(odffragment, officens, "annotation-end"), currentAnnotationName, i;
- function matchAnnotationEnd(element) {
- return currentAnnotationName === element.getAttributeNS(officens, "name")
++ if(zip_compr_level <= 3) {
++ zip_deflate_fast()
++ }else {
++ zip_deflate_better()
++ }
++ if(zip_lookahead === 0) {
++ if(zip_match_available !== 0) {
++ zip_ct_tally(0, zip_window[zip_strstart - 1] & 255)
+ }
- for(i = 0;i < annotationNodes.length;i += 1) {
- currentAnnotationName = annotationNodes[i].getAttributeNS(officens, "name");
- annotationViewManager.addAnnotation({node:annotationNodes[i], end:annotationEnds.filter(matchAnnotationEnd)[0] || null})
++ zip_flush_block(1);
++ zip_complete = true
++ }
++ return n + zip_qcopy(buff, n + off, buff_size - n)
++ };
++ var zip_deflate = function(str, level) {
++ var i, j;
++ zip_deflate_data = str;
++ zip_deflate_pos = 0;
++ if(String(typeof level) === "undefined") {
++ level = zip_DEFAULT_LEVEL
++ }
++ zip_deflate_start(level);
++ var buff = new Array(1024);
++ var aout = [], cbuf = [];
++ i = zip_deflate_internal(buff, 0, buff.length);
++ while(i > 0) {
++ cbuf.length = i;
++ for(j = 0;j < i;j++) {
++ cbuf[j] = String.fromCharCode(buff[j])
+ }
- annotationViewManager.rerenderAnnotations()
++ aout[aout.length] = cbuf.join("");
++ i = zip_deflate_internal(buff, 0, buff.length)
+ }
- function handleAnnotations(odfnode) {
- if(allowAnnotations) {
- if(!annotationsPane.parentNode) {
- sizer.appendChild(annotationsPane);
- fixContainerSize()
- }
- if(annotationViewManager) {
- annotationViewManager.forgetAnnotations()
- }
- annotationViewManager = new gui.AnnotationViewManager(self, odfnode.body, annotationsPane);
- modifyAnnotations(odfnode.body)
- }else {
- if(annotationsPane.parentNode) {
- sizer.removeChild(annotationsPane);
- annotationViewManager.forgetAnnotations();
- fixContainerSize()
- }
++ zip_deflate_data = "";
++ return aout.join("")
++ };
++ this.deflate = zip_deflate
++};
++runtime.loadClass("odf.Namespaces");
++gui.ImageSelector = function ImageSelector(odfCanvas) {
++ var svgns = odf.Namespaces.svgns, imageSelectorId = "imageSelector", selectorBorderWidth = 1, squareClassNames = ["topLeft", "topRight", "bottomRight", "bottomLeft", "topMiddle", "rightMiddle", "bottomMiddle", "leftMiddle"], document = odfCanvas.getElement().ownerDocument, hasSelection = false;
++ function createSelectorElement() {
++ var sizerElement = odfCanvas.getSizer(), selectorElement, squareElement;
++ selectorElement = document.createElement("div");
++ selectorElement.id = "imageSelector";
++ selectorElement.style.borderWidth = selectorBorderWidth + "px";
++ sizerElement.appendChild(selectorElement);
++ squareClassNames.forEach(function(className) {
++ squareElement = document.createElement("div");
++ squareElement.className = className;
++ selectorElement.appendChild(squareElement)
++ });
++ return selectorElement
++ }
++ function getPosition(element, referenceElement) {
++ var rect = element.getBoundingClientRect(), refRect = referenceElement.getBoundingClientRect(), zoomLevel = odfCanvas.getZoomLevel();
++ return{left:(rect.left - refRect.left) / zoomLevel - selectorBorderWidth, top:(rect.top - refRect.top) / zoomLevel - selectorBorderWidth}
++ }
++ this.select = function(frameElement) {
++ var selectorElement = document.getElementById(imageSelectorId), position;
++ if(!selectorElement) {
++ selectorElement = createSelectorElement()
++ }
++ hasSelection = true;
++ position = getPosition(frameElement, (selectorElement.parentNode));
++ selectorElement.style.display = "block";
++ selectorElement.style.left = position.left + "px";
++ selectorElement.style.top = position.top + "px";
++ selectorElement.style.width = frameElement.getAttributeNS(svgns, "width");
++ selectorElement.style.height = frameElement.getAttributeNS(svgns, "height")
++ };
++ this.clearSelection = function() {
++ var selectorElement;
++ if(hasSelection) {
++ selectorElement = document.getElementById(imageSelectorId);
++ if(selectorElement) {
++ selectorElement.style.display = "none"
+ }
+ }
- function refreshOdf(suppressEvent) {
- function callback() {
- clear(element);
- element.style.display = "inline-block";
- var odfnode = odfcontainer.rootElement;
- element.ownerDocument.importNode(odfnode, true);
- formatting.setOdfContainer(odfcontainer);
- handleFonts(odfcontainer, fontcss);
- handleStyles(odfcontainer, formatting, stylesxmlcss);
- handleContent(odfcontainer, odfnode);
- handleAnnotations(odfnode);
- if(!suppressEvent) {
- fireEvent("statereadychange", [odfcontainer])
- }
++ hasSelection = false
++ };
++ this.isSelectorElement = function(node) {
++ var selectorElement = document.getElementById(imageSelectorId);
++ if(!selectorElement) {
++ return false
++ }
++ return node === selectorElement || node.parentNode === selectorElement
++ }
++};
++runtime.loadClass("odf.OdfCanvas");
++odf.CommandLineTools = function CommandLineTools() {
++ this.roundTrip = function(inputfilepath, outputfilepath, callback) {
++ function onready(odfcontainer) {
++ if(odfcontainer.state === odf.OdfContainer.INVALID) {
++ return callback("Document " + inputfilepath + " is invalid.")
+ }
+ if(odfcontainer.state === odf.OdfContainer.DONE) {
- callback()
- }else {
- runtime.log("WARNING: refreshOdf called but ODF was not DONE.");
- runtime.setTimeout(function later_cb() {
- if(odfcontainer.state === odf.OdfContainer.DONE) {
- callback()
- }else {
- runtime.log("will be back later...");
- runtime.setTimeout(later_cb, 500)
- }
- }, 100)
- }
- }
- this.refreshCSS = function() {
- handleStyles(odfcontainer, formatting, stylesxmlcss);
- fixContainerSize()
- };
- this.refreshSize = function() {
- fixContainerSize()
- };
- this.odfContainer = function() {
- return odfcontainer
- };
- this.slidevisibilitycss = function() {
- return pageSwitcher.css
- };
- this.setOdfContainer = function(container, suppressEvent) {
- odfcontainer = container;
- refreshOdf(suppressEvent === true)
- };
- function load(url) {
- loadingQueue.clearQueue();
- element.innerHTML = runtime.tr("Loading") + " " + url + "...";
- element.removeAttribute("style");
- odfcontainer = new odf.OdfContainer(url, function(container) {
- odfcontainer = container;
- refreshOdf(false)
- })
- }
- this["load"] = load;
- this.load = load;
- this.save = function(callback) {
- odfcontainer.save(callback)
- };
- this.addListener = function(eventName, handler) {
- switch(eventName) {
- case "selectionchange":
- selectionWatcher.addListener(eventName, handler);
- break;
- case "click":
- listenEvent(element, eventName, handler);
- break;
- default:
- addEventListener(eventName, handler);
- break
- }
- };
- this.getFormatting = function() {
- return formatting
- };
- this.getAnnotationViewManager = function() {
- return annotationViewManager
- };
- this.refreshAnnotations = function() {
- handleAnnotations(odfcontainer.rootElement)
- };
- this.rerenderAnnotations = function() {
- if(annotationViewManager) {
- annotationViewManager.rerenderAnnotations()
- }
- };
- this.getSizer = function() {
- return sizer
- };
- this.enableAnnotations = function(allow) {
- if(allow !== allowAnnotations) {
- allowAnnotations = allow;
- if(odfcontainer) {
- handleAnnotations(odfcontainer.rootElement)
- }
- }
- };
- this.addAnnotation = function(annotation) {
- if(annotationViewManager) {
- annotationViewManager.addAnnotation(annotation)
- }
- };
- this.forgetAnnotations = function() {
- if(annotationViewManager) {
- annotationViewManager.forgetAnnotations()
- }
- };
- this.setZoomLevel = function(zoom) {
- zoomLevel = zoom;
- fixContainerSize()
- };
- this.getZoomLevel = function() {
- return zoomLevel
- };
- this.fitToContainingElement = function(width, height) {
- var realWidth = element.offsetWidth / zoomLevel, realHeight = element.offsetHeight / zoomLevel;
- zoomLevel = width / realWidth;
- if(height / realHeight < zoomLevel) {
- zoomLevel = height / realHeight
- }
- fixContainerSize()
- };
- this.fitToWidth = function(width) {
- var realWidth = element.offsetWidth / zoomLevel;
- zoomLevel = width / realWidth;
- fixContainerSize()
- };
- this.fitSmart = function(width, height) {
- var realWidth, realHeight, newScale;
- realWidth = element.offsetWidth / zoomLevel;
- realHeight = element.offsetHeight / zoomLevel;
- newScale = width / realWidth;
- if(height !== undefined) {
- if(height / realHeight < newScale) {
- newScale = height / realHeight
- }
- }
- zoomLevel = Math.min(1, newScale);
- fixContainerSize()
- };
- this.fitToHeight = function(height) {
- var realHeight = element.offsetHeight / zoomLevel;
- zoomLevel = height / realHeight;
- fixContainerSize()
- };
- this.showFirstPage = function() {
- pageSwitcher.showFirstPage()
- };
- this.showNextPage = function() {
- pageSwitcher.showNextPage()
- };
- this.showPreviousPage = function() {
- pageSwitcher.showPreviousPage()
- };
- this.showPage = function(n) {
- pageSwitcher.showPage(n);
- fixContainerSize()
- };
- this.getElement = function() {
- return element
- };
- this.addCssForFrameWithImage = function(frame) {
- var frameName = frame.getAttributeNS(drawns, "name");
- setDrawElementPosition(frameName, frame, positioncss.sheet);
- setImage(frameName + "img", odfcontainer, (frame.firstChild), positioncss.sheet)
- };
- this.destroy = function(callback) {
- var head = doc.getElementsByTagName("head")[0];
- if(annotationsPane && annotationsPane.parentNode) {
- annotationsPane.parentNode.removeChild(annotationsPane)
- }
- if(sizer) {
- element.removeChild(sizer)
- }
- head.removeChild(webodfcss);
- head.removeChild(fontcss);
- head.removeChild(stylesxmlcss);
- head.removeChild(positioncss);
- selectionWatcher.destroy(function(err) {
- if(err) {
- callback(err)
- }else {
- pageSwitcher.destroy(callback)
- }
- })
- };
- function init() {
- webodfcss = addWebODFStyleSheet(doc);
- pageSwitcher = new PageSwitcher(addStyleSheet(doc));
- fontcss = addStyleSheet(doc);
- stylesxmlcss = addStyleSheet(doc);
- positioncss = addStyleSheet(doc)
- }
- init()
- };
- return odf.OdfCanvas
- }();
- runtime.loadClass("odf.OdfCanvas");
- odf.CommandLineTools = function CommandLineTools() {
- this.roundTrip = function(inputfilepath, outputfilepath, callback) {
- function onready(odfcontainer) {
- if(odfcontainer.state === odf.OdfContainer.INVALID) {
- return callback("Document " + inputfilepath + " is invalid.")
- }
- if(odfcontainer.state === odf.OdfContainer.DONE) {
- odfcontainer.saveAs(outputfilepath, function(err) {
- callback(err)
- })
++ odfcontainer.saveAs(outputfilepath, function(err) {
++ callback(err)
++ })
+ }else {
+ callback("Document was not completely loaded.")
+ }
+ }
+ var odfcontainer = new odf.OdfContainer(inputfilepath, onready);
+ return odfcontainer
+ };
+ this.render = function(inputfilepath, document, callback) {
+ var body = document.getElementsByTagName("body")[0], odfcanvas;
+ while(body.firstChild) {
+ body.removeChild(body.firstChild)
+ }
+ odfcanvas = new odf.OdfCanvas(body);
+ odfcanvas.addListener("statereadychange", function(err) {
+ callback(err)
+ });
+ odfcanvas.load(inputfilepath)
+ }
+};
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ This file is part of WebODF.
+
+ WebODF is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License (GNU AGPL)
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ WebODF is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ @licend
+
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+ops.Member = function Member(memberId, properties) {
+ var props = {};
+ function getMemberId() {
+ return memberId
+ }
+ function getProperties() {
+ return props
+ }
+ function setProperties(newProperties) {
+ Object.keys(newProperties).forEach(function(key) {
+ props[key] = newProperties[key]
+ })
+ }
+ function removeProperties(removedProperties) {
+ delete removedProperties.fullName;
+ delete removedProperties.color;
+ delete removedProperties.imageUrl;
+ Object.keys(removedProperties).forEach(function(key) {
+ if(props.hasOwnProperty(key)) {
+ delete props[key]
+ }
+ })
+ }
+ this.getMemberId = getMemberId;
+ this.getProperties = getProperties;
+ this.setProperties = setProperties;
+ this.removeProperties = removeProperties;
+ function init() {
+ runtime.assert(Boolean(memberId), "No memberId was supplied!");
+ if(!properties.fullName) {
+ properties.fullName = runtime.tr("Unknown Author")
+ }
+ if(!properties.color) {
+ properties.color = "black"
+ }
+ if(!properties.imageUrl) {
+ properties.imageUrl = "avatar-joe.png"
+ }
+ props = properties
+ }
+ init()
+};
+/*
+
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- ops.Server = function Server() {
- };
- ops.Server.prototype.connect = function(timeout, cb) {
- };
- ops.Server.prototype.networkStatus = function() {
- };
- ops.Server.prototype.login = function(login, password, successCb, failCb) {
- };
- ops.Server.prototype.joinSession = function(userId, sessionId, successCb, failCb) {
- };
- ops.Server.prototype.leaveSession = function(sessionId, memberId, successCb, failCb) {
- };
- ops.Server.prototype.getGenesisUrl = function(sessionId) {
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- ops.Operation = function Operation() {
- };
- ops.Operation.prototype.init = function(data) {
- };
- ops.Operation.prototype.isEdit;
- ops.Operation.prototype.execute = function(odtDocument) {
- };
- ops.Operation.prototype.spec = function() {
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- ops.OpAddCursor = function OpAddCursor() {
- var memberid, timestamp;
- this.init = function(data) {
- memberid = data.memberid;
- timestamp = data.timestamp
- };
- this.isEdit = false;
- this.execute = function(odtDocument) {
- var cursor = odtDocument.getCursor(memberid);
- if(cursor) {
- return false
- }
- cursor = new ops.OdtCursor(memberid, odtDocument);
- odtDocument.addCursor(cursor);
- odtDocument.emit(ops.OdtDocument.signalCursorAdded, cursor);
- return true
- };
- this.spec = function() {
- return{optype:"AddCursor", memberid:memberid, timestamp:timestamp}
- }
- };
- /*
-
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+runtime.loadClass("core.DomUtils");
- runtime.loadClass("odf.Namespaces");
++runtime.loadClass("core.PositionFilter");
+runtime.loadClass("odf.OdfUtils");
- gui.StyleHelper = function StyleHelper(formatting) {
- var domUtils = new core.DomUtils, odfUtils = new odf.OdfUtils, textns = odf.Namespaces.textns;
- function getAppliedStyles(range) {
- var container, nodes;
- if(range.collapsed) {
- container = range.startContainer;
- if(container.hasChildNodes() && range.startOffset < container.childNodes.length) {
- container = container.childNodes[range.startOffset]
++(function() {
++ var nextNodeId = 0, PREVIOUS_STEP = 0, NEXT_STEP = 1;
++ function StepsCache(rootNode, filter, bucketSize) {
++ var coordinatens = "urn:webodf:names:steps", stepToDomPoint = {}, nodeToBookmark = {}, odfUtils = new odf.OdfUtils, domUtils = new core.DomUtils, basePoint, FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT;
++ function ParagraphBookmark(steps, paragraphNode) {
++ this.steps = steps;
++ this.node = paragraphNode;
++ function positionInContainer(node) {
++ var position = 0;
++ while(node && node.previousSibling) {
++ position += 1;
++ node = node.previousSibling
++ }
++ return position
+ }
- nodes = [container]
- }else {
- nodes = odfUtils.getTextNodes(range, true)
- }
- return formatting.getAppliedStyles(nodes)
- }
- this.getAppliedStyles = getAppliedStyles;
- this.applyStyle = function(memberId, range, info) {
- var nextTextNodes = domUtils.splitBoundaries(range), textNodes = odfUtils.getTextNodes(range, false), limits;
- limits = {startContainer:range.startContainer, startOffset:range.startOffset, endContainer:range.endContainer, endOffset:range.endOffset};
- formatting.applyStyle(memberId, textNodes, limits, info);
- nextTextNodes.forEach(domUtils.normalizeTextNodes)
- };
- function hasTextPropertyValue(appliedStyles, propertyName, propertyValue) {
- var hasOtherValue = true, properties, i;
- for(i = 0;i < appliedStyles.length;i += 1) {
- properties = appliedStyles[i]["style:text-properties"];
- hasOtherValue = !properties || properties[propertyName] !== propertyValue;
- if(hasOtherValue) {
- break
++ this.setIteratorPosition = function(iterator) {
++ iterator.setUnfilteredPosition(paragraphNode.parentNode, positionInContainer(paragraphNode));
++ do {
++ if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
++ break
++ }
++ }while(iterator.nextPosition())
+ }
+ }
- return!hasOtherValue
- }
- this.isBold = function(appliedStyles) {
- return hasTextPropertyValue(appliedStyles, "fo:font-weight", "bold")
- };
- this.isItalic = function(appliedStyles) {
- return hasTextPropertyValue(appliedStyles, "fo:font-style", "italic")
- };
- this.hasUnderline = function(appliedStyles) {
- return hasTextPropertyValue(appliedStyles, "style:text-underline-style", "solid")
- };
- this.hasStrikeThrough = function(appliedStyles) {
- return hasTextPropertyValue(appliedStyles, "style:text-line-through-style", "solid")
- };
- function hasParagraphPropertyValue(range, propertyName, propertyValues) {
- var nodes = odfUtils.getParagraphElements(range), isStyleChecked = {}, isDefaultParagraphStyleChecked = false, paragraphStyleName, paragraphStyleElement, paragraphStyleAttributes, properties;
- function pickDefaultParagraphStyleElement() {
- isDefaultParagraphStyleChecked = true;
- paragraphStyleElement = formatting.getDefaultStyleElement("paragraph");
- if(!paragraphStyleElement) {
- paragraphStyleElement = null
++ function RootBookmark(steps, rootNode) {
++ this.steps = steps;
++ this.node = rootNode;
++ this.setIteratorPosition = function(iterator) {
++ iterator.setUnfilteredPosition(rootNode, 0);
++ do {
++ if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
++ break
++ }
++ }while(iterator.nextPosition())
+ }
+ }
- while(nodes.length > 0) {
- paragraphStyleName = nodes[0].getAttributeNS(textns, "style-name");
- if(paragraphStyleName) {
- if(!isStyleChecked[paragraphStyleName]) {
- paragraphStyleElement = formatting.getStyleElement(paragraphStyleName, "paragraph");
- isStyleChecked[paragraphStyleName] = true;
- if(!paragraphStyleElement && !isDefaultParagraphStyleChecked) {
- pickDefaultParagraphStyleElement()
- }
- }
++ function getBucket(steps) {
++ return Math.floor(steps / bucketSize) * bucketSize
++ }
++ function getDestinationBucket(steps) {
++ return Math.ceil(steps / bucketSize) * bucketSize
++ }
++ function clearNodeId(node) {
++ node.removeAttributeNS(coordinatens, "nodeId")
++ }
++ function getNodeId(node) {
++ return node.nodeType === Node.ELEMENT_NODE && node.getAttributeNS(coordinatens, "nodeId")
++ }
++ function setNodeId(node) {
++ var nodeId = nextNodeId;
++ node.setAttributeNS(coordinatens, "nodeId", nodeId.toString());
++ nextNodeId += 1;
++ return nodeId
++ }
++ function isValidBookmarkForNode(node, bookmark) {
++ return bookmark.node === node
++ }
++ function getNodeBookmark(node, steps) {
++ var nodeId = getNodeId(node) || setNodeId(node), existingBookmark;
++ existingBookmark = nodeToBookmark[nodeId];
++ if(!existingBookmark) {
++ existingBookmark = nodeToBookmark[nodeId] = new ParagraphBookmark(steps, node)
+ }else {
- if(!isDefaultParagraphStyleChecked) {
- pickDefaultParagraphStyleElement()
++ if(!isValidBookmarkForNode(node, existingBookmark)) {
++ runtime.log("Cloned node detected. Creating new bookmark");
++ nodeId = setNodeId(node);
++ existingBookmark = nodeToBookmark[nodeId] = new ParagraphBookmark(steps, node)
+ }else {
- paragraphStyleElement = undefined
++ existingBookmark.steps = steps
+ }
+ }
- if(paragraphStyleElement !== undefined) {
- if(paragraphStyleElement === null) {
- paragraphStyleAttributes = formatting.getSystemDefaultStyleAttributes("paragraph")
- }else {
- paragraphStyleAttributes = formatting.getInheritedStyleAttributes((paragraphStyleElement), true)
++ return existingBookmark
++ }
++ function isFirstPositionInParagraph(node, offset) {
++ return offset === 0 && odfUtils.isParagraph(node)
++ }
++ this.updateCache = function(steps, node, offset, isWalkable) {
++ var stablePoint, cacheBucket, existingCachePoint, bookmark;
++ if(isFirstPositionInParagraph(node, offset)) {
++ stablePoint = true;
++ if(!isWalkable) {
++ steps += 1
+ }
- properties = paragraphStyleAttributes["style:paragraph-properties"];
- if(properties && propertyValues.indexOf(properties[propertyName]) === -1) {
- return false
++ }else {
++ if(node.hasChildNodes() && node.childNodes[offset]) {
++ node = node.childNodes[offset];
++ offset = 0;
++ stablePoint = isFirstPositionInParagraph(node, offset);
++ if(stablePoint) {
++ steps += 1
++ }
+ }
+ }
- nodes.pop()
- }
- return true
- }
- this.isAlignedLeft = function(range) {
- return hasParagraphPropertyValue(range, "fo:text-align", ["left", "start"])
- };
- this.isAlignedCenter = function(range) {
- return hasParagraphPropertyValue(range, "fo:text-align", ["center"])
- };
- this.isAlignedRight = function(range) {
- return hasParagraphPropertyValue(range, "fo:text-align", ["right", "end"])
- };
- this.isAlignedJustified = function(range) {
- return hasParagraphPropertyValue(range, "fo:text-align", ["justify"])
- }
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- runtime.loadClass("gui.StyleHelper");
- runtime.loadClass("odf.OdfUtils");
- ops.OpApplyDirectStyling = function OpApplyDirectStyling() {
- var memberid, timestamp, position, length, setProperties, odfUtils = new odf.OdfUtils;
- this.init = function(data) {
- memberid = data.memberid;
- timestamp = data.timestamp;
- position = parseInt(data.position, 10);
- length = parseInt(data.length, 10);
- setProperties = data.setProperties
- };
- this.isEdit = true;
- function getRange(odtDocument) {
- var point1 = length >= 0 ? position : position + length, point2 = length >= 0 ? position + length : position, p1 = odtDocument.getIteratorAtPosition(point1), p2 = length ? odtDocument.getIteratorAtPosition(point2) : p1, range = odtDocument.getDOM().createRange();
- range.setStart(p1.container(), p1.unfilteredDomOffset());
- range.setEnd(p2.container(), p2.unfilteredDomOffset());
- return range
- }
- this.execute = function(odtDocument) {
- var range = getRange(odtDocument), impactedParagraphs = odfUtils.getImpactedParagraphs(range), styleHelper = new gui.StyleHelper(odtDocument.getFormatting());
- styleHelper.applyStyle(memberid, range, setProperties);
- range.detach();
- odtDocument.getOdfCanvas().refreshCSS();
- odtDocument.fixCursorPositions();
- impactedParagraphs.forEach(function(n) {
- odtDocument.emit(ops.OdtDocument.signalParagraphChanged, {paragraphElement:n, memberId:memberid, timeStamp:timestamp})
- });
- odtDocument.getOdfCanvas().rerenderAnnotations();
- return true
- };
- this.spec = function() {
- return{optype:"ApplyDirectStyling", memberid:memberid, timestamp:timestamp, position:position, length:length, setProperties:setProperties}
- }
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- ops.OpRemoveCursor = function OpRemoveCursor() {
- var memberid, timestamp;
- this.init = function(data) {
- memberid = data.memberid;
- timestamp = data.timestamp
- };
- this.isEdit = false;
- this.execute = function(odtDocument) {
- if(!odtDocument.removeCursor(memberid)) {
- return false
- }
- return true
- };
- this.spec = function() {
- return{optype:"RemoveCursor", memberid:memberid, timestamp:timestamp}
- }
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- ops.OpMoveCursor = function OpMoveCursor() {
- var memberid, timestamp, position, length, selectionType;
- this.init = function(data) {
- memberid = data.memberid;
- timestamp = data.timestamp;
- position = data.position;
- length = data.length || 0;
- selectionType = data.selectionType || ops.OdtCursor.RangeSelection
- };
- this.isEdit = false;
- this.execute = function(odtDocument) {
- var cursor = odtDocument.getCursor(memberid), selectedRange;
- if(!cursor) {
- return false
- }
- selectedRange = odtDocument.convertCursorToDomRange(position, length);
- cursor.setSelectedRange(selectedRange, length >= 0);
- cursor.setSelectionType(selectionType);
- odtDocument.emit(ops.OdtDocument.signalCursorMoved, cursor);
- return true
- };
- this.spec = function() {
- return{optype:"MoveCursor", memberid:memberid, timestamp:timestamp, position:position, length:length, selectionType:selectionType}
- }
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- ops.OpSetBlob = function OpSetBlob() {
- var memberid, timestamp, filename, mimetype, content;
- this.init = function(data) {
- memberid = data.memberid;
- timestamp = data.timestamp;
- filename = data.filename;
- mimetype = data.mimetype;
- content = data.content
- };
- this.isEdit = true;
- this.execute = function(odtDocument) {
- odtDocument.getOdfCanvas().odfContainer().setBlob(filename, mimetype, content);
- return true
- };
- this.spec = function() {
- return{optype:"SetBlob", memberid:memberid, timestamp:timestamp, filename:filename, mimetype:mimetype, content:content}
- }
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- ops.OpRemoveBlob = function OpRemoveBlob() {
- var memberid, timestamp, filename;
- this.init = function(data) {
- memberid = data.memberid;
- timestamp = data.timestamp;
- filename = data.filename
- };
- this.isEdit = true;
- this.execute = function(odtDocument) {
- odtDocument.getOdfCanvas().odfContainer().removeBlob(filename);
- return true
- };
- this.spec = function() {
- return{optype:"RemoveBlob", memberid:memberid, timestamp:timestamp, filename:filename}
- }
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- ops.OpInsertImage = function OpInsertImage() {
- var memberid, timestamp, position, filename, frameWidth, frameHeight, frameStyleName, frameName, drawns = odf.Namespaces.drawns, svgns = odf.Namespaces.svgns, textns = odf.Namespaces.textns, xlinkns = odf.Namespaces.xlinkns;
- this.init = function(data) {
- memberid = data.memberid;
- timestamp = data.timestamp;
- position = data.position;
- filename = data.filename;
- frameWidth = data.frameWidth;
- frameHeight = data.frameHeight;
- frameStyleName = data.frameStyleName;
- frameName = data.frameName
- };
- this.isEdit = true;
- function createFrameElement(document) {
- var imageNode = document.createElementNS(drawns, "draw:image"), frameNode = document.createElementNS(drawns, "draw:frame");
- imageNode.setAttributeNS(xlinkns, "xlink:href", filename);
- imageNode.setAttributeNS(xlinkns, "xlink:type", "simple");
- imageNode.setAttributeNS(xlinkns, "xlink:show", "embed");
- imageNode.setAttributeNS(xlinkns, "xlink:actuate", "onLoad");
- frameNode.setAttributeNS(drawns, "draw:style-name", frameStyleName);
- frameNode.setAttributeNS(drawns, "draw:name", frameName);
- frameNode.setAttributeNS(textns, "text:anchor-type", "as-char");
- frameNode.setAttributeNS(svgns, "svg:width", frameWidth);
- frameNode.setAttributeNS(svgns, "svg:height", frameHeight);
- frameNode.appendChild(imageNode);
- return frameNode
- }
- this.execute = function(odtDocument) {
- var odfCanvas = odtDocument.getOdfCanvas(), domPosition = odtDocument.getTextNodeAtStep(position, memberid), textNode, refNode, paragraphElement, frameElement;
- if(!domPosition) {
- return false
- }
- textNode = domPosition.textNode;
- paragraphElement = odtDocument.getParagraphElement(textNode);
- refNode = domPosition.offset !== textNode.length ? textNode.splitText(domPosition.offset) : textNode.nextSibling;
- frameElement = createFrameElement(odtDocument.getDOM());
- textNode.parentNode.insertBefore(frameElement, refNode);
- odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position:position, length:1});
- if(textNode.length === 0) {
- textNode.parentNode.removeChild(textNode)
- }
- odfCanvas.addCssForFrameWithImage(frameElement);
- odfCanvas.refreshCSS();
- odtDocument.emit(ops.OdtDocument.signalParagraphChanged, {paragraphElement:paragraphElement, memberId:memberid, timeStamp:timestamp});
- odfCanvas.rerenderAnnotations();
- return true
- };
- this.spec = function() {
- return{optype:"InsertImage", memberid:memberid, timestamp:timestamp, filename:filename, position:position, frameWidth:frameWidth, frameHeight:frameHeight, frameStyleName:frameStyleName, frameName:frameName}
- }
- };
- /*
-
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- ops.OpInsertTable = function OpInsertTable() {
- var memberid, timestamp, initialRows, initialColumns, position, tableName, tableStyleName, tableColumnStyleName, tableCellStyleMatrix, tablens = "urn:oasis:names:tc:opendocument:xmlns:table:1.0", textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0";
- this.init = function(data) {
- memberid = data.memberid;
- timestamp = data.timestamp;
- position = data.position;
- initialRows = data.initialRows;
- initialColumns = data.initialColumns;
- tableName = data.tableName;
- tableStyleName = data.tableStyleName;
- tableColumnStyleName = data.tableColumnStyleName;
- tableCellStyleMatrix = data.tableCellStyleMatrix
- };
- this.isEdit = true;
- function getCellStyleName(row, column) {
- var rowStyles;
- if(tableCellStyleMatrix.length === 1) {
- rowStyles = tableCellStyleMatrix[0]
- }else {
- if(tableCellStyleMatrix.length === 3) {
- switch(row) {
- case 0:
- rowStyles = tableCellStyleMatrix[0];
- break;
- case initialRows - 1:
- rowStyles = tableCellStyleMatrix[2];
- break;
- default:
- rowStyles = tableCellStyleMatrix[1];
- break
- }
- }else {
- rowStyles = tableCellStyleMatrix[row]
- }
- }
- if(rowStyles.length === 1) {
- return rowStyles[0]
- }
- if(rowStyles.length === 3) {
- switch(column) {
- case 0:
- return rowStyles[0];
- case initialColumns - 1:
- return rowStyles[2];
- default:
- return rowStyles[1]
- }
- }
- return rowStyles[column]
- }
- function createTableNode(document) {
- var tableNode = document.createElementNS(tablens, "table:table"), columns = document.createElementNS(tablens, "table:table-column"), row, cell, paragraph, rowCounter, columnCounter, cellStyleName;
- if(tableStyleName) {
- tableNode.setAttributeNS(tablens, "table:style-name", tableStyleName)
- }
- if(tableName) {
- tableNode.setAttributeNS(tablens, "table:name", tableName)
- }
- columns.setAttributeNS(tablens, "table:number-columns-repeated", initialColumns);
- if(tableColumnStyleName) {
- columns.setAttributeNS(tablens, "table:style-name", tableColumnStyleName)
- }
- tableNode.appendChild(columns);
- for(rowCounter = 0;rowCounter < initialRows;rowCounter += 1) {
- row = document.createElementNS(tablens, "table:table-row");
- for(columnCounter = 0;columnCounter < initialColumns;columnCounter += 1) {
- cell = document.createElementNS(tablens, "table:table-cell");
- cellStyleName = getCellStyleName(rowCounter, columnCounter);
- if(cellStyleName) {
- cell.setAttributeNS(tablens, "table:style-name", cellStyleName)
- }
- paragraph = document.createElementNS(textns, "text:p");
- cell.appendChild(paragraph);
- row.appendChild(cell)
- }
- tableNode.appendChild(row)
- }
- return tableNode
- }
- this.execute = function(odtDocument) {
- var domPosition = odtDocument.getTextNodeAtStep(position), rootNode = odtDocument.getRootNode(), previousSibling, tableNode;
- if(domPosition) {
- tableNode = createTableNode(odtDocument.getDOM());
- previousSibling = odtDocument.getParagraphElement(domPosition.textNode);
- rootNode.insertBefore(tableNode, previousSibling.nextSibling);
- odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position:position, length:initialColumns * initialRows + 1});
- odtDocument.getOdfCanvas().refreshSize();
- odtDocument.emit(ops.OdtDocument.signalTableAdded, {tableElement:tableNode, memberId:memberid, timeStamp:timestamp});
- odtDocument.getOdfCanvas().rerenderAnnotations();
- return true
- }
- return false
- };
- this.spec = function() {
- return{optype:"InsertTable", memberid:memberid, timestamp:timestamp, position:position, initialRows:initialRows, initialColumns:initialColumns, tableName:tableName, tableStyleName:tableStyleName, tableColumnStyleName:tableColumnStyleName, tableCellStyleMatrix:tableCellStyleMatrix}
- }
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- ops.OpInsertText = function OpInsertText() {
- var space = " ", tab = "\t", memberid, timestamp, position, text;
- this.init = function(data) {
- memberid = data.memberid;
- timestamp = data.timestamp;
- position = data.position;
- text = data.text
- };
- this.isEdit = true;
- function triggerLayoutInWebkit(textNode) {
- var parent = textNode.parentNode, next = textNode.nextSibling;
- parent.removeChild(textNode);
- parent.insertBefore(textNode, next)
- }
- function requiresSpaceElement(text, index) {
- return text[index] === space && (index === 0 || (index === text.length - 1 || text[index - 1] === space))
- }
- this.execute = function(odtDocument) {
- var domPosition, previousNode, parentElement, nextNode = null, ownerDocument = odtDocument.getDOM(), paragraphElement, textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0", toInsertIndex = 0, spaceTag, spaceElement, i;
- function insertTextNode(toInsertText) {
- parentElement.insertBefore(ownerDocument.createTextNode(toInsertText), nextNode)
- }
- odtDocument.upgradeWhitespacesAtPosition(position);
- domPosition = odtDocument.getTextNodeAtStep(position, memberid);
- if(domPosition) {
- previousNode = domPosition.textNode;
- nextNode = previousNode.nextSibling;
- parentElement = previousNode.parentNode;
- paragraphElement = odtDocument.getParagraphElement(previousNode);
- for(i = 0;i < text.length;i += 1) {
- if(requiresSpaceElement(text, i) || text[i] === tab) {
- if(toInsertIndex === 0) {
- if(domPosition.offset !== previousNode.length) {
- nextNode = previousNode.splitText(domPosition.offset)
- }
- if(0 < i) {
- previousNode.appendData(text.substring(0, i))
- }
- }else {
- if(toInsertIndex < i) {
- insertTextNode(text.substring(toInsertIndex, i))
- }
- }
- toInsertIndex = i + 1;
- spaceTag = text[i] === space ? "text:s" : "text:tab";
- spaceElement = ownerDocument.createElementNS(textns, spaceTag);
- spaceElement.appendChild(ownerDocument.createTextNode(text[i]));
- parentElement.insertBefore(spaceElement, nextNode)
- }
- }
- if(toInsertIndex === 0) {
- previousNode.insertData(domPosition.offset, text)
- }else {
- if(toInsertIndex < text.length) {
- insertTextNode(text.substring(toInsertIndex))
- }
- }
- triggerLayoutInWebkit(previousNode);
- if(previousNode.length === 0) {
- previousNode.parentNode.removeChild(previousNode)
- }
- odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position:position, length:text.length});
- if(position > 0) {
- if(position > 1) {
- odtDocument.downgradeWhitespacesAtPosition(position - 2)
- }
- odtDocument.downgradeWhitespacesAtPosition(position - 1)
- }
- odtDocument.downgradeWhitespacesAtPosition(position);
- odtDocument.downgradeWhitespacesAtPosition(position + text.length - 1);
- odtDocument.downgradeWhitespacesAtPosition(position + text.length);
- odtDocument.getOdfCanvas().refreshSize();
- odtDocument.emit(ops.OdtDocument.signalParagraphChanged, {paragraphElement:paragraphElement, memberId:memberid, timeStamp:timestamp});
- odtDocument.getOdfCanvas().rerenderAnnotations();
- return true
- }
- return false
- };
- this.spec = function() {
- return{optype:"InsertText", memberid:memberid, timestamp:timestamp, position:position, text:text}
- }
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- runtime.loadClass("odf.Namespaces");
- runtime.loadClass("odf.OdfUtils");
- runtime.loadClass("core.DomUtils");
- ops.OpRemoveText = function OpRemoveText() {
- var memberid, timestamp, position, length, odfUtils, domUtils, editinfons = "urn:webodf:names:editinfo", odfNodeNamespaceMap = {};
- this.init = function(data) {
- runtime.assert(data.length >= 0, "OpRemoveText only supports positive lengths");
- memberid = data.memberid;
- timestamp = data.timestamp;
- position = parseInt(data.position, 10);
- length = parseInt(data.length, 10);
- odfUtils = new odf.OdfUtils;
- domUtils = new core.DomUtils;
- odfNodeNamespaceMap[odf.Namespaces.dbns] = true;
- odfNodeNamespaceMap[odf.Namespaces.dcns] = true;
- odfNodeNamespaceMap[odf.Namespaces.dr3dns] = true;
- odfNodeNamespaceMap[odf.Namespaces.drawns] = true;
- odfNodeNamespaceMap[odf.Namespaces.chartns] = true;
- odfNodeNamespaceMap[odf.Namespaces.formns] = true;
- odfNodeNamespaceMap[odf.Namespaces.numberns] = true;
- odfNodeNamespaceMap[odf.Namespaces.officens] = true;
- odfNodeNamespaceMap[odf.Namespaces.presentationns] = true;
- odfNodeNamespaceMap[odf.Namespaces.stylens] = true;
- odfNodeNamespaceMap[odf.Namespaces.svgns] = true;
- odfNodeNamespaceMap[odf.Namespaces.tablens] = true;
- odfNodeNamespaceMap[odf.Namespaces.textns] = true
- };
- this.isEdit = true;
- function CollapsingRules(rootNode) {
- function isOdfNode(node) {
- return odfNodeNamespaceMap.hasOwnProperty(node.namespaceURI)
- }
- function shouldRemove(node) {
- return isOdfNode(node) || (node.localName === "br" && odfUtils.isLineBreak(node.parentNode) || node.nodeType === Node.TEXT_NODE && isOdfNode((node.parentNode)))
- }
- function isEmpty(node) {
- var childNode;
- if(odfUtils.isCharacterElement(node)) {
- return false
++ if(stablePoint) {
++ bookmark = getNodeBookmark(node, steps);
++ cacheBucket = getDestinationBucket(bookmark.steps);
++ existingCachePoint = stepToDomPoint[cacheBucket];
++ if(!existingCachePoint || bookmark.steps > existingCachePoint.steps) {
++ stepToDomPoint[cacheBucket] = bookmark
++ }
+ }
- if(node.nodeType === Node.TEXT_NODE) {
- return node.textContent.length === 0
++ };
++ this.setToClosestStep = function(steps, iterator) {
++ var cacheBucket = getBucket(steps), cachePoint;
++ while(!cachePoint && cacheBucket !== 0) {
++ cachePoint = stepToDomPoint[cacheBucket];
++ cacheBucket -= bucketSize
+ }
- childNode = node.firstChild;
- while(childNode) {
- if(isOdfNode(childNode) || !isEmpty(childNode)) {
- return false
++ cachePoint = cachePoint || basePoint;
++ cachePoint.setIteratorPosition(iterator);
++ return cachePoint.steps
++ };
++ function findBookmarkedAncestor(node, offset) {
++ var nodeId, bookmark = null;
++ node = node.childNodes[offset] || node;
++ while(!bookmark && (node && node !== rootNode)) {
++ nodeId = getNodeId(node);
++ if(nodeId) {
++ bookmark = nodeToBookmark[nodeId];
++ if(bookmark && !isValidBookmarkForNode(node, bookmark)) {
++ runtime.log("Cloned node detected. Creating new bookmark");
++ bookmark = null;
++ clearNodeId(node)
++ }
+ }
- childNode = childNode.nextSibling
++ node = node.parentNode
+ }
- return true
- }
- this.isEmpty = isEmpty;
- function isCollapsibleContainer(node) {
- return!odfUtils.isParagraph(node) && (node !== rootNode && isEmpty(node))
++ return bookmark
+ }
- function mergeChildrenIntoParent(targetNode) {
- var parent;
- if(targetNode.nodeType === Node.TEXT_NODE) {
- parent = targetNode.parentNode;
- parent.removeChild(targetNode)
++ this.setToClosestDomPoint = function(node, offset, iterator) {
++ var bookmark;
++ if(node === rootNode && offset === 0) {
++ bookmark = basePoint
+ }else {
- parent = domUtils.removeUnwantedNodes(targetNode, shouldRemove)
- }
- if(isCollapsibleContainer(parent)) {
- return mergeChildrenIntoParent(parent)
++ if(node === rootNode && offset === rootNode.childNodes.length) {
++ bookmark = Object.keys(stepToDomPoint).map(function(cacheBucket) {
++ return stepToDomPoint[cacheBucket]
++ }).reduce(function(largestBookmark, bookmark) {
++ return bookmark.steps > largestBookmark.steps ? bookmark : largestBookmark
++ }, basePoint)
++ }else {
++ bookmark = findBookmarkedAncestor(node, offset);
++ if(!bookmark) {
++ iterator.setUnfilteredPosition(node, offset);
++ while(!bookmark && iterator.previousNode()) {
++ bookmark = findBookmarkedAncestor(iterator.container(), iterator.unfilteredDomOffset())
++ }
++ }
++ }
+ }
- return parent
++ bookmark = bookmark || basePoint;
++ bookmark.setIteratorPosition(iterator);
++ return bookmark.steps
++ };
++ this.updateCacheAtPoint = function(inflectionStep, doUpdate) {
++ var affectedBookmarks, updatedBuckets = {};
++ affectedBookmarks = Object.keys(nodeToBookmark).map(function(nodeId) {
++ return nodeToBookmark[nodeId]
++ }).filter(function(bookmark) {
++ return bookmark.steps > inflectionStep
++ });
++ affectedBookmarks.forEach(function(bookmark) {
++ var originalCacheBucket = getDestinationBucket(bookmark.steps), newCacheBucket, existingBookmark;
++ if(domUtils.containsNode(rootNode, bookmark.node)) {
++ doUpdate(bookmark);
++ newCacheBucket = getDestinationBucket(bookmark.steps);
++ existingBookmark = updatedBuckets[newCacheBucket];
++ if(!existingBookmark || bookmark.steps > existingBookmark.steps) {
++ updatedBuckets[newCacheBucket] = bookmark
++ }
++ }else {
++ delete nodeToBookmark[getNodeId(bookmark.node)]
++ }
++ if(stepToDomPoint[originalCacheBucket] === bookmark) {
++ delete stepToDomPoint[originalCacheBucket]
++ }
++ });
++ Object.keys(updatedBuckets).forEach(function(cacheBucket) {
++ stepToDomPoint[cacheBucket] = updatedBuckets[cacheBucket]
++ })
++ };
++ function init() {
++ basePoint = new RootBookmark(0, rootNode)
+ }
- this.mergeChildrenIntoParent = mergeChildrenIntoParent
++ init()
+ }
- function mergeParagraphs(first, second, collapseRules) {
- var child, mergeForward = false, destination = first, source = second, secondParent, insertionPoint = null;
- if(collapseRules.isEmpty(first)) {
- mergeForward = true;
- if(second.parentNode !== first.parentNode) {
- secondParent = second.parentNode;
- first.parentNode.insertBefore(second, first.nextSibling)
++ ops.StepsTranslator = function StepsTranslator(getRootNode, newIterator, filter, bucketSize) {
++ var rootNode = getRootNode(), stepsCache = new StepsCache(rootNode, filter, bucketSize), domUtils = new core.DomUtils, iterator = newIterator(getRootNode()), FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT;
++ function verifyRootNode() {
++ var currentRootNode = getRootNode();
++ if(currentRootNode !== rootNode) {
++ runtime.log("Undo detected. Resetting steps cache");
++ rootNode = currentRootNode;
++ stepsCache = new StepsCache(rootNode, filter, bucketSize);
++ iterator = newIterator(rootNode)
+ }
- source = first;
- destination = second;
- insertionPoint = destination.getElementsByTagNameNS(editinfons, "editinfo")[0] || destination.firstChild
+ }
- while(source.hasChildNodes()) {
- child = mergeForward ? source.lastChild : source.firstChild;
- source.removeChild(child);
- if(child.localName !== "editinfo") {
- destination.insertBefore(child, insertionPoint)
++ this.convertStepsToDomPoint = function(steps) {
++ var stepsFromRoot, isWalkable;
++ if(steps < 0) {
++ runtime.log("warn", "Requested steps were negative (" + steps + ")");
++ steps = 0
+ }
++ verifyRootNode();
++ stepsFromRoot = stepsCache.setToClosestStep(steps, iterator);
++ while(stepsFromRoot < steps && iterator.nextPosition()) {
++ isWalkable = filter.acceptPosition(iterator) === FILTER_ACCEPT;
++ if(isWalkable) {
++ stepsFromRoot += 1
++ }
++ stepsCache.updateCache(stepsFromRoot, iterator.container(), iterator.unfilteredDomOffset(), isWalkable)
++ }
++ if(stepsFromRoot !== steps) {
++ runtime.log("warn", "Requested " + steps + " steps but only " + stepsFromRoot + " are available")
++ }
++ return{node:iterator.container(), offset:iterator.unfilteredDomOffset()}
++ };
++ function roundToPreferredStep(iterator, roundDirection) {
++ if(!roundDirection || filter.acceptPosition(iterator) === FILTER_ACCEPT) {
++ return true
++ }
++ while(iterator.previousPosition()) {
++ if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
++ if(roundDirection(PREVIOUS_STEP, iterator.container(), iterator.unfilteredDomOffset())) {
++ return true
++ }
++ break
++ }
++ }
++ while(iterator.nextPosition()) {
++ if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
++ if(roundDirection(NEXT_STEP, iterator.container(), iterator.unfilteredDomOffset())) {
++ return true
++ }
++ break
++ }
++ }
++ return false
++ }
++ this.convertDomPointToSteps = function(node, offset, roundDirection) {
++ var stepsFromRoot, beforeRoot, destinationNode, destinationOffset, rounding = 0, isWalkable;
++ verifyRootNode();
++ if(!domUtils.containsNode(rootNode, node)) {
++ beforeRoot = domUtils.comparePoints(rootNode, 0, node, offset) < 0;
++ node = rootNode;
++ offset = beforeRoot ? 0 : rootNode.childNodes.length
++ }
++ iterator.setUnfilteredPosition(node, offset);
++ if(!roundToPreferredStep(iterator, roundDirection)) {
++ iterator.setUnfilteredPosition(node, offset)
++ }
++ destinationNode = iterator.container();
++ destinationOffset = iterator.unfilteredDomOffset();
++ stepsFromRoot = stepsCache.setToClosestDomPoint(destinationNode, destinationOffset, iterator);
++ if(domUtils.comparePoints(iterator.container(), iterator.unfilteredDomOffset(), destinationNode, destinationOffset) < 0) {
++ return stepsFromRoot > 0 ? stepsFromRoot - 1 : stepsFromRoot
++ }
++ while(!(iterator.container() === destinationNode && iterator.unfilteredDomOffset() === destinationOffset) && iterator.nextPosition()) {
++ isWalkable = filter.acceptPosition(iterator) === FILTER_ACCEPT;
++ if(isWalkable) {
++ stepsFromRoot += 1
++ }
++ stepsCache.updateCache(stepsFromRoot, iterator.container(), iterator.unfilteredDomOffset(), isWalkable)
++ }
++ return stepsFromRoot + rounding
++ };
++ this.prime = function() {
++ var stepsFromRoot, isWalkable;
++ verifyRootNode();
++ stepsFromRoot = stepsCache.setToClosestStep(0, iterator);
++ while(iterator.nextPosition()) {
++ isWalkable = filter.acceptPosition(iterator) === FILTER_ACCEPT;
++ if(isWalkable) {
++ stepsFromRoot += 1
++ }
++ stepsCache.updateCache(stepsFromRoot, iterator.container(), iterator.unfilteredDomOffset(), isWalkable)
++ }
++ };
++ this.handleStepsInserted = function(eventArgs) {
++ verifyRootNode();
++ stepsCache.updateCacheAtPoint(eventArgs.position, function(bucket) {
++ bucket.steps += eventArgs.length
++ })
++ };
++ this.handleStepsRemoved = function(eventArgs) {
++ verifyRootNode();
++ stepsCache.updateCacheAtPoint(eventArgs.position, function(bucket) {
++ bucket.steps -= eventArgs.length;
++ if(bucket.steps < 0) {
++ bucket.steps = 0
++ }
++ })
+ }
- if(secondParent && collapseRules.isEmpty(secondParent)) {
- collapseRules.mergeChildrenIntoParent(secondParent)
- }
- collapseRules.mergeChildrenIntoParent(source);
- return destination
- }
- this.execute = function(odtDocument) {
- var paragraphElement, destinationParagraph, range, textNodes, paragraphs, cursor = odtDocument.getCursor(memberid), collapseRules = new CollapsingRules(odtDocument.getRootNode());
- odtDocument.upgradeWhitespacesAtPosition(position);
- odtDocument.upgradeWhitespacesAtPosition(position + length);
- range = odtDocument.convertCursorToDomRange(position, length);
- domUtils.splitBoundaries(range);
- paragraphElement = odtDocument.getParagraphElement(range.startContainer);
- textNodes = odfUtils.getTextElements(range, false, true);
- paragraphs = odfUtils.getParagraphElements(range);
- range.detach();
- textNodes.forEach(function(element) {
- collapseRules.mergeChildrenIntoParent(element)
- });
- destinationParagraph = paragraphs.reduce(function(destination, paragraph) {
- return mergeParagraphs(destination, paragraph, collapseRules)
- });
- odtDocument.emit(ops.OdtDocument.signalStepsRemoved, {position:position, length:length});
- odtDocument.downgradeWhitespacesAtPosition(position);
- odtDocument.fixCursorPositions();
- odtDocument.getOdfCanvas().refreshSize();
- odtDocument.emit(ops.OdtDocument.signalParagraphChanged, {paragraphElement:destinationParagraph || paragraphElement, memberId:memberid, timeStamp:timestamp});
- if(cursor) {
- cursor.resetSelectionType();
- odtDocument.emit(ops.OdtDocument.signalCursorMoved, cursor)
- }
- odtDocument.getOdfCanvas().rerenderAnnotations();
- return true
- };
- this.spec = function() {
- return{optype:"RemoveText", memberid:memberid, timestamp:timestamp, position:position, length:length}
- }
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- ops.OpSplitParagraph = function OpSplitParagraph() {
- var memberid, timestamp, position, odfUtils;
- this.init = function(data) {
- memberid = data.memberid;
- timestamp = data.timestamp;
- position = data.position;
- odfUtils = new odf.OdfUtils
+ };
- this.isEdit = true;
- this.execute = function(odtDocument) {
- var domPosition, paragraphNode, targetNode, node, splitNode, splitChildNode, keptChildNode;
- odtDocument.upgradeWhitespacesAtPosition(position);
- domPosition = odtDocument.getTextNodeAtStep(position, memberid);
- if(!domPosition) {
- return false
++ ops.StepsTranslator.PREVIOUS_STEP = PREVIOUS_STEP;
++ ops.StepsTranslator.NEXT_STEP = NEXT_STEP;
++ return ops.StepsTranslator
++})();
++xmldom.RNG = {};
++xmldom.RNG.Name;
++xmldom.RNG.Attr;
++xmldom.RNG.Element;
++xmldom.RelaxNGParser = function RelaxNGParser() {
++ var self = this, rngns = "http://relaxng.org/ns/structure/1.0", xmlnsns = "http://www.w3.org/2000/xmlns/", start, nsmap = {"http://www.w3.org/XML/1998/namespace":"xml"}, parse;
++ function RelaxNGParseError(error, context) {
++ this.message = function() {
++ if(context) {
++ error += context.nodeType === 1 ? " Element " : " Node ";
++ error += context.nodeName;
++ if(context.nodeValue) {
++ error += " with value '" + context.nodeValue + "'"
++ }
++ error += "."
++ }
++ return error
+ }
- paragraphNode = odtDocument.getParagraphElement(domPosition.textNode);
- if(!paragraphNode) {
- return false
++ }
++ function splitToDuos(e) {
++ if(e.e.length <= 2) {
++ return e
+ }
- if(odfUtils.isListItem(paragraphNode.parentNode)) {
- targetNode = paragraphNode.parentNode
++ var o = {name:e.name, e:e.e.slice(0, 2)};
++ return splitToDuos({name:e.name, e:[o].concat(e.e.slice(2))})
++ }
++ function splitQName(name) {
++ var r = name.split(":", 2), prefix = "", i;
++ if(r.length === 1) {
++ r = ["", r[0]]
+ }else {
- targetNode = paragraphNode
++ prefix = r[0]
+ }
- if(domPosition.offset === 0) {
- keptChildNode = domPosition.textNode.previousSibling;
- splitChildNode = null
- }else {
- keptChildNode = domPosition.textNode;
- if(domPosition.offset >= domPosition.textNode.length) {
- splitChildNode = null
- }else {
- splitChildNode = (domPosition.textNode.splitText(domPosition.offset))
++ for(i in nsmap) {
++ if(nsmap[i] === prefix) {
++ r[0] = i
+ }
+ }
- node = domPosition.textNode;
- while(node !== targetNode) {
- node = node.parentNode;
- splitNode = node.cloneNode(false);
- if(splitChildNode) {
- splitNode.appendChild(splitChildNode)
- }
- if(keptChildNode) {
- while(keptChildNode && keptChildNode.nextSibling) {
- splitNode.appendChild(keptChildNode.nextSibling)
++ return r
++ }
++ function splitQNames(def) {
++ var i, l = def.names ? def.names.length : 0, name, localnames = [], namespaces = [];
++ for(i = 0;i < l;i += 1) {
++ name = splitQName(def.names[i]);
++ namespaces[i] = name[0];
++ localnames[i] = name[1]
++ }
++ def.localnames = localnames;
++ def.namespaces = namespaces
++ }
++ function trim(str) {
++ str = str.replace(/^\s\s*/, "");
++ var ws = /\s/, i = str.length - 1;
++ while(ws.test(str.charAt(i))) {
++ i -= 1
++ }
++ return str.slice(0, i + 1)
++ }
++ function copyAttributes(atts, name, names) {
++ var a = {}, i, att;
++ for(i = 0;atts && i < atts.length;i += 1) {
++ att = (atts.item(i));
++ if(!att.namespaceURI) {
++ if(att.localName === "name" && (name === "element" || name === "attribute")) {
++ names.push(att.value)
++ }
++ if(att.localName === "name" || (att.localName === "combine" || att.localName === "type")) {
++ att.value = trim(att.value)
+ }
++ a[att.localName] = att.value
+ }else {
- while(node.firstChild) {
- splitNode.appendChild(node.firstChild)
++ if(att.namespaceURI === xmlnsns) {
++ nsmap[att.value] = att.localName
+ }
+ }
- node.parentNode.insertBefore(splitNode, node.nextSibling);
- keptChildNode = node;
- splitChildNode = splitNode
+ }
- if(odfUtils.isListItem(splitChildNode)) {
- splitChildNode = splitChildNode.childNodes[0]
++ return a
++ }
++ function parseChildren(c, e, elements, names) {
++ var text = "", ce;
++ while(c) {
++ if(c.nodeType === Node.ELEMENT_NODE && c.namespaceURI === rngns) {
++ ce = parse((c), elements, e);
++ if(ce) {
++ if(ce.name === "name") {
++ names.push(nsmap[ce.a.ns] + ":" + ce.text);
++ e.push(ce)
++ }else {
++ if(ce.name === "choice" && (ce.names && ce.names.length)) {
++ names = names.concat(ce.names);
++ delete ce.names;
++ e.push(ce)
++ }else {
++ e.push(ce)
++ }
++ }
++ }
++ }else {
++ if(c.nodeType === Node.TEXT_NODE) {
++ text += c.nodeValue
++ }
++ }
++ c = c.nextSibling
+ }
- if(domPosition.textNode.length === 0) {
- domPosition.textNode.parentNode.removeChild(domPosition.textNode)
++ return text
++ }
++ function combineDefines(combine, name, e, siblings) {
++ var i, ce;
++ for(i = 0;siblings && i < siblings.length;i += 1) {
++ ce = siblings[i];
++ if(ce.name === "define" && (ce.a && ce.a.name === name)) {
++ ce.e = [{name:combine, e:ce.e.concat(e)}];
++ return ce
++ }
+ }
- odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position:position, length:1});
- odtDocument.fixCursorPositions();
- odtDocument.getOdfCanvas().refreshSize();
- odtDocument.emit(ops.OdtDocument.signalParagraphChanged, {paragraphElement:paragraphNode, memberId:memberid, timeStamp:timestamp});
- odtDocument.emit(ops.OdtDocument.signalParagraphChanged, {paragraphElement:splitChildNode, memberId:memberid, timeStamp:timestamp});
- odtDocument.getOdfCanvas().rerenderAnnotations();
- return true
- };
- this.spec = function() {
- return{optype:"SplitParagraph", memberid:memberid, timestamp:timestamp, position:position}
++ return null
+ }
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- ops.OpSetParagraphStyle = function OpSetParagraphStyle() {
- var memberid, timestamp, position, styleName, textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0";
- this.init = function(data) {
- memberid = data.memberid;
- timestamp = data.timestamp;
- position = data.position;
- styleName = data.styleName
- };
- this.isEdit = true;
- this.execute = function(odtDocument) {
- var iterator, paragraphNode;
- iterator = odtDocument.getIteratorAtPosition(position);
- paragraphNode = odtDocument.getParagraphElement(iterator.container());
- if(paragraphNode) {
- if(styleName !== "") {
- paragraphNode.setAttributeNS(textns, "text:style-name", styleName)
- }else {
- paragraphNode.removeAttributeNS(textns, "style-name")
++ parse = function parse(element, elements, siblings) {
++ var e = [], a, ce, i, text, name = element.localName, names = [];
++ a = copyAttributes(element.attributes, name, names);
++ a.combine = a.combine || undefined;
++ text = parseChildren(element.firstChild, e, elements, names);
++ if(name !== "value" && name !== "param") {
++ text = /^\s*([\s\S]*\S)?\s*$/.exec(text)[1]
++ }
++ if(name === "value" && a.type === undefined) {
++ a.type = "token";
++ a.datatypeLibrary = ""
++ }
++ if((name === "attribute" || name === "element") && a.name !== undefined) {
++ i = splitQName(a.name);
++ e = [{name:"name", text:i[1], a:{ns:i[0]}}].concat(e);
++ delete a.name
++ }
++ if(name === "name" || (name === "nsName" || name === "value")) {
++ if(a.ns === undefined) {
++ a.ns = ""
+ }
- odtDocument.getOdfCanvas().refreshSize();
- odtDocument.emit(ops.OdtDocument.signalParagraphChanged, {paragraphElement:paragraphNode, timeStamp:timestamp, memberId:memberid});
- odtDocument.getOdfCanvas().rerenderAnnotations();
- return true
++ }else {
++ delete a.ns
+ }
- return false
- };
- this.spec = function() {
- return{optype:"SetParagraphStyle", memberid:memberid, timestamp:timestamp, position:position, styleName:styleName}
- }
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- runtime.loadClass("odf.Namespaces");
- ops.OpUpdateParagraphStyle = function OpUpdateParagraphStyle() {
- var memberid, timestamp, styleName, setProperties, removedProperties, paragraphPropertiesName = "style:paragraph-properties", textPropertiesName = "style:text-properties", stylens = odf.Namespaces.stylens;
- function removedAttributesFromStyleNode(node, removedAttributeNames) {
- var i, attributeNameParts, attributeNameList = removedAttributeNames ? removedAttributeNames.split(",") : [];
- for(i = 0;i < attributeNameList.length;i += 1) {
- attributeNameParts = attributeNameList[i].split(":");
- node.removeAttributeNS(odf.Namespaces.resolvePrefix(attributeNameParts[0]), attributeNameParts[1])
++ if(name === "name") {
++ i = splitQName(text);
++ a.ns = i[0];
++ text = i[1]
+ }
- }
- this.init = function(data) {
- memberid = data.memberid;
- timestamp = data.timestamp;
- styleName = data.styleName;
- setProperties = data.setProperties;
- removedProperties = data.removedProperties
- };
- this.isEdit = true;
- this.execute = function(odtDocument) {
- var formatting = odtDocument.getFormatting(), styleNode, paragraphPropertiesNode, textPropertiesNode;
- if(styleName !== "") {
- styleNode = odtDocument.getParagraphStyleElement(styleName)
++ if(e.length > 1 && (name === "define" || (name === "oneOrMore" || (name === "zeroOrMore" || (name === "optional" || (name === "list" || name === "mixed")))))) {
++ e = [{name:"group", e:splitToDuos({name:"group", e:e}).e}]
++ }
++ if(e.length > 2 && name === "element") {
++ e = [e[0]].concat({name:"group", e:splitToDuos({name:"group", e:e.slice(1)}).e})
++ }
++ if(e.length === 1 && name === "attribute") {
++ e.push({name:"text", text:text})
++ }
++ if(e.length === 1 && (name === "choice" || (name === "group" || name === "interleave"))) {
++ name = e[0].name;
++ names = e[0].names;
++ a = e[0].a;
++ text = e[0].text;
++ e = e[0].e
+ }else {
- styleNode = formatting.getDefaultStyleElement("paragraph")
++ if(e.length > 2 && (name === "choice" || (name === "group" || name === "interleave"))) {
++ e = splitToDuos({name:name, e:e}).e
++ }
+ }
- if(styleNode) {
- paragraphPropertiesNode = styleNode.getElementsByTagNameNS(stylens, "paragraph-properties")[0];
- textPropertiesNode = styleNode.getElementsByTagNameNS(stylens, "text-properties")[0];
- if(setProperties) {
- formatting.updateStyle(styleNode, setProperties)
++ if(name === "mixed") {
++ name = "interleave";
++ e = [e[0], {name:"text"}]
++ }
++ if(name === "optional") {
++ name = "choice";
++ e = [e[0], {name:"empty"}]
++ }
++ if(name === "zeroOrMore") {
++ name = "choice";
++ e = [{name:"oneOrMore", e:[e[0]]}, {name:"empty"}]
++ }
++ if(name === "define" && a.combine) {
++ ce = combineDefines(a.combine, a.name, e, siblings);
++ if(ce) {
++ return null
+ }
- if(removedProperties) {
- if(removedProperties[paragraphPropertiesName]) {
- removedAttributesFromStyleNode(paragraphPropertiesNode, removedProperties[paragraphPropertiesName].attributes);
- if(paragraphPropertiesNode.attributes.length === 0) {
- styleNode.removeChild(paragraphPropertiesNode)
- }
++ }
++ ce = {name:name};
++ if(e && e.length > 0) {
++ ce.e = e
++ }
++ for(i in a) {
++ if(a.hasOwnProperty(i)) {
++ ce.a = a;
++ break
++ }
++ }
++ if(text !== undefined) {
++ ce.text = text
++ }
++ if(names && names.length > 0) {
++ ce.names = names
++ }
++ if(name === "element") {
++ ce.id = elements.length;
++ elements.push(ce);
++ ce = {name:"elementref", id:ce.id}
++ }
++ return ce
++ };
++ function resolveDefines(def, defines) {
++ var i = 0, e, defs, end, name = def.name;
++ while(def.e && i < def.e.length) {
++ e = def.e[i];
++ if(e.name === "ref") {
++ defs = defines[e.a.name];
++ if(!defs) {
++ throw e.a.name + " was not defined.";
+ }
- if(removedProperties[textPropertiesName]) {
- removedAttributesFromStyleNode(textPropertiesNode, removedProperties[textPropertiesName].attributes);
- if(textPropertiesNode.attributes.length === 0) {
- styleNode.removeChild(textPropertiesNode)
- }
++ end = def.e.slice(i + 1);
++ def.e = def.e.slice(0, i);
++ def.e = def.e.concat(defs.e);
++ def.e = def.e.concat(end)
++ }else {
++ i += 1;
++ resolveDefines(e, defines)
++ }
++ }
++ e = def.e;
++ if(name === "choice") {
++ if(!e || (!e[1] || e[1].name === "empty")) {
++ if(!e || (!e[0] || e[0].name === "empty")) {
++ delete def.e;
++ def.name = "empty"
++ }else {
++ e[1] = e[0];
++ e[0] = {name:"empty"}
+ }
- removedAttributesFromStyleNode(styleNode, removedProperties.attributes)
+ }
- odtDocument.getOdfCanvas().refreshCSS();
- odtDocument.emit(ops.OdtDocument.signalParagraphStyleModified, styleName);
- odtDocument.getOdfCanvas().rerenderAnnotations();
- return true
+ }
- return false
- };
- this.spec = function() {
- return{optype:"UpdateParagraphStyle", memberid:memberid, timestamp:timestamp, styleName:styleName, setProperties:setProperties, removedProperties:removedProperties}
- }
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- runtime.loadClass("odf.Namespaces");
- ops.OpAddStyle = function OpAddStyle() {
- var memberid, timestamp, styleName, styleFamily, isAutomaticStyle, setProperties, stylens = odf.Namespaces.stylens;
- this.init = function(data) {
- memberid = data.memberid;
- timestamp = data.timestamp;
- styleName = data.styleName;
- styleFamily = data.styleFamily;
- isAutomaticStyle = data.isAutomaticStyle === "true" || data.isAutomaticStyle === true;
- setProperties = data.setProperties
- };
- this.isEdit = true;
- this.execute = function(odtDocument) {
- var odfContainer = odtDocument.getOdfCanvas().odfContainer(), formatting = odtDocument.getFormatting(), dom = odtDocument.getDOM(), styleNode = dom.createElementNS(stylens, "style:style");
- if(!styleNode) {
- return false
++ if(name === "group" || name === "interleave") {
++ if(e[0].name === "empty") {
++ if(e[1].name === "empty") {
++ delete def.e;
++ def.name = "empty"
++ }else {
++ name = def.name = e[1].name;
++ def.names = e[1].names;
++ e = def.e = e[1].e
++ }
++ }else {
++ if(e[1].name === "empty") {
++ name = def.name = e[0].name;
++ def.names = e[0].names;
++ e = def.e = e[0].e
++ }
++ }
+ }
- if(setProperties) {
- formatting.updateStyle(styleNode, setProperties)
++ if(name === "oneOrMore" && e[0].name === "empty") {
++ delete def.e;
++ def.name = "empty"
+ }
- styleNode.setAttributeNS(stylens, "style:family", styleFamily);
- styleNode.setAttributeNS(stylens, "style:name", styleName);
- if(isAutomaticStyle) {
- odfContainer.rootElement.automaticStyles.appendChild(styleNode)
- }else {
- odfContainer.rootElement.styles.appendChild(styleNode)
++ if(name === "attribute") {
++ splitQNames(def)
+ }
- odtDocument.getOdfCanvas().refreshCSS();
- if(!isAutomaticStyle) {
- odtDocument.emit(ops.OdtDocument.signalCommonStyleCreated, {name:styleName, family:styleFamily})
++ if(name === "interleave") {
++ if(e[0].name === "interleave") {
++ if(e[1].name === "interleave") {
++ e = def.e = e[0].e.concat(e[1].e)
++ }else {
++ e = def.e = [e[1]].concat(e[0].e)
++ }
++ }else {
++ if(e[1].name === "interleave") {
++ e = def.e = [e[0]].concat(e[1].e)
++ }
++ }
+ }
- return true
- };
- this.spec = function() {
- return{optype:"AddStyle", memberid:memberid, timestamp:timestamp, styleName:styleName, styleFamily:styleFamily, isAutomaticStyle:isAutomaticStyle, setProperties:setProperties}
+ }
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- ops.OpRemoveStyle = function OpRemoveStyle() {
- var memberid, timestamp, styleName, styleFamily;
- this.init = function(data) {
- memberid = data.memberid;
- timestamp = data.timestamp;
- styleName = data.styleName;
- styleFamily = data.styleFamily
- };
- this.isEdit = true;
- this.execute = function(odtDocument) {
- var styleNode = odtDocument.getStyleElement(styleName, styleFamily);
- if(!styleNode) {
- return false
++ function resolveElements(def, elements) {
++ var i = 0, e;
++ while(def.e && i < def.e.length) {
++ e = def.e[i];
++ if(e.name === "elementref") {
++ e.id = e.id || 0;
++ def.e[i] = elements[e.id]
++ }else {
++ if(e.name !== "element") {
++ resolveElements(e, elements)
++ }
++ }
++ i += 1
+ }
- styleNode.parentNode.removeChild(styleNode);
- odtDocument.getOdfCanvas().refreshCSS();
- odtDocument.emit(ops.OdtDocument.signalCommonStyleDeleted, {name:styleName, family:styleFamily});
- return true
- };
- this.spec = function() {
- return{optype:"RemoveStyle", memberid:memberid, timestamp:timestamp, styleName:styleName, styleFamily:styleFamily}
- }
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- ops.OpAddAnnotation = function OpAddAnnotation() {
- var memberid, timestamp, position, length, name;
- this.init = function(data) {
- memberid = data.memberid;
- timestamp = parseInt(data.timestamp, 10);
- position = parseInt(data.position, 10);
- length = parseInt(data.length, 10) || 0;
- name = data.name
- };
- this.isEdit = true;
- function createAnnotationNode(odtDocument, date) {
- var annotationNode, creatorNode, dateNode, listNode, listItemNode, paragraphNode, doc = odtDocument.getDOM();
- annotationNode = doc.createElementNS(odf.Namespaces.officens, "office:annotation");
- annotationNode.setAttributeNS(odf.Namespaces.officens, "office:name", name);
- creatorNode = doc.createElementNS(odf.Namespaces.dcns, "dc:creator");
- creatorNode.setAttributeNS("urn:webodf:names:editinfo", "editinfo:memberid", memberid);
- creatorNode.textContent = odtDocument.getMember(memberid).getProperties().fullName;
- dateNode = doc.createElementNS(odf.Namespaces.dcns, "dc:date");
- dateNode.appendChild(doc.createTextNode(date.toISOString()));
- listNode = doc.createElementNS(odf.Namespaces.textns, "text:list");
- listItemNode = doc.createElementNS(odf.Namespaces.textns, "text:list-item");
- paragraphNode = doc.createElementNS(odf.Namespaces.textns, "text:p");
- listItemNode.appendChild(paragraphNode);
- listNode.appendChild(listItemNode);
- annotationNode.appendChild(creatorNode);
- annotationNode.appendChild(dateNode);
- annotationNode.appendChild(listNode);
- return annotationNode
- }
- function createAnnotationEnd(odtDocument) {
- var annotationEnd, doc = odtDocument.getDOM();
- annotationEnd = doc.createElementNS(odf.Namespaces.officens, "office:annotation-end");
- annotationEnd.setAttributeNS(odf.Namespaces.officens, "office:name", name);
- return annotationEnd
+ }
- function insertNodeAtPosition(odtDocument, node, insertPosition) {
- var previousNode, parentNode, domPosition = odtDocument.getTextNodeAtStep(insertPosition, memberid);
- if(domPosition) {
- previousNode = domPosition.textNode;
- parentNode = previousNode.parentNode;
- if(domPosition.offset !== previousNode.length) {
- previousNode.splitText(domPosition.offset)
++ function main(dom, callback) {
++ var elements = [], grammar = parse(dom && dom.documentElement, elements, undefined), i, e, defines = {};
++ for(i = 0;i < grammar.e.length;i += 1) {
++ e = grammar.e[i];
++ if(e.name === "define") {
++ defines[e.a.name] = e
++ }else {
++ if(e.name === "start") {
++ start = e
++ }
+ }
- parentNode.insertBefore(node, previousNode.nextSibling);
- if(previousNode.length === 0) {
- parentNode.removeChild(previousNode)
++ }
++ if(!start) {
++ return[new RelaxNGParseError("No Relax NG start element was found.")]
++ }
++ resolveDefines(start, defines);
++ for(i in defines) {
++ if(defines.hasOwnProperty(i)) {
++ resolveDefines(defines[i], defines)
+ }
+ }
- }
- this.execute = function(odtDocument) {
- var annotation = {}, positionFilter = odtDocument.getPositionFilter(), cursor = odtDocument.getCursor(memberid), oldCursorPosition = odtDocument.getCursorPosition(memberid), lengthToMove = position - oldCursorPosition - 1, stepsToParagraph;
- annotation.node = createAnnotationNode(odtDocument, new Date(timestamp));
- if(!annotation.node) {
- return false
++ for(i = 0;i < elements.length;i += 1) {
++ resolveDefines(elements[i], defines)
+ }
- if(length) {
- annotation.end = createAnnotationEnd(odtDocument);
- if(!annotation.end) {
- return false
++ if(callback) {
++ self.rootPattern = callback(start.e[0], elements)
++ }
++ resolveElements(start, elements);
++ for(i = 0;i < elements.length;i += 1) {
++ resolveElements(elements[i], elements)
++ }
++ self.start = start;
++ self.elements = elements;
++ self.nsmap = nsmap;
++ return null
++ }
++ this.parseRelaxNGDOM = main
++};
++runtime.loadClass("core.Cursor");
++runtime.loadClass("gui.SelectionMover");
++ops.OdtCursor = function OdtCursor(memberId, odtDocument) {
++ var self = this, validSelectionTypes = {}, selectionType, selectionMover, cursor;
++ this.removeFromOdtDocument = function() {
++ cursor.remove()
++ };
++ this.move = function(number, extend) {
++ var moved = 0;
++ if(number > 0) {
++ moved = selectionMover.movePointForward(number, extend)
++ }else {
++ if(number <= 0) {
++ moved = -selectionMover.movePointBackward(-number, extend)
+ }
- insertNodeAtPosition(odtDocument, annotation.end, position + length)
+ }
- insertNodeAtPosition(odtDocument, annotation.node, position);
- odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position:position, length:length});
- if(cursor) {
- stepsToParagraph = cursor.getStepCounter().countSteps(lengthToMove, positionFilter);
- cursor.move(stepsToParagraph);
- cursor.resetSelectionType();
- odtDocument.emit(ops.OdtDocument.signalCursorMoved, cursor)
++ self.handleUpdate();
++ return moved
++ };
++ this.handleUpdate = function() {
++ };
++ this.getStepCounter = function() {
++ return selectionMover.getStepCounter()
++ };
++ this.getMemberId = function() {
++ return memberId
++ };
++ this.getNode = function() {
++ return cursor.getNode()
++ };
++ this.getAnchorNode = function() {
++ return cursor.getAnchorNode()
++ };
++ this.getSelectedRange = function() {
++ return cursor.getSelectedRange()
++ };
++ this.setSelectedRange = function(range, isForwardSelection) {
++ cursor.setSelectedRange(range, isForwardSelection);
++ self.handleUpdate()
++ };
++ this.hasForwardSelection = function() {
++ return cursor.hasForwardSelection()
++ };
++ this.getOdtDocument = function() {
++ return odtDocument
++ };
++ this.getSelectionType = function() {
++ return selectionType
++ };
++ this.setSelectionType = function(value) {
++ if(validSelectionTypes.hasOwnProperty(value)) {
++ selectionType = value
++ }else {
++ runtime.log("Invalid selection type: " + value)
+ }
- odtDocument.getOdfCanvas().addAnnotation(annotation);
- odtDocument.fixCursorPositions();
- return true
+ };
- this.spec = function() {
- return{optype:"AddAnnotation", memberid:memberid, timestamp:timestamp, position:position, length:length, name:name}
++ this.resetSelectionType = function() {
++ self.setSelectionType(ops.OdtCursor.RangeSelection)
++ };
++ function init() {
++ cursor = new core.Cursor(odtDocument.getDOM(), memberId);
++ selectionMover = new gui.SelectionMover(cursor, odtDocument.getRootNode());
++ validSelectionTypes[ops.OdtCursor.RangeSelection] = true;
++ validSelectionTypes[ops.OdtCursor.RegionSelection] = true;
++ self.resetSelectionType()
+ }
++ init()
+};
++ops.OdtCursor.RangeSelection = "Range";
++ops.OdtCursor.RegionSelection = "Region";
++(function() {
++ return ops.OdtCursor
++})();
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("odf.Namespaces");
++runtime.loadClass("core.EventNotifier");
+runtime.loadClass("core.DomUtils");
- ops.OpRemoveAnnotation = function OpRemoveAnnotation() {
- var memberid, timestamp, position, length, domUtils;
- this.init = function(data) {
- memberid = data.memberid;
- timestamp = data.timestamp;
- position = parseInt(data.position, 10);
- length = parseInt(data.length, 10);
- domUtils = new core.DomUtils
- };
- this.isEdit = true;
- this.execute = function(odtDocument) {
- var iterator = odtDocument.getIteratorAtPosition(position), container = iterator.container(), annotationName, annotationNode, annotationEnd, cursors;
- while(!(container.namespaceURI === odf.Namespaces.officens && container.localName === "annotation")) {
- container = container.parentNode
++runtime.loadClass("odf.OdfUtils");
++runtime.loadClass("odf.Namespaces");
++runtime.loadClass("gui.SelectionMover");
++runtime.loadClass("core.PositionFilterChain");
++runtime.loadClass("ops.StepsTranslator");
++runtime.loadClass("ops.TextPositionFilter");
++runtime.loadClass("ops.Member");
++ops.OdtDocument = function OdtDocument(odfCanvas) {
++ var self = this, odfUtils, domUtils, cursors = {}, members = {}, eventNotifier = new core.EventNotifier([ops.OdtDocument.signalMemberAdded, ops.OdtDocument.signalMemberUpdated, ops.OdtDocument.signalMemberRemoved, ops.OdtDocument.signalCursorAdded, ops.OdtDocument.signalCursorRemoved, ops.OdtDocument.signalCursorMoved, ops.OdtDocument.signalParagraphChanged, ops.OdtDocument.signalParagraphStyleModified, ops.OdtDocument.signalCommonStyleCreated, ops.OdtDocument.signalCommonStyleDeleted [...]
++ ops.OdtDocument.signalOperationExecuted, ops.OdtDocument.signalUndoStackChanged, ops.OdtDocument.signalStepsInserted, ops.OdtDocument.signalStepsRemoved]), FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT, FILTER_REJECT = core.PositionFilter.FilterResult.FILTER_REJECT, filter, stepsTranslator, lastEditingOp, unsupportedMetadataRemoved = false;
++ function getRootNode() {
++ var element = odfCanvas.odfContainer().getContentElement(), localName = element && element.localName;
++ runtime.assert(localName === "text", "Unsupported content element type '" + localName + "' for OdtDocument");
++ return element
++ }
++ function getDOM() {
++ return(getRootNode().ownerDocument)
++ }
++ this.getDOM = getDOM;
++ function isRoot(node) {
++ if(node.namespaceURI === odf.Namespaces.officens && node.localName === "text" || node.namespaceURI === odf.Namespaces.officens && node.localName === "annotation") {
++ return true
+ }
- if(container === null) {
- return false
++ return false
++ }
++ function getRoot(node) {
++ while(node && !isRoot(node)) {
++ node = (node.parentNode)
+ }
- annotationNode = container;
- annotationName = annotationNode.getAttributeNS(odf.Namespaces.officens, "name");
- if(annotationName) {
- annotationEnd = domUtils.getElementsByTagNameNS(odtDocument.getRootNode(), odf.Namespaces.officens, "annotation-end").filter(function(element) {
- return annotationName === element.getAttributeNS(odf.Namespaces.officens, "name")
- })[0] || null
++ return node
++ }
++ this.getRootElement = getRoot;
++ function RootFilter(anchor) {
++ this.acceptPosition = function(iterator) {
++ var node = iterator.container(), anchorNode;
++ if(typeof anchor === "string") {
++ anchorNode = cursors[anchor].getNode()
++ }else {
++ anchorNode = anchor
++ }
++ if(getRoot(node) === getRoot(anchorNode)) {
++ return FILTER_ACCEPT
++ }
++ return FILTER_REJECT
+ }
- odtDocument.getOdfCanvas().forgetAnnotations();
- cursors = domUtils.getElementsByTagNameNS(annotationNode, "urn:webodf:names:cursor", "cursor");
- while(cursors.length) {
- annotationNode.parentNode.insertBefore(cursors.pop(), annotationNode)
++ }
++ function getIteratorAtPosition(position) {
++ var iterator = gui.SelectionMover.createPositionIterator(getRootNode()), point = stepsTranslator.convertStepsToDomPoint(position);
++ iterator.setUnfilteredPosition(point.node, point.offset);
++ return iterator
++ }
++ this.getIteratorAtPosition = getIteratorAtPosition;
++ this.convertDomPointToCursorStep = function(node, offset, roundDirection) {
++ return stepsTranslator.convertDomPointToSteps(node, offset, roundDirection)
++ };
++ this.convertDomToCursorRange = function(selection, constraint) {
++ var point1, point2, anchorConstraint = constraint(selection.anchorNode, selection.anchorOffset), focusConstraint;
++ point1 = stepsTranslator.convertDomPointToSteps(selection.anchorNode, selection.anchorOffset, anchorConstraint);
++ if(!constraint && (selection.anchorNode === selection.focusNode && selection.anchorOffset === selection.focusOffset)) {
++ point2 = point1
++ }else {
++ focusConstraint = constraint(selection.focusNode, selection.focusOffset);
++ point2 = stepsTranslator.convertDomPointToSteps(selection.focusNode, selection.focusOffset, focusConstraint)
+ }
- annotationNode.parentNode.removeChild(annotationNode);
- if(annotationEnd) {
- annotationEnd.parentNode.removeChild(annotationEnd)
++ return{position:point1, length:point2 - point1}
++ };
++ this.convertCursorToDomRange = function(position, length) {
++ var range = getDOM().createRange(), point1, point2;
++ point1 = stepsTranslator.convertStepsToDomPoint(position);
++ if(length) {
++ point2 = stepsTranslator.convertStepsToDomPoint(position + length);
++ if(length > 0) {
++ range.setStart(point1.node, point1.offset);
++ range.setEnd(point2.node, point2.offset)
++ }else {
++ range.setStart(point2.node, point2.offset);
++ range.setEnd(point1.node, point1.offset)
++ }
++ }else {
++ range.setStart(point1.node, point1.offset)
+ }
- odtDocument.emit(ops.OdtDocument.signalStepsRemoved, {position:position > 0 ? position - 1 : position, length:length});
- odtDocument.fixCursorPositions();
- odtDocument.getOdfCanvas().refreshAnnotations();
- return true
++ return range
+ };
- this.spec = function() {
- return{optype:"RemoveAnnotation", memberid:memberid, timestamp:timestamp, position:position, length:length}
++ function getTextNodeAtStep(steps, memberid) {
++ var iterator = getIteratorAtPosition(steps), node = iterator.container(), lastTextNode, nodeOffset = 0, cursorNode = null;
++ if(node.nodeType === Node.TEXT_NODE) {
++ lastTextNode = (node);
++ nodeOffset = iterator.unfilteredDomOffset()
++ }else {
++ lastTextNode = getDOM().createTextNode("");
++ nodeOffset = 0;
++ node.insertBefore(lastTextNode, iterator.rightNode())
++ }
++ if(memberid && (cursors[memberid] && self.getCursorPosition(memberid) === steps)) {
++ cursorNode = cursors[memberid].getNode();
++ while(cursorNode.nextSibling && cursorNode.nextSibling.localName === "cursor") {
++ cursorNode.parentNode.insertBefore(cursorNode.nextSibling, cursorNode)
++ }
++ if(lastTextNode.length > 0 && lastTextNode.nextSibling !== cursorNode) {
++ lastTextNode = getDOM().createTextNode("");
++ nodeOffset = 0
++ }
++ cursorNode.parentNode.insertBefore(lastTextNode, cursorNode)
++ }
++ while(lastTextNode.previousSibling && lastTextNode.previousSibling.nodeType === Node.TEXT_NODE) {
++ lastTextNode.previousSibling.appendData(lastTextNode.data);
++ nodeOffset = lastTextNode.previousSibling.length;
++ lastTextNode = (lastTextNode.previousSibling);
++ lastTextNode.parentNode.removeChild(lastTextNode.nextSibling)
++ }
++ return{textNode:lastTextNode, offset:nodeOffset}
+ }
- };
- /*
-
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- This file is part of WebODF.
-
- WebODF is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License (GNU AGPL)
- as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version.
-
- WebODF is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with WebODF. If not, see <http://www.gnu.org/licenses/>.
- @licend
-
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- runtime.loadClass("ops.Member");
- ops.OpAddMember = function OpAddMember() {
- var memberid, timestamp, setProperties;
- this.init = function(data) {
- memberid = data.memberid;
- timestamp = parseInt(data.timestamp, 10);
- setProperties = data.setProperties
- };
- this.isEdit = false;
- this.execute = function(odtDocument) {
- if(odtDocument.getMember(memberid)) {
- return false
++ function getParagraphElement(node) {
++ return odfUtils.getParagraphElement(node)
++ }
++ function getStyleElement(styleName, styleFamily) {
++ return odfCanvas.getFormatting().getStyleElement(styleName, styleFamily)
++ }
++ this.getStyleElement = getStyleElement;
++ function getParagraphStyleElement(styleName) {
++ return getStyleElement(styleName, "paragraph")
++ }
++ function getParagraphStyleAttributes(styleName) {
++ var node = getParagraphStyleElement(styleName);
++ if(node) {
++ return odfCanvas.getFormatting().getInheritedStyleAttributes(node)
++ }
++ return null
++ }
++ function handleOperationExecuted(op) {
++ var spec = op.spec(), memberId = spec.memberid, date = (new Date(spec.timestamp)).toISOString(), metadataManager = odfCanvas.odfContainer().getMetadataManager(), fullName;
++ if(op.isEdit) {
++ fullName = self.getMember(memberId).getProperties().fullName;
++ metadataManager.setMetadata({"dc:creator":fullName, "dc:date":date}, null);
++ if(!lastEditingOp) {
++ metadataManager.incrementEditingCycles();
++ if(!unsupportedMetadataRemoved) {
++ metadataManager.setMetadata(null, ["meta:editing-duration", "meta:document-statistic"])
++ }
++ }
++ lastEditingOp = op
++ }
++ }
++ function upgradeWhitespaceToElement(textNode, offset) {
++ runtime.assert(textNode.data[offset] === " ", "upgradeWhitespaceToElement: textNode.data[offset] should be a literal space");
++ var space = textNode.ownerDocument.createElementNS(odf.Namespaces.textns, "text:s");
++ space.appendChild(textNode.ownerDocument.createTextNode(" "));
++ textNode.deleteData(offset, 1);
++ if(offset > 0) {
++ textNode = (textNode.splitText(offset))
+ }
- var member = new ops.Member(memberid, setProperties);
- odtDocument.addMember(member);
- odtDocument.emit(ops.OdtDocument.signalMemberAdded, member);
- return true
- };
- this.spec = function() {
- return{optype:"AddMember", memberid:memberid, timestamp:timestamp, setProperties:setProperties}
++ textNode.parentNode.insertBefore(space, textNode);
++ return space
+ }
- };
- /*
-
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- This file is part of WebODF.
-
- WebODF is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License (GNU AGPL)
- as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version.
-
- WebODF is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with WebODF. If not, see <http://www.gnu.org/licenses/>.
- @licend
-
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- runtime.loadClass("ops.Member");
- runtime.loadClass("xmldom.XPath");
- ops.OpUpdateMember = function OpUpdateMember() {
- var memberid, timestamp, setProperties, removedProperties, doc;
- this.init = function(data) {
- memberid = data.memberid;
- timestamp = parseInt(data.timestamp, 10);
- setProperties = data.setProperties;
- removedProperties = data.removedProperties
- };
- this.isEdit = false;
- function updateCreators() {
- var xpath = new xmldom.XPath, xp = "//dc:creator[@editinfo:memberid='" + memberid + "']", creators = xpath.getODFElementsWithXPath(doc.getRootNode(), xp, function(prefix) {
- if(prefix === "editinfo") {
- return"urn:webodf:names:editinfo"
++ function upgradeWhitespacesAtPosition(position) {
++ var iterator = getIteratorAtPosition(position), container, offset, i;
++ iterator.previousPosition();
++ iterator.previousPosition();
++ for(i = -1;i <= 1;i += 1) {
++ container = iterator.container();
++ offset = iterator.unfilteredDomOffset();
++ if(container.nodeType === Node.TEXT_NODE && (container.data[offset] === " " && odfUtils.isSignificantWhitespace(container, offset))) {
++ container = upgradeWhitespaceToElement((container), offset);
++ iterator.moveToEndOfNode(container)
+ }
- return odf.Namespaces.resolvePrefix(prefix)
- }), i;
- for(i = 0;i < creators.length;i += 1) {
- creators[i].textContent = setProperties.fullName
++ iterator.nextPosition()
+ }
+ }
- this.execute = function(odtDocument) {
- doc = odtDocument;
- var member = odtDocument.getMember(memberid);
- if(!member) {
- return false
++ this.upgradeWhitespacesAtPosition = upgradeWhitespacesAtPosition;
++ this.downgradeWhitespacesAtPosition = function(position) {
++ var iterator = getIteratorAtPosition(position), container, offset, firstSpaceElementChild, lastSpaceElementChild;
++ container = iterator.container();
++ offset = iterator.unfilteredDomOffset();
++ while(!odfUtils.isCharacterElement(container) && container.childNodes[offset]) {
++ container = container.childNodes[offset];
++ offset = 0
+ }
- if(removedProperties) {
- member.removeProperties(removedProperties)
++ if(container.nodeType === Node.TEXT_NODE) {
++ container = container.parentNode
+ }
- if(setProperties) {
- member.setProperties(setProperties);
- if(setProperties.fullName) {
- updateCreators()
++ if(odfUtils.isDowngradableSpaceElement(container)) {
++ firstSpaceElementChild = container.firstChild;
++ lastSpaceElementChild = container.lastChild;
++ domUtils.mergeIntoParent(container);
++ if(lastSpaceElementChild !== firstSpaceElementChild) {
++ domUtils.normalizeTextNodes(lastSpaceElementChild)
+ }
++ domUtils.normalizeTextNodes(firstSpaceElementChild)
+ }
- odtDocument.emit(ops.OdtDocument.signalMemberUpdated, member);
- return true
+ };
- this.spec = function() {
- return{optype:"UpdateMember", memberid:memberid, timestamp:timestamp, setProperties:setProperties, removedProperties:removedProperties}
- }
- };
- /*
-
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- This file is part of WebODF.
-
- WebODF is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License (GNU AGPL)
- as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version.
-
- WebODF is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with WebODF. If not, see <http://www.gnu.org/licenses/>.
- @licend
-
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- runtime.loadClass("ops.Member");
- ops.OpRemoveMember = function OpRemoveMember() {
- var memberid, timestamp;
- this.init = function(data) {
- memberid = data.memberid;
- timestamp = parseInt(data.timestamp, 10)
++ this.getParagraphStyleElement = getParagraphStyleElement;
++ this.getParagraphElement = getParagraphElement;
++ this.getParagraphStyleAttributes = getParagraphStyleAttributes;
++ this.getTextNodeAtStep = getTextNodeAtStep;
++ this.fixCursorPositions = function() {
++ var rootConstrainedFilter = new core.PositionFilterChain;
++ rootConstrainedFilter.addFilter("BaseFilter", filter);
++ Object.keys(cursors).forEach(function(memberId) {
++ var cursor = cursors[memberId], stepCounter = cursor.getStepCounter(), stepsSelectionLength, positionsToAdjustFocus, positionsToAdjustAnchor, positionsToAnchor, cursorMoved = false;
++ rootConstrainedFilter.addFilter("RootFilter", self.createRootFilter(memberId));
++ stepsSelectionLength = stepCounter.countStepsToPosition(cursor.getAnchorNode(), 0, rootConstrainedFilter);
++ if(!stepCounter.isPositionWalkable(rootConstrainedFilter)) {
++ cursorMoved = true;
++ positionsToAdjustFocus = stepCounter.countPositionsToNearestStep(cursor.getNode(), 0, rootConstrainedFilter);
++ positionsToAdjustAnchor = stepCounter.countPositionsToNearestStep(cursor.getAnchorNode(), 0, rootConstrainedFilter);
++ cursor.move(positionsToAdjustFocus);
++ if(stepsSelectionLength !== 0) {
++ if(positionsToAdjustAnchor > 0) {
++ stepsSelectionLength += 1
++ }
++ if(positionsToAdjustFocus > 0) {
++ stepsSelectionLength -= 1
++ }
++ positionsToAnchor = stepCounter.countSteps(stepsSelectionLength, rootConstrainedFilter);
++ cursor.move(positionsToAnchor);
++ cursor.move(-positionsToAnchor, true)
++ }
++ }else {
++ if(stepsSelectionLength === 0) {
++ cursorMoved = true;
++ cursor.move(0)
++ }
++ }
++ if(cursorMoved) {
++ self.emit(ops.OdtDocument.signalCursorMoved, cursor)
++ }
++ rootConstrainedFilter.removeFilter("RootFilter")
++ })
+ };
- this.isEdit = false;
- this.execute = function(odtDocument) {
- if(!odtDocument.getMember(memberid)) {
- return false
++ this.getDistanceFromCursor = function(memberid, node, offset) {
++ var cursor = cursors[memberid], focusPosition, targetPosition;
++ runtime.assert(node !== null && node !== undefined, "OdtDocument.getDistanceFromCursor called without node");
++ if(cursor) {
++ focusPosition = stepsTranslator.convertDomPointToSteps(cursor.getNode(), 0);
++ targetPosition = stepsTranslator.convertDomPointToSteps(node, offset)
+ }
- odtDocument.removeMember(memberid);
- odtDocument.emit(ops.OdtDocument.signalMemberRemoved, memberid);
- return true
++ return targetPosition - focusPosition
++ };
++ this.getCursorPosition = function(memberid) {
++ var cursor = cursors[memberid];
++ return cursor ? stepsTranslator.convertDomPointToSteps(cursor.getNode(), 0) : 0
++ };
++ this.getCursorSelection = function(memberid) {
++ var cursor = cursors[memberid], focusPosition = 0, anchorPosition = 0;
++ if(cursor) {
++ focusPosition = stepsTranslator.convertDomPointToSteps(cursor.getNode(), 0);
++ anchorPosition = stepsTranslator.convertDomPointToSteps(cursor.getAnchorNode(), 0)
++ }
++ return{position:anchorPosition, length:focusPosition - anchorPosition}
++ };
++ this.getPositionFilter = function() {
++ return filter
++ };
++ this.getOdfCanvas = function() {
++ return odfCanvas
++ };
++ this.getRootNode = getRootNode;
++ this.addMember = function(member) {
++ runtime.assert(members[member.getMemberId()] === undefined, "This member already exists");
++ members[member.getMemberId()] = member
++ };
++ this.getMember = function(memberId) {
++ return members.hasOwnProperty(memberId) ? members[memberId] : null
++ };
++ this.removeMember = function(memberId) {
++ delete members[memberId]
++ };
++ this.getCursor = function(memberid) {
++ return cursors[memberid]
++ };
++ this.getCursors = function() {
++ var list = [], i;
++ for(i in cursors) {
++ if(cursors.hasOwnProperty(i)) {
++ list.push(cursors[i])
++ }
++ }
++ return list
++ };
++ this.addCursor = function(cursor) {
++ runtime.assert(Boolean(cursor), "OdtDocument::addCursor without cursor");
++ var distanceToFirstTextNode = cursor.getStepCounter().countSteps(1, filter), memberid = cursor.getMemberId();
++ runtime.assert(typeof memberid === "string", "OdtDocument::addCursor has cursor without memberid");
++ runtime.assert(!cursors[memberid], "OdtDocument::addCursor is adding a duplicate cursor with memberid " + memberid);
++ cursor.move(distanceToFirstTextNode);
++ cursors[memberid] = cursor
++ };
++ this.removeCursor = function(memberid) {
++ var cursor = cursors[memberid];
++ if(cursor) {
++ cursor.removeFromOdtDocument();
++ delete cursors[memberid];
++ self.emit(ops.OdtDocument.signalCursorRemoved, memberid);
++ return true
++ }
++ return false
++ };
++ this.getFormatting = function() {
++ return odfCanvas.getFormatting()
++ };
++ this.emit = function(eventid, args) {
++ eventNotifier.emit(eventid, args)
++ };
++ this.subscribe = function(eventid, cb) {
++ eventNotifier.subscribe(eventid, cb)
++ };
++ this.unsubscribe = function(eventid, cb) {
++ eventNotifier.unsubscribe(eventid, cb)
++ };
++ this.createRootFilter = function(inputMemberId) {
++ return new RootFilter(inputMemberId)
+ };
- this.spec = function() {
- return{optype:"RemoveMember", memberid:memberid, timestamp:timestamp}
++ this.close = function(callback) {
++ callback()
++ };
++ this.destroy = function(callback) {
++ callback()
++ };
++ function init() {
++ filter = new ops.TextPositionFilter(getRootNode);
++ odfUtils = new odf.OdfUtils;
++ domUtils = new core.DomUtils;
++ stepsTranslator = new ops.StepsTranslator(getRootNode, gui.SelectionMover.createPositionIterator, filter, 500);
++ eventNotifier.subscribe(ops.OdtDocument.signalStepsInserted, stepsTranslator.handleStepsInserted);
++ eventNotifier.subscribe(ops.OdtDocument.signalStepsRemoved, stepsTranslator.handleStepsRemoved);
++ eventNotifier.subscribe(ops.OdtDocument.signalOperationExecuted, handleOperationExecuted)
+ }
++ init()
+};
++ops.OdtDocument.signalMemberAdded = "member/added";
++ops.OdtDocument.signalMemberUpdated = "member/updated";
++ops.OdtDocument.signalMemberRemoved = "member/removed";
++ops.OdtDocument.signalCursorAdded = "cursor/added";
++ops.OdtDocument.signalCursorRemoved = "cursor/removed";
++ops.OdtDocument.signalCursorMoved = "cursor/moved";
++ops.OdtDocument.signalParagraphChanged = "paragraph/changed";
++ops.OdtDocument.signalTableAdded = "table/added";
++ops.OdtDocument.signalCommonStyleCreated = "style/created";
++ops.OdtDocument.signalCommonStyleDeleted = "style/deleted";
++ops.OdtDocument.signalParagraphStyleModified = "paragraphstyle/modified";
++ops.OdtDocument.signalOperationExecuted = "operation/executed";
++ops.OdtDocument.signalUndoStackChanged = "undo/changed";
++ops.OdtDocument.signalStepsInserted = "steps/inserted";
++ops.OdtDocument.signalStepsRemoved = "steps/removed";
++(function() {
++ return ops.OdtDocument
++})();
+/*
+
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
- This file is part of WebODF.
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
- WebODF is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License (GNU AGPL)
- as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version.
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
- WebODF is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
+
- You should have received a copy of the GNU Affero General Public License
- along with WebODF. If not, see <http://www.gnu.org/licenses/>.
- @licend
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
+
++ This license applies to this entire compilation.
++ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.OpUpdateMetadata = function OpUpdateMetadata() {
- var memberid, timestamp, setProperties, removedProperties;
- this.init = function(data) {
- memberid = data.memberid;
- timestamp = parseInt(data.timestamp, 10);
- setProperties = data.setProperties;
- removedProperties = data.removedProperties
- };
- this.isEdit = true;
- this.execute = function(odtDocument) {
- var metadataManager = odtDocument.getOdfCanvas().odfContainer().getMetadataManager(), removedPropertiesArray = [], blockedProperties = ["dc:date", "dc:creator", "meta:editing-cycles"];
- if(setProperties) {
- blockedProperties.forEach(function(el) {
- if(setProperties[el]) {
- return false
++ops.Operation = function Operation() {
++};
++ops.Operation.prototype.init = function(data) {
++};
++ops.Operation.prototype.isEdit;
++ops.Operation.prototype.execute = function(odtDocument) {
++};
++ops.Operation.prototype.spec = function() {
++};
++runtime.loadClass("xmldom.RelaxNGParser");
++xmldom.RelaxNGItem;
++xmldom.RelaxNG = function RelaxNG() {
++ var xmlnsns = "http://www.w3.org/2000/xmlns/", createChoice, createInterleave, createGroup, createAfter, createOneOrMore, createValue, createAttribute, createNameClass, createData, makePattern, applyAfter, childDeriv, rootPattern, notAllowed = {type:"notAllowed", nullable:false, hash:"notAllowed", nc:undefined, p:undefined, p1:undefined, p2:undefined, textDeriv:function() {
++ return notAllowed
++ }, startTagOpenDeriv:function() {
++ return notAllowed
++ }, attDeriv:function() {
++ return notAllowed
++ }, startTagCloseDeriv:function() {
++ return notAllowed
++ }, endTagDeriv:function() {
++ return notAllowed
++ }}, empty = {type:"empty", nullable:true, hash:"empty", nc:undefined, p:undefined, p1:undefined, p2:undefined, textDeriv:function() {
++ return notAllowed
++ }, startTagOpenDeriv:function() {
++ return notAllowed
++ }, attDeriv:function() {
++ return notAllowed
++ }, startTagCloseDeriv:function() {
++ return empty
++ }, endTagDeriv:function() {
++ return notAllowed
++ }}, text = {type:"text", nullable:true, hash:"text", nc:undefined, p:undefined, p1:undefined, p2:undefined, textDeriv:function() {
++ return text
++ }, startTagOpenDeriv:function() {
++ return notAllowed
++ }, attDeriv:function() {
++ return notAllowed
++ }, startTagCloseDeriv:function() {
++ return text
++ }, endTagDeriv:function() {
++ return notAllowed
++ }};
++ function memoize0arg(func) {
++ function f() {
++ var cache;
++ function g() {
++ if(cache === undefined) {
++ cache = func()
++ }
++ return cache
++ }
++ return g
++ }
++ return f()
++ }
++ function memoize1arg(type, func) {
++ function f() {
++ var cache = {}, cachecount = 0;
++ function g(a) {
++ var ahash = a.hash || a.toString(), v;
++ if(cache.hasOwnProperty(ahash)) {
++ return cache[ahash]
++ }
++ cache[ahash] = v = func(a);
++ v.hash = type + cachecount.toString();
++ cachecount += 1;
++ return v
++ }
++ return g
++ }
++ return f()
++ }
++ function memoizeNode(func) {
++ function f() {
++ var cache = {};
++ function g(node) {
++ var v, m;
++ if(!cache.hasOwnProperty(node.localName)) {
++ cache[node.localName] = m = {}
++ }else {
++ m = cache[node.localName];
++ v = m[node.namespaceURI];
++ if(v !== undefined) {
++ return v
++ }
++ }
++ m[node.namespaceURI] = v = func(node);
++ return v
++ }
++ return g
++ }
++ return f()
++ }
++ function memoize2arg(type, fastfunc, func) {
++ function f() {
++ var cache = {}, cachecount = 0;
++ function g(a, b) {
++ var v = fastfunc && fastfunc(a, b), ahash, bhash, m;
++ if(v !== undefined) {
++ return v
++ }
++ ahash = a.hash || a.toString();
++ bhash = b.hash || b.toString();
++ if(!cache.hasOwnProperty(ahash)) {
++ cache[ahash] = m = {}
++ }else {
++ m = cache[ahash];
++ if(m.hasOwnProperty(bhash)) {
++ return m[bhash]
++ }
++ }
++ m[bhash] = v = func(a, b);
++ v.hash = type + cachecount.toString();
++ cachecount += 1;
++ return v
++ }
++ return g
++ }
++ return f()
++ }
++ function unorderedMemoize2arg(type, fastfunc, func) {
++ function f() {
++ var cache = {}, cachecount = 0;
++ function g(a, b) {
++ var v = fastfunc && fastfunc(a, b), ahash, bhash, hash, m;
++ if(v !== undefined) {
++ return v
++ }
++ ahash = a.hash || a.toString();
++ bhash = b.hash || b.toString();
++ if(ahash < bhash) {
++ hash = ahash;
++ ahash = bhash;
++ bhash = hash;
++ hash = a;
++ a = b;
++ b = hash
++ }
++ if(!cache.hasOwnProperty(ahash)) {
++ cache[ahash] = m = {}
++ }else {
++ m = cache[ahash];
++ if(m.hasOwnProperty(bhash)) {
++ return m[bhash]
++ }
++ }
++ m[bhash] = v = func(a, b);
++ v.hash = type + cachecount.toString();
++ cachecount += 1;
++ return v
++ }
++ return g
++ }
++ return f()
++ }
++ function getUniqueLeaves(leaves, pattern) {
++ if(pattern.p1.type === "choice") {
++ getUniqueLeaves(leaves, pattern.p1)
++ }else {
++ leaves[pattern.p1.hash] = pattern.p1
++ }
++ if(pattern.p2.type === "choice") {
++ getUniqueLeaves(leaves, pattern.p2)
++ }else {
++ leaves[pattern.p2.hash] = pattern.p2
++ }
++ }
++ createChoice = memoize2arg("choice", function(p1, p2) {
++ if(p1 === notAllowed) {
++ return p2
++ }
++ if(p2 === notAllowed) {
++ return p1
++ }
++ if(p1 === p2) {
++ return p1
++ }
++ }, function(p1, p2) {
++ function makeChoice(p1, p2) {
++ return{type:"choice", nullable:p1.nullable || p2.nullable, hash:undefined, nc:undefined, p:undefined, p1:p1, p2:p2, textDeriv:function(context, text) {
++ return createChoice(p1.textDeriv(context, text), p2.textDeriv(context, text))
++ }, startTagOpenDeriv:memoizeNode(function(node) {
++ return createChoice(p1.startTagOpenDeriv(node), p2.startTagOpenDeriv(node))
++ }), attDeriv:function(context, attribute) {
++ return createChoice(p1.attDeriv(context, attribute), p2.attDeriv(context, attribute))
++ }, startTagCloseDeriv:memoize0arg(function() {
++ return createChoice(p1.startTagCloseDeriv(), p2.startTagCloseDeriv())
++ }), endTagDeriv:memoize0arg(function() {
++ return createChoice(p1.endTagDeriv(), p2.endTagDeriv())
++ })}
++ }
++ var leaves = {}, i;
++ getUniqueLeaves(leaves, {p1:p1, p2:p2});
++ p1 = undefined;
++ p2 = undefined;
++ for(i in leaves) {
++ if(leaves.hasOwnProperty(i)) {
++ if(p1 === undefined) {
++ p1 = leaves[i]
++ }else {
++ if(p2 === undefined) {
++ p2 = leaves[i]
++ }else {
++ p2 = createChoice(p2, leaves[i])
++ }
+ }
- })
++ }
+ }
- if(removedProperties) {
- blockedProperties.forEach(function(el) {
- if(removedPropertiesArray.indexOf(el) !== -1) {
- return false
- }
- });
- removedPropertiesArray = removedProperties.attributes.split(",")
++ return makeChoice(p1, p2)
++ });
++ createInterleave = unorderedMemoize2arg("interleave", function(p1, p2) {
++ if(p1 === notAllowed || p2 === notAllowed) {
++ return notAllowed
+ }
- metadataManager.setMetadata(setProperties, removedPropertiesArray);
- return true
- };
- this.spec = function() {
- return{optype:"UpdateMetadata", memberid:memberid, timestamp:timestamp, setProperties:setProperties, removedProperties:removedProperties}
- }
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- runtime.loadClass("ops.OpAddMember");
- runtime.loadClass("ops.OpUpdateMember");
- runtime.loadClass("ops.OpRemoveMember");
- runtime.loadClass("ops.OpAddCursor");
- runtime.loadClass("ops.OpApplyDirectStyling");
- runtime.loadClass("ops.OpRemoveCursor");
- runtime.loadClass("ops.OpMoveCursor");
- runtime.loadClass("ops.OpSetBlob");
- runtime.loadClass("ops.OpRemoveBlob");
- runtime.loadClass("ops.OpInsertImage");
- runtime.loadClass("ops.OpInsertTable");
- runtime.loadClass("ops.OpInsertText");
- runtime.loadClass("ops.OpRemoveText");
- runtime.loadClass("ops.OpSplitParagraph");
- runtime.loadClass("ops.OpSetParagraphStyle");
- runtime.loadClass("ops.OpUpdateParagraphStyle");
- runtime.loadClass("ops.OpAddStyle");
- runtime.loadClass("ops.OpRemoveStyle");
- runtime.loadClass("ops.OpAddAnnotation");
- runtime.loadClass("ops.OpRemoveAnnotation");
- runtime.loadClass("ops.OpUpdateMetadata");
- ops.OperationFactory = function OperationFactory() {
- var specs;
- this.register = function(specName, specConstructor) {
- specs[specName] = specConstructor
- };
- this.create = function(spec) {
- var op = null, specConstructor = specs[spec.optype];
- if(specConstructor) {
- op = specConstructor(spec);
- op.init(spec)
++ if(p1 === empty) {
++ return p2
+ }
- return op
- };
- function constructor(OperationType) {
- return function() {
- return new OperationType
++ if(p2 === empty) {
++ return p1
+ }
++ }, function(p1, p2) {
++ return{type:"interleave", nullable:p1.nullable && p2.nullable, hash:undefined, p1:p1, p2:p2, textDeriv:function(context, text) {
++ return createChoice(createInterleave(p1.textDeriv(context, text), p2), createInterleave(p1, p2.textDeriv(context, text)))
++ }, startTagOpenDeriv:memoizeNode(function(node) {
++ return createChoice(applyAfter(function(p) {
++ return createInterleave(p, p2)
++ }, p1.startTagOpenDeriv(node)), applyAfter(function(p) {
++ return createInterleave(p1, p)
++ }, p2.startTagOpenDeriv(node)))
++ }), attDeriv:function(context, attribute) {
++ return createChoice(createInterleave(p1.attDeriv(context, attribute), p2), createInterleave(p1, p2.attDeriv(context, attribute)))
++ }, startTagCloseDeriv:memoize0arg(function() {
++ return createInterleave(p1.startTagCloseDeriv(), p2.startTagCloseDeriv())
++ }), endTagDeriv:undefined}
++ });
++ createGroup = memoize2arg("group", function(p1, p2) {
++ if(p1 === notAllowed || p2 === notAllowed) {
++ return notAllowed
++ }
++ if(p1 === empty) {
++ return p2
++ }
++ if(p2 === empty) {
++ return p1
++ }
++ }, function(p1, p2) {
++ return{type:"group", p1:p1, p2:p2, nullable:p1.nullable && p2.nullable, textDeriv:function(context, text) {
++ var p = createGroup(p1.textDeriv(context, text), p2);
++ if(p1.nullable) {
++ return createChoice(p, p2.textDeriv(context, text))
++ }
++ return p
++ }, startTagOpenDeriv:function(node) {
++ var x = applyAfter(function(p) {
++ return createGroup(p, p2)
++ }, p1.startTagOpenDeriv(node));
++ if(p1.nullable) {
++ return createChoice(x, p2.startTagOpenDeriv(node))
++ }
++ return x
++ }, attDeriv:function(context, attribute) {
++ return createChoice(createGroup(p1.attDeriv(context, attribute), p2), createGroup(p1, p2.attDeriv(context, attribute)))
++ }, startTagCloseDeriv:memoize0arg(function() {
++ return createGroup(p1.startTagCloseDeriv(), p2.startTagCloseDeriv())
++ })}
++ });
++ createAfter = memoize2arg("after", function(p1, p2) {
++ if(p1 === notAllowed || p2 === notAllowed) {
++ return notAllowed
++ }
++ }, function(p1, p2) {
++ return{type:"after", p1:p1, p2:p2, nullable:false, textDeriv:function(context, text) {
++ return createAfter(p1.textDeriv(context, text), p2)
++ }, startTagOpenDeriv:memoizeNode(function(node) {
++ return applyAfter(function(p) {
++ return createAfter(p, p2)
++ }, p1.startTagOpenDeriv(node))
++ }), attDeriv:function(context, attribute) {
++ return createAfter(p1.attDeriv(context, attribute), p2)
++ }, startTagCloseDeriv:memoize0arg(function() {
++ return createAfter(p1.startTagCloseDeriv(), p2)
++ }), endTagDeriv:memoize0arg(function() {
++ return p1.nullable ? p2 : notAllowed
++ })}
++ });
++ createOneOrMore = memoize1arg("oneormore", function(p) {
++ if(p === notAllowed) {
++ return notAllowed
++ }
++ return{type:"oneOrMore", p:p, nullable:p.nullable, textDeriv:function(context, text) {
++ return createGroup(p.textDeriv(context, text), createChoice(this, empty))
++ }, startTagOpenDeriv:function(node) {
++ var oneOrMore = this;
++ return applyAfter(function(pf) {
++ return createGroup(pf, createChoice(oneOrMore, empty))
++ }, p.startTagOpenDeriv(node))
++ }, attDeriv:function(context, attribute) {
++ var oneOrMore = this;
++ return createGroup(p.attDeriv(context, attribute), createChoice(oneOrMore, empty))
++ }, startTagCloseDeriv:memoize0arg(function() {
++ return createOneOrMore(p.startTagCloseDeriv())
++ })}
++ });
++ function createElement(nc, p) {
++ return{type:"element", nc:nc, nullable:false, textDeriv:function() {
++ return notAllowed
++ }, startTagOpenDeriv:function(node) {
++ if(nc.contains(node)) {
++ return createAfter(p, empty)
++ }
++ return notAllowed
++ }, attDeriv:function() {
++ return notAllowed
++ }, startTagCloseDeriv:function() {
++ return this
++ }}
+ }
- function init() {
- specs = {AddMember:constructor(ops.OpAddMember), UpdateMember:constructor(ops.OpUpdateMember), RemoveMember:constructor(ops.OpRemoveMember), AddCursor:constructor(ops.OpAddCursor), ApplyDirectStyling:constructor(ops.OpApplyDirectStyling), SetBlob:constructor(ops.OpSetBlob), RemoveBlob:constructor(ops.OpRemoveBlob), InsertImage:constructor(ops.OpInsertImage), InsertTable:constructor(ops.OpInsertTable), InsertText:constructor(ops.OpInsertText), RemoveText:constructor(ops.OpRemoveText) [...]
- SetParagraphStyle:constructor(ops.OpSetParagraphStyle), UpdateParagraphStyle:constructor(ops.OpUpdateParagraphStyle), AddStyle:constructor(ops.OpAddStyle), RemoveStyle:constructor(ops.OpRemoveStyle), MoveCursor:constructor(ops.OpMoveCursor), RemoveCursor:constructor(ops.OpRemoveCursor), AddAnnotation:constructor(ops.OpAddAnnotation), RemoveAnnotation:constructor(ops.OpRemoveAnnotation), UpdateMetadata:constructor(ops.OpUpdateMetadata)}
- }
- init()
- };
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- runtime.loadClass("core.Cursor");
- runtime.loadClass("core.DomUtils");
- runtime.loadClass("core.PositionIterator");
- runtime.loadClass("core.PositionFilter");
- runtime.loadClass("core.LoopWatchDog");
- runtime.loadClass("odf.OdfUtils");
- gui.SelectionMover = function SelectionMover(cursor, rootNode) {
- var odfUtils, domUtils, positionIterator, cachedXOffset, timeoutHandle, FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT;
- function getIteratorAtCursor() {
- positionIterator.setUnfilteredPosition(cursor.getNode(), 0);
- return positionIterator
++ function valueMatch(context, pattern, text) {
++ return pattern.nullable && /^\s+$/.test(text) || pattern.textDeriv(context, text).nullable
+ }
- function getMaximumNodePosition(node) {
- return node.nodeType === Node.TEXT_NODE ? node.textContent.length : node.childNodes.length
++ createAttribute = memoize2arg("attribute", undefined, function(nc, p) {
++ return{type:"attribute", nullable:false, hash:undefined, nc:nc, p:p, p1:undefined, p2:undefined, textDeriv:undefined, startTagOpenDeriv:undefined, attDeriv:function(context, attribute) {
++ if(nc.contains(attribute) && valueMatch(context, p, attribute.nodeValue)) {
++ return empty
++ }
++ return notAllowed
++ }, startTagCloseDeriv:function() {
++ return notAllowed
++ }, endTagDeriv:undefined}
++ });
++ function createList() {
++ return{type:"list", nullable:false, hash:"list", textDeriv:function() {
++ return empty
++ }}
+ }
- function getClientRect(clientRectangles, useRightEdge) {
- var rectangle, simplifiedRectangle = null;
- if(clientRectangles) {
- rectangle = useRightEdge ? clientRectangles[clientRectangles.length - 1] : clientRectangles[0]
++ createValue = memoize1arg("value", function(value) {
++ return{type:"value", nullable:false, value:value, textDeriv:function(context, text) {
++ return text === value ? empty : notAllowed
++ }, attDeriv:function() {
++ return notAllowed
++ }, startTagCloseDeriv:function() {
++ return this
++ }}
++ });
++ createData = memoize1arg("data", function(type) {
++ return{type:"data", nullable:false, dataType:type, textDeriv:function() {
++ return empty
++ }, attDeriv:function() {
++ return notAllowed
++ }, startTagCloseDeriv:function() {
++ return this
++ }}
++ });
++ applyAfter = function applyAfter(f, p) {
++ var result;
++ if(p.type === "after") {
++ result = createAfter(p.p1, f(p.p2))
++ }else {
++ if(p.type === "choice") {
++ result = createChoice(applyAfter(f, p.p1), applyAfter(f, p.p2))
++ }else {
++ result = p
++ }
+ }
- if(rectangle) {
- simplifiedRectangle = {top:rectangle.top, left:useRightEdge ? rectangle.right : rectangle.left, bottom:rectangle.bottom}
++ return result
++ };
++ function attsDeriv(context, pattern, attributes, position) {
++ if(pattern === notAllowed) {
++ return notAllowed
+ }
- return simplifiedRectangle
- }
- function getVisibleRect(container, offset, range, useRightEdge) {
- var rectangle, nodeType = container.nodeType;
- range.setStart(container, offset);
- range.collapse(!useRightEdge);
- rectangle = getClientRect(range.getClientRects(), useRightEdge === true);
- if(!rectangle && offset > 0) {
- range.setStart(container, offset - 1);
- range.setEnd(container, offset);
- rectangle = getClientRect(range.getClientRects(), true)
++ if(position >= attributes.length) {
++ return pattern
+ }
- if(!rectangle) {
- if(nodeType === Node.ELEMENT_NODE && container.childNodes[offset - 1]) {
- rectangle = getVisibleRect(container, offset - 1, range, true)
++ if(position === 0) {
++ position = 0
++ }
++ var a = attributes.item(position);
++ while(a.namespaceURI === xmlnsns) {
++ position += 1;
++ if(position >= attributes.length) {
++ return pattern
++ }
++ a = attributes.item(position)
++ }
++ a = attsDeriv(context, pattern.attDeriv(context, attributes.item(position)), attributes, position + 1);
++ return a
++ }
++ function childrenDeriv(context, pattern, walker) {
++ var element = walker.currentNode, childNode = walker.firstChild(), childNodes = [], i, p;
++ while(childNode) {
++ if(childNode.nodeType === Node.ELEMENT_NODE) {
++ childNodes.push(childNode)
+ }else {
- if(container.nodeType === Node.TEXT_NODE && offset > 0) {
- rectangle = getVisibleRect(container, offset - 1, range, true)
++ if(childNode.nodeType === Node.TEXT_NODE && !/^\s*$/.test(childNode.nodeValue)) {
++ childNodes.push(childNode.nodeValue)
++ }
++ }
++ childNode = walker.nextSibling()
++ }
++ if(childNodes.length === 0) {
++ childNodes = [""]
++ }
++ p = pattern;
++ for(i = 0;p !== notAllowed && i < childNodes.length;i += 1) {
++ childNode = childNodes[i];
++ if(typeof childNode === "string") {
++ if(/^\s*$/.test(childNode)) {
++ p = createChoice(p, p.textDeriv(context, childNode))
+ }else {
- if(container.previousSibling) {
- rectangle = getVisibleRect(container.previousSibling, getMaximumNodePosition(container.previousSibling), range, true)
- }else {
- if(container.parentNode && container.parentNode !== rootNode) {
- rectangle = getVisibleRect(container.parentNode, 0, range, false)
- }else {
- range.selectNode(rootNode);
- rectangle = getClientRect(range.getClientRects(), false)
- }
- }
++ p = p.textDeriv(context, childNode)
+ }
++ }else {
++ walker.currentNode = childNode;
++ p = childDeriv(context, p, walker)
+ }
+ }
- runtime.assert(Boolean(rectangle), "No visible rectangle found");
- return(rectangle)
++ walker.currentNode = element;
++ return p
+ }
- function doMove(positions, extend, move) {
- var left = positions, iterator = getIteratorAtCursor(), initialRect, range = (rootNode.ownerDocument.createRange()), selectionRange = cursor.getSelectedRange() ? cursor.getSelectedRange().cloneRange() : rootNode.ownerDocument.createRange(), newRect, horizontalMovement, o, c, isForwardSelection;
- initialRect = getVisibleRect(iterator.container(), iterator.unfilteredDomOffset(), range);
- while(left > 0 && move()) {
- left -= 1
++ childDeriv = function childDeriv(context, pattern, walker) {
++ var childNode = walker.currentNode, p;
++ p = pattern.startTagOpenDeriv(childNode);
++ p = attsDeriv(context, p, childNode.attributes, 0);
++ p = p.startTagCloseDeriv();
++ p = childrenDeriv(context, p, walker);
++ p = p.endTagDeriv();
++ return p
++ };
++ function addNames(name, ns, pattern) {
++ if(pattern.e[0].a) {
++ name.push(pattern.e[0].text);
++ ns.push(pattern.e[0].a.ns)
++ }else {
++ addNames(name, ns, pattern.e[0])
+ }
- if(extend) {
- c = iterator.container();
- o = iterator.unfilteredDomOffset();
- if(domUtils.comparePoints(selectionRange.startContainer, selectionRange.startOffset, c, o) === -1) {
- selectionRange.setStart(c, o);
- isForwardSelection = false
++ if(pattern.e[1].a) {
++ name.push(pattern.e[1].text);
++ ns.push(pattern.e[1].a.ns)
++ }else {
++ addNames(name, ns, pattern.e[1])
++ }
++ }
++ createNameClass = function createNameClass(pattern) {
++ var name, ns, hash, i, result;
++ if(pattern.name === "name") {
++ name = pattern.text;
++ ns = pattern.a.ns;
++ result = {name:name, ns:ns, hash:"{" + ns + "}" + name, contains:function(node) {
++ return node.namespaceURI === ns && node.localName === name
++ }}
++ }else {
++ if(pattern.name === "choice") {
++ name = [];
++ ns = [];
++ addNames(name, ns, pattern);
++ hash = "";
++ for(i = 0;i < name.length;i += 1) {
++ hash += "{" + ns[i] + "}" + name[i] + ","
++ }
++ result = {hash:hash, contains:function(node) {
++ var j;
++ for(j = 0;j < name.length;j += 1) {
++ if(name[j] === node.localName && ns[j] === node.namespaceURI) {
++ return true
++ }
++ }
++ return false
++ }}
+ }else {
- selectionRange.setEnd(c, o)
++ result = {hash:"anyName", contains:function() {
++ return true
++ }}
+ }
- }else {
- selectionRange.setStart(iterator.container(), iterator.unfilteredDomOffset());
- selectionRange.collapse(true)
+ }
- cursor.setSelectedRange(selectionRange, isForwardSelection);
- iterator = getIteratorAtCursor();
- newRect = getVisibleRect(iterator.container(), iterator.unfilteredDomOffset(), range);
- horizontalMovement = newRect.top === initialRect.top ? true : false;
- if(horizontalMovement || cachedXOffset === undefined) {
- cachedXOffset = newRect.left
++ return result
++ };
++ function resolveElement(pattern, elements) {
++ var element, p, i, hash;
++ hash = "element" + pattern.id.toString();
++ p = elements[pattern.id] = {hash:hash};
++ element = createElement(createNameClass(pattern.e[0]), makePattern(pattern.e[1], elements));
++ for(i in element) {
++ if(element.hasOwnProperty(i)) {
++ p[i] = element[i]
++ }
+ }
- runtime.clearTimeout(timeoutHandle);
- timeoutHandle = runtime.setTimeout(function() {
- cachedXOffset = undefined
- }, 2E3);
- range.detach();
- return positions - left
++ return p
+ }
- this.movePointForward = function(positions, extend) {
- return doMove(positions, extend || false, positionIterator.nextPosition)
++ makePattern = function makePattern(pattern, elements) {
++ var p, i;
++ if(pattern.name === "elementref") {
++ p = pattern.id || 0;
++ pattern = elements[p];
++ if(pattern.name !== undefined) {
++ return resolveElement(pattern, elements)
++ }
++ return pattern
++ }
++ switch(pattern.name) {
++ case "empty":
++ return empty;
++ case "notAllowed":
++ return notAllowed;
++ case "text":
++ return text;
++ case "choice":
++ return createChoice(makePattern(pattern.e[0], elements), makePattern(pattern.e[1], elements));
++ case "interleave":
++ p = makePattern(pattern.e[0], elements);
++ for(i = 1;i < pattern.e.length;i += 1) {
++ p = createInterleave(p, makePattern(pattern.e[i], elements))
++ }
++ return p;
++ case "group":
++ return createGroup(makePattern(pattern.e[0], elements), makePattern(pattern.e[1], elements));
++ case "oneOrMore":
++ return createOneOrMore(makePattern(pattern.e[0], elements));
++ case "attribute":
++ return createAttribute(createNameClass(pattern.e[0]), makePattern(pattern.e[1], elements));
++ case "value":
++ return createValue(pattern.text);
++ case "data":
++ p = pattern.a && pattern.a.type;
++ if(p === undefined) {
++ p = ""
++ }
++ return createData(p);
++ case "list":
++ return createList()
++ }
++ throw"No support for " + pattern.name;
++ };
++ this.makePattern = function(pattern, elements) {
++ var copy = {}, i;
++ for(i in elements) {
++ if(elements.hasOwnProperty(i)) {
++ copy[i] = elements[i]
++ }
++ }
++ i = makePattern(pattern, copy);
++ return i
+ };
- this.movePointBackward = function(positions, extend) {
- return doMove(positions, extend || false, positionIterator.previousPosition)
++ this.validate = function validate(walker, callback) {
++ var errors;
++ walker.currentNode = walker.root;
++ errors = childDeriv(null, rootPattern, walker);
++ if(!errors.nullable) {
++ runtime.log("Error in Relax NG validation: " + errors);
++ callback(["Error in Relax NG validation: " + errors])
++ }else {
++ callback(null)
++ }
+ };
- function isPositionWalkable(filter) {
- var iterator = getIteratorAtCursor();
- if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
- iterator.setUnfilteredPosition(cursor.getAnchorNode(), 0);
- if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
- return true
++ this.init = function init(rootPattern1) {
++ rootPattern = rootPattern1
++ }
++};
++runtime.loadClass("xmldom.RelaxNGParser");
++xmldom.RelaxNG2 = function RelaxNG2() {
++ var start, validateNonEmptyPattern, nsmap;
++ function RelaxNGParseError(error, context) {
++ this.message = function() {
++ if(context) {
++ error += context.nodeType === Node.ELEMENT_NODE ? " Element " : " Node ";
++ error += context.nodeName;
++ if(context.nodeValue) {
++ error += " with value '" + context.nodeValue + "'"
++ }
++ error += "."
+ }
++ return error
+ }
- return false
+ }
- function countSteps(iterator, steps, filter) {
- var watch = new core.LoopWatchDog(1E4), positions = 0, positionsCount = 0, increment = steps >= 0 ? 1 : -1, delegate = (steps >= 0 ? iterator.nextPosition : iterator.previousPosition);
- while(steps !== 0 && delegate()) {
- watch.check();
- positionsCount += increment;
- if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
- steps -= increment;
- positions += positionsCount;
- positionsCount = 0
- }
++ function validateOneOrMore(elementdef, walker, element) {
++ var node, i = 0, err;
++ do {
++ node = walker.currentNode;
++ err = validateNonEmptyPattern(elementdef.e[0], walker, element);
++ i += 1
++ }while(!err && node !== walker.currentNode);
++ if(i > 1) {
++ walker.currentNode = node;
++ return null
+ }
- return positions
++ return err
+ }
- function convertForwardStepsBetweenFilters(stepsFilter1, filter1, filter2) {
- var iterator = getIteratorAtCursor(), watch = new core.LoopWatchDog(1E4), pendingStepsFilter2 = 0, stepsFilter2 = 0;
- while(stepsFilter1 > 0 && iterator.nextPosition()) {
- watch.check();
- if(filter2.acceptPosition(iterator) === FILTER_ACCEPT) {
- pendingStepsFilter2 += 1;
- if(filter1.acceptPosition(iterator) === FILTER_ACCEPT) {
- stepsFilter2 += pendingStepsFilter2;
- pendingStepsFilter2 = 0;
- stepsFilter1 -= 1
- }
- }
++ function qName(node) {
++ return nsmap[node.namespaceURI] + ":" + node.localName
++ }
++ function isWhitespace(node) {
++ return node && (node.nodeType === Node.TEXT_NODE && /^\s+$/.test(node.nodeValue))
++ }
++ function validatePattern(elementdef, walker, element, data) {
++ if(elementdef.name === "empty") {
++ return null
+ }
- return stepsFilter2
++ return validateNonEmptyPattern(elementdef, walker, element, data)
+ }
- function convertBackwardStepsBetweenFilters(stepsFilter1, filter1, filter2) {
- var iterator = getIteratorAtCursor(), watch = new core.LoopWatchDog(1E4), pendingStepsFilter2 = 0, stepsFilter2 = 0;
- while(stepsFilter1 > 0 && iterator.previousPosition()) {
- watch.check();
- if(filter2.acceptPosition(iterator) === FILTER_ACCEPT) {
- pendingStepsFilter2 += 1;
- if(filter1.acceptPosition(iterator) === FILTER_ACCEPT) {
- stepsFilter2 += pendingStepsFilter2;
- pendingStepsFilter2 = 0;
- stepsFilter1 -= 1
- }
++ function validateAttribute(elementdef, walker, element) {
++ if(elementdef.e.length !== 2) {
++ throw"Attribute with wrong # of elements: " + elementdef.e.length;
++ }
++ var att, a, l = elementdef.localnames.length, i;
++ for(i = 0;i < l;i += 1) {
++ a = element.getAttributeNS(elementdef.namespaces[i], elementdef.localnames[i]);
++ if(a === "" && !element.hasAttributeNS(elementdef.namespaces[i], elementdef.localnames[i])) {
++ a = undefined
++ }
++ if(att !== undefined && a !== undefined) {
++ return[new RelaxNGParseError("Attribute defined too often.", element)]
+ }
++ att = a
+ }
- return stepsFilter2
++ if(att === undefined) {
++ return[new RelaxNGParseError("Attribute not found: " + elementdef.names, element)]
++ }
++ return validatePattern(elementdef.e[1], walker, element, att)
+ }
- function countStepsPublic(steps, filter) {
- var iterator = getIteratorAtCursor();
- return countSteps(iterator, steps, filter)
++ function validateTop(elementdef, walker, element) {
++ return validatePattern(elementdef, walker, element)
+ }
- function countPositionsToClosestStep(container, offset, filter) {
- var iterator = getIteratorAtCursor(), paragraphNode = odfUtils.getParagraphElement(iterator.getCurrentNode()), count = 0;
- iterator.setUnfilteredPosition(container, offset);
- if(filter.acceptPosition(iterator) !== FILTER_ACCEPT) {
- count = countSteps(iterator, -1, filter);
- if(count === 0 || paragraphNode && paragraphNode !== odfUtils.getParagraphElement(iterator.getCurrentNode())) {
- iterator.setUnfilteredPosition(container, offset);
- count = countSteps(iterator, 1, filter)
++ function validateElement(elementdef, walker) {
++ if(elementdef.e.length !== 2) {
++ throw"Element with wrong # of elements: " + elementdef.e.length;
++ }
++ var node = walker.currentNode, type = node ? node.nodeType : 0, error = null;
++ while(type > Node.ELEMENT_NODE) {
++ if(type !== Node.COMMENT_NODE && (type !== Node.TEXT_NODE || !/^\s+$/.test(walker.currentNode.nodeValue))) {
++ return[new RelaxNGParseError("Not allowed node of type " + type + ".")]
+ }
++ node = walker.nextSibling();
++ type = node ? node.nodeType : 0
+ }
- return count
- }
- function countLineSteps(filter, direction, iterator) {
- var c = iterator.container(), steps = 0, bestContainer = null, bestOffset, bestXDiff = 10, xDiff, bestCount = 0, top, left, lastTop, rect, range = (rootNode.ownerDocument.createRange()), watch = new core.LoopWatchDog(1E4);
- rect = getVisibleRect(c, iterator.unfilteredDomOffset(), range);
- top = rect.top;
- if(cachedXOffset === undefined) {
- left = rect.left
- }else {
- left = cachedXOffset
++ if(!node) {
++ return[new RelaxNGParseError("Missing element " + elementdef.names)]
+ }
- lastTop = top;
- while((direction < 0 ? iterator.previousPosition() : iterator.nextPosition()) === true) {
- watch.check();
- if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
- steps += 1;
- c = iterator.container();
- rect = getVisibleRect(c, iterator.unfilteredDomOffset(), range);
- if(rect.top !== top) {
- if(rect.top !== lastTop && lastTop !== top) {
- break
- }
- lastTop = rect.top;
- xDiff = Math.abs(left - rect.left);
- if(bestContainer === null || xDiff < bestXDiff) {
- bestContainer = c;
- bestOffset = iterator.unfilteredDomOffset();
- bestXDiff = xDiff;
- bestCount = steps
- }
++ if(elementdef.names && elementdef.names.indexOf(qName(node)) === -1) {
++ return[new RelaxNGParseError("Found " + node.nodeName + " instead of " + elementdef.names + ".", node)]
++ }
++ if(walker.firstChild()) {
++ error = validateTop(elementdef.e[1], walker, node);
++ while(walker.nextSibling()) {
++ type = walker.currentNode.nodeType;
++ if(!isWhitespace(walker.currentNode) && type !== Node.COMMENT_NODE) {
++ return[new RelaxNGParseError("Spurious content.", walker.currentNode)]
+ }
+ }
- }
- if(bestContainer !== null) {
- iterator.setUnfilteredPosition(bestContainer, (bestOffset));
- steps = bestCount
++ if(walker.parentNode() !== node) {
++ return[new RelaxNGParseError("Implementation error.")]
++ }
+ }else {
- steps = 0
++ error = validateTop(elementdef.e[1], walker, node)
+ }
- range.detach();
- return steps
++ node = walker.nextSibling();
++ return error
+ }
- function countLinesSteps(lines, filter) {
- var iterator = getIteratorAtCursor(), stepCount = 0, steps = 0, direction = lines < 0 ? -1 : 1;
- lines = Math.abs(lines);
- while(lines > 0) {
- stepCount += countLineSteps(filter, direction, iterator);
- if(stepCount === 0) {
- break
++ function validateChoice(elementdef, walker, element, data) {
++ if(elementdef.e.length !== 2) {
++ throw"Choice with wrong # of options: " + elementdef.e.length;
++ }
++ var node = walker.currentNode, err;
++ if(elementdef.e[0].name === "empty") {
++ err = validateNonEmptyPattern(elementdef.e[1], walker, element, data);
++ if(err) {
++ walker.currentNode = node
+ }
- steps += stepCount;
- lines -= 1
++ return null
+ }
- return steps * direction
- }
- function countStepsToLineBoundary(direction, filter) {
- var fnNextPos, increment, lastRect, rect, onSameLine, iterator = getIteratorAtCursor(), paragraphNode = odfUtils.getParagraphElement(iterator.getCurrentNode()), steps = 0, range = (rootNode.ownerDocument.createRange());
- if(direction < 0) {
- fnNextPos = iterator.previousPosition;
- increment = -1
- }else {
- fnNextPos = iterator.nextPosition;
- increment = 1
++ err = validatePattern(elementdef.e[0], walker, element, data);
++ if(err) {
++ walker.currentNode = node;
++ err = validateNonEmptyPattern(elementdef.e[1], walker, element, data)
+ }
- lastRect = getVisibleRect(iterator.container(), iterator.unfilteredDomOffset(), range);
- while(fnNextPos.call(iterator)) {
- if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
- if(odfUtils.getParagraphElement(iterator.getCurrentNode()) !== paragraphNode) {
- break
- }
- rect = getVisibleRect(iterator.container(), iterator.unfilteredDomOffset(), range);
- if(rect.bottom !== lastRect.bottom) {
- onSameLine = rect.top >= lastRect.top && rect.bottom < lastRect.bottom || rect.top <= lastRect.top && rect.bottom > lastRect.bottom;
- if(!onSameLine) {
- break
++ return err
++ }
++ function validateInterleave(elementdef, walker, element) {
++ var l = elementdef.e.length, n = [l], err, i, todo = l, donethisround, node, subnode, e;
++ while(todo > 0) {
++ donethisround = 0;
++ node = walker.currentNode;
++ for(i = 0;i < l;i += 1) {
++ subnode = walker.currentNode;
++ if(n[i] !== true && n[i] !== subnode) {
++ e = elementdef.e[i];
++ err = validateNonEmptyPattern(e, walker, element);
++ if(err) {
++ walker.currentNode = subnode;
++ if(n[i] === undefined) {
++ n[i] = false
++ }
++ }else {
++ if(subnode === walker.currentNode || (e.name === "oneOrMore" || e.name === "choice" && (e.e[0].name === "oneOrMore" || e.e[1].name === "oneOrMore"))) {
++ donethisround += 1;
++ n[i] = subnode
++ }else {
++ donethisround += 1;
++ n[i] = true
++ }
++ }
++ }
++ }
++ if(node === walker.currentNode && donethisround === todo) {
++ return null
++ }
++ if(donethisround === 0) {
++ for(i = 0;i < l;i += 1) {
++ if(n[i] === false) {
++ return[new RelaxNGParseError("Interleave does not match.", element)]
+ }
+ }
- steps += increment;
- lastRect = rect
++ return null
++ }
++ todo = 0;
++ for(i = 0;i < l;i += 1) {
++ if(n[i] !== true) {
++ todo += 1
++ }
+ }
+ }
- range.detach();
- return steps
++ return null
+ }
- function countStepsToPosition(targetNode, targetOffset, filter) {
- runtime.assert(targetNode !== null, "SelectionMover.countStepsToPosition called with element===null");
- var iterator = getIteratorAtCursor(), c = iterator.container(), o = iterator.unfilteredDomOffset(), steps = 0, watch = new core.LoopWatchDog(1E4), comparison;
- iterator.setUnfilteredPosition(targetNode, targetOffset);
- while(filter.acceptPosition(iterator) !== FILTER_ACCEPT && iterator.previousPosition()) {
- watch.check()
- }
- targetNode = iterator.container();
- runtime.assert(Boolean(targetNode), "SelectionMover.countStepsToPosition: positionIterator.container() returned null");
- targetOffset = iterator.unfilteredDomOffset();
- iterator.setUnfilteredPosition(c, o);
- while(filter.acceptPosition(iterator) !== FILTER_ACCEPT && iterator.previousPosition()) {
- watch.check()
++ function validateGroup(elementdef, walker, element) {
++ if(elementdef.e.length !== 2) {
++ throw"Group with wrong # of members: " + elementdef.e.length;
+ }
- comparison = domUtils.comparePoints(targetNode, targetOffset, iterator.container(), iterator.unfilteredDomOffset());
- if(comparison < 0) {
- while(iterator.nextPosition()) {
- watch.check();
- if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
- steps += 1
- }
- if(iterator.container() === targetNode && iterator.unfilteredDomOffset() === targetOffset) {
- return steps
- }
++ return validateNonEmptyPattern(elementdef.e[0], walker, element) || validateNonEmptyPattern(elementdef.e[1], walker, element)
++ }
++ function validateText(elementdef, walker, element) {
++ var node = walker.currentNode, type = node ? node.nodeType : 0;
++ while(node !== element && type !== 3) {
++ if(type === 1) {
++ return[new RelaxNGParseError("Element not allowed here.", node)]
+ }
++ node = walker.nextSibling();
++ type = node ? node.nodeType : 0
++ }
++ walker.nextSibling();
++ return null
++ }
++ validateNonEmptyPattern = function validateNonEmptyPattern(elementdef, walker, element, data) {
++ var name = elementdef.name, err = null;
++ if(name === "text") {
++ err = validateText(elementdef, walker, element)
+ }else {
- if(comparison > 0) {
- while(iterator.previousPosition()) {
- watch.check();
- if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
- steps -= 1;
- if(iterator.container() === targetNode && iterator.unfilteredDomOffset() === targetOffset) {
- break
++ if(name === "data") {
++ err = null
++ }else {
++ if(name === "value") {
++ if(data !== elementdef.text) {
++ err = [new RelaxNGParseError("Wrong value, should be '" + elementdef.text + "', not '" + data + "'", element)]
++ }
++ }else {
++ if(name === "list") {
++ err = null
++ }else {
++ if(name === "attribute") {
++ err = validateAttribute(elementdef, walker, element)
++ }else {
++ if(name === "element") {
++ err = validateElement(elementdef, walker)
++ }else {
++ if(name === "oneOrMore") {
++ err = validateOneOrMore(elementdef, walker, element)
++ }else {
++ if(name === "choice") {
++ err = validateChoice(elementdef, walker, element, data)
++ }else {
++ if(name === "group") {
++ err = validateGroup(elementdef, walker, element)
++ }else {
++ if(name === "interleave") {
++ err = validateInterleave(elementdef, walker, element)
++ }else {
++ throw name + " not allowed in nonEmptyPattern.";
++ }
++ }
++ }
++ }
++ }
+ }
+ }
+ }
+ }
+ }
- return steps
- }
- this.getStepCounter = function() {
- return{countSteps:countStepsPublic, convertForwardStepsBetweenFilters:convertForwardStepsBetweenFilters, convertBackwardStepsBetweenFilters:convertBackwardStepsBetweenFilters, countLinesSteps:countLinesSteps, countStepsToLineBoundary:countStepsToLineBoundary, countStepsToPosition:countStepsToPosition, isPositionWalkable:isPositionWalkable, countPositionsToNearestStep:countPositionsToClosestStep}
++ return err
+ };
- function init() {
- odfUtils = new odf.OdfUtils;
- domUtils = new core.DomUtils;
- positionIterator = gui.SelectionMover.createPositionIterator(rootNode);
- var range = rootNode.ownerDocument.createRange();
- range.setStart(positionIterator.container(), positionIterator.unfilteredDomOffset());
- range.collapse(true);
- cursor.setSelectedRange(range)
- }
- init()
- };
- gui.SelectionMover.createPositionIterator = function(rootNode) {
- function CursorFilter() {
- this.acceptNode = function(node) {
- if(!node || (node.namespaceURI === "urn:webodf:names:cursor" || node.namespaceURI === "urn:webodf:names:editinfo")) {
- return NodeFilter.FILTER_REJECT
- }
- return NodeFilter.FILTER_ACCEPT
- }
++ this.validate = function validate(walker, callback) {
++ walker.currentNode = walker.root;
++ var errors = validatePattern(start.e[0], walker, (walker.root));
++ callback(errors)
++ };
++ this.init = function init(start1, nsmap1) {
++ start = start1;
++ nsmap = nsmap1
+ }
- var filter = new CursorFilter;
- return new core.PositionIterator(rootNode, 5, filter, false)
+};
- (function() {
- return gui.SelectionMover
- })();
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
+runtime.loadClass("core.DomUtils");
- runtime.loadClass("core.PositionFilter");
- runtime.loadClass("odf.OdfUtils");
- (function() {
- var nextNodeId = 0;
- function StepsCache(rootNode, filter, bucketSize) {
- var coordinatens = "urn:webodf:names:steps", stepToDomPoint = {}, nodeToBookmark = {}, odfUtils = new odf.OdfUtils, domUtils = new core.DomUtils, basePoint, FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT;
- function ParagraphBookmark(steps, paragraphNode) {
- this.steps = steps;
- this.node = paragraphNode;
- function positionInContainer(node) {
- var position = 0;
- while(node && node.previousSibling) {
- position += 1;
- node = node.previousSibling
- }
- return position
- }
- this.setIteratorPosition = function(iterator) {
- iterator.setUnfilteredPosition(paragraphNode.parentNode, positionInContainer(paragraphNode));
- do {
- if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
- break
- }
- }while(iterator.nextPosition())
- }
++runtime.loadClass("gui.Avatar");
++runtime.loadClass("ops.OdtCursor");
++gui.Caret = function Caret(cursor, avatarInitiallyVisible, blinkOnRangeSelect) {
++ var MIN_CARET_HEIGHT_PX = 8, DEFAULT_CARET_TOP = "5%", DEFAULT_CARET_HEIGHT = "1em", span, avatar, cursorNode, isShown = true, shouldBlink = false, blinking = false, blinkTimeout, domUtils = new core.DomUtils;
++ function blink(reset) {
++ if(!shouldBlink || !cursorNode.parentNode) {
++ return
+ }
- function RootBookmark(steps, rootNode) {
- this.steps = steps;
- this.node = rootNode;
- this.setIteratorPosition = function(iterator) {
- iterator.setUnfilteredPosition(rootNode, 0);
- do {
- if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
- break
- }
- }while(iterator.nextPosition())
++ if(!blinking || reset) {
++ if(reset && blinkTimeout !== undefined) {
++ runtime.clearTimeout(blinkTimeout)
+ }
++ blinking = true;
++ span.style.opacity = reset || span.style.opacity === "0" ? "1" : "0";
++ blinkTimeout = runtime.setTimeout(function() {
++ blinking = false;
++ blink(false)
++ }, 500)
+ }
- function getBucket(steps) {
- return Math.floor(steps / bucketSize) * bucketSize
- }
- function getDestinationBucket(steps) {
- return Math.ceil(steps / bucketSize) * bucketSize
- }
- function clearNodeId(node) {
- node.removeAttributeNS(coordinatens, "nodeId")
- }
- function getNodeId(node) {
- return node.nodeType === Node.ELEMENT_NODE && node.getAttributeNS(coordinatens, "nodeId")
- }
- function setNodeId(node) {
- var nodeId = nextNodeId;
- node.setAttributeNS(coordinatens, "nodeId", nodeId.toString());
- nextNodeId += 1;
- return nodeId
++ }
++ function getCaretClientRectWithMargin(caretElement, margin) {
++ var caretRect = caretElement.getBoundingClientRect();
++ return{left:caretRect.left - margin.left, top:caretRect.top - margin.top, right:caretRect.right + margin.right, bottom:caretRect.bottom + margin.bottom}
++ }
++ function length(node) {
++ return node.nodeType === Node.TEXT_NODE ? node.textContent.length : node.childNodes.length
++ }
++ function verticalOverlap(cursorNode, rangeRect) {
++ var cursorRect = cursorNode.getBoundingClientRect(), intersectTop = 0, intersectBottom = 0;
++ if(cursorRect && rangeRect) {
++ intersectTop = Math.max(cursorRect.top, rangeRect.top);
++ intersectBottom = Math.min(cursorRect.bottom, rangeRect.bottom)
+ }
- function isValidBookmarkForNode(node, bookmark) {
- return bookmark.node === node
++ return intersectBottom - intersectTop
++ }
++ function getSelectionRect() {
++ var range = cursor.getSelectedRange().cloneRange(), node = cursor.getNode(), nextRectangle, selectionRectangle = null, nodeLength;
++ if(node.previousSibling) {
++ nodeLength = length(node.previousSibling);
++ range.setStart(node.previousSibling, nodeLength > 0 ? nodeLength - 1 : 0);
++ range.setEnd(node.previousSibling, nodeLength);
++ nextRectangle = range.getBoundingClientRect();
++ if(nextRectangle && nextRectangle.height) {
++ selectionRectangle = nextRectangle
++ }
+ }
- function getNodeBookmark(node, steps) {
- var nodeId = getNodeId(node) || setNodeId(node), existingBookmark;
- existingBookmark = nodeToBookmark[nodeId];
- if(!existingBookmark) {
- existingBookmark = nodeToBookmark[nodeId] = new ParagraphBookmark(steps, node)
- }else {
- if(!isValidBookmarkForNode(node, existingBookmark)) {
- runtime.log("Cloned node detected. Creating new bookmark");
- nodeId = setNodeId(node);
- existingBookmark = nodeToBookmark[nodeId] = new ParagraphBookmark(steps, node)
- }else {
- existingBookmark.steps = steps
++ if(node.nextSibling) {
++ range.setStart(node.nextSibling, 0);
++ range.setEnd(node.nextSibling, length(node.nextSibling) > 0 ? 1 : 0);
++ nextRectangle = range.getBoundingClientRect();
++ if(nextRectangle && nextRectangle.height) {
++ if(!selectionRectangle || verticalOverlap(node, nextRectangle) > verticalOverlap(node, selectionRectangle)) {
++ selectionRectangle = nextRectangle
+ }
+ }
- return existingBookmark
+ }
- function isFirstPositionInParagraph(node, offset) {
- return offset === 0 && odfUtils.isParagraph(node)
++ return selectionRectangle
++ }
++ function handleUpdate() {
++ var selectionRect = getSelectionRect(), zoomLevel = cursor.getOdtDocument().getOdfCanvas().getZoomLevel(), caretRect;
++ if(isShown && cursor.getSelectionType() === ops.OdtCursor.RangeSelection) {
++ span.style.visibility = "visible"
++ }else {
++ span.style.visibility = "hidden"
+ }
- this.updateCache = function(steps, node, offset, isWalkable) {
- var stablePoint, cacheBucket, existingCachePoint, bookmark;
- if(isFirstPositionInParagraph(node, offset)) {
- stablePoint = true;
- if(!isWalkable) {
- steps += 1
- }
- }else {
- if(node.hasChildNodes() && node.childNodes[offset]) {
- node = node.childNodes[offset];
- offset = 0;
- stablePoint = isFirstPositionInParagraph(node, offset);
- if(stablePoint) {
- steps += 1
- }
- }
- }
- if(stablePoint) {
- bookmark = getNodeBookmark(node, steps);
- cacheBucket = getDestinationBucket(bookmark.steps);
- existingCachePoint = stepToDomPoint[cacheBucket];
- if(!existingCachePoint || bookmark.steps > existingCachePoint.steps) {
- stepToDomPoint[cacheBucket] = bookmark
- }
++ if(selectionRect) {
++ span.style.top = "0";
++ caretRect = domUtils.getBoundingClientRect(span);
++ if(selectionRect.height < MIN_CARET_HEIGHT_PX) {
++ selectionRect = {top:selectionRect.top - (MIN_CARET_HEIGHT_PX - selectionRect.height) / 2, height:MIN_CARET_HEIGHT_PX}
+ }
- };
- this.setToClosestStep = function(steps, iterator) {
- var cacheBucket = getBucket(steps), cachePoint;
- while(!cachePoint && cacheBucket !== 0) {
- cachePoint = stepToDomPoint[cacheBucket];
- cacheBucket -= bucketSize
++ span.style.height = domUtils.adaptRangeDifferenceToZoomLevel(selectionRect.height, zoomLevel) + "px";
++ span.style.top = domUtils.adaptRangeDifferenceToZoomLevel(selectionRect.top - caretRect.top, zoomLevel) + "px"
++ }else {
++ span.style.height = DEFAULT_CARET_HEIGHT;
++ span.style.top = DEFAULT_CARET_TOP
++ }
++ }
++ this.handleUpdate = handleUpdate;
++ this.refreshCursorBlinking = function() {
++ if(blinkOnRangeSelect || cursor.getSelectedRange().collapsed) {
++ shouldBlink = true;
++ blink(true)
++ }else {
++ shouldBlink = false;
++ span.style.opacity = "0"
++ }
++ };
++ this.setFocus = function() {
++ shouldBlink = true;
++ avatar.markAsFocussed(true);
++ blink(true)
++ };
++ this.removeFocus = function() {
++ shouldBlink = false;
++ avatar.markAsFocussed(false);
++ span.style.opacity = "1"
++ };
++ this.show = function() {
++ isShown = true;
++ handleUpdate();
++ avatar.markAsFocussed(true)
++ };
++ this.hide = function() {
++ isShown = false;
++ handleUpdate();
++ avatar.markAsFocussed(false)
++ };
++ this.setAvatarImageUrl = function(url) {
++ avatar.setImageUrl(url)
++ };
++ this.setColor = function(newColor) {
++ span.style.borderColor = newColor;
++ avatar.setColor(newColor)
++ };
++ this.getCursor = function() {
++ return cursor
++ };
++ this.getFocusElement = function() {
++ return span
++ };
++ this.toggleHandleVisibility = function() {
++ if(avatar.isVisible()) {
++ avatar.hide()
++ }else {
++ avatar.show()
++ }
++ };
++ this.showHandle = function() {
++ avatar.show()
++ };
++ this.hideHandle = function() {
++ avatar.hide()
++ };
++ this.ensureVisible = function() {
++ var canvasElement = cursor.getOdtDocument().getOdfCanvas().getElement(), canvasContainerElement = canvasElement.parentNode, caretRect, canvasContainerRect, horizontalMargin = canvasContainerElement.offsetWidth - canvasContainerElement.clientWidth + 5, verticalMargin = canvasContainerElement.offsetHeight - canvasContainerElement.clientHeight + 5;
++ caretRect = getCaretClientRectWithMargin(span, {top:verticalMargin, left:horizontalMargin, bottom:verticalMargin, right:horizontalMargin});
++ canvasContainerRect = canvasContainerElement.getBoundingClientRect();
++ if(caretRect.top < canvasContainerRect.top) {
++ canvasContainerElement.scrollTop -= canvasContainerRect.top - caretRect.top
++ }else {
++ if(caretRect.bottom > canvasContainerRect.bottom) {
++ canvasContainerElement.scrollTop += caretRect.bottom - canvasContainerRect.bottom
+ }
- cachePoint = cachePoint || basePoint;
- cachePoint.setIteratorPosition(iterator);
- return cachePoint.steps
- };
- function findBookmarkedAncestor(node, offset) {
- var nodeId, bookmark = null;
- node = node.childNodes[offset] || node;
- while(!bookmark && (node && node !== rootNode)) {
- nodeId = getNodeId(node);
- if(nodeId) {
- bookmark = nodeToBookmark[nodeId];
- if(bookmark && !isValidBookmarkForNode(node, bookmark)) {
- runtime.log("Cloned node detected. Creating new bookmark");
- bookmark = null;
- clearNodeId(node)
- }
- }
- node = node.parentNode
++ }
++ if(caretRect.left < canvasContainerRect.left) {
++ canvasContainerElement.scrollLeft -= canvasContainerRect.left - caretRect.left
++ }else {
++ if(caretRect.right > canvasContainerRect.right) {
++ canvasContainerElement.scrollLeft += caretRect.right - canvasContainerRect.right
+ }
- return bookmark
+ }
- this.setToClosestDomPoint = function(node, offset, iterator) {
- var bookmark;
- if(node === rootNode && offset === 0) {
- bookmark = basePoint
++ handleUpdate()
++ };
++ this.destroy = function(callback) {
++ avatar.destroy(function(err) {
++ if(err) {
++ callback(err)
+ }else {
- if(node === rootNode && offset === rootNode.childNodes.length) {
- bookmark = Object.keys(stepToDomPoint).map(function(cacheBucket) {
- return stepToDomPoint[cacheBucket]
- }).reduce(function(largestBookmark, bookmark) {
- return bookmark.steps > largestBookmark.steps ? bookmark : largestBookmark
- }, basePoint)
- }else {
- bookmark = findBookmarkedAncestor(node, offset);
- if(!bookmark) {
- iterator.setUnfilteredPosition(node, offset);
- while(!bookmark && iterator.previousNode()) {
- bookmark = findBookmarkedAncestor(iterator.container(), iterator.unfilteredDomOffset())
- }
- }
- }
++ cursorNode.removeChild(span);
++ callback()
++ }
++ })
++ };
++ function init() {
++ var dom = cursor.getOdtDocument().getDOM(), htmlns = dom.documentElement.namespaceURI;
++ span = (dom.createElementNS(htmlns, "span"));
++ span.style.top = DEFAULT_CARET_TOP;
++ cursorNode = cursor.getNode();
++ cursorNode.appendChild(span);
++ avatar = new gui.Avatar(cursorNode, avatarInitiallyVisible);
++ handleUpdate()
++ }
++ init()
++};
++gui.EventManager = function EventManager(odtDocument) {
++ var canvasElement = odtDocument.getOdfCanvas().getElement(), window = runtime.getWindow(), bindToDirectHandler = {"beforecut":true, "beforepaste":true}, bindToWindow;
++ function EventDelegate() {
++ var self = this, recentEvents = [];
++ this.handlers = [];
++ this.isSubscribed = false;
++ this.handleEvent = function(e) {
++ if(recentEvents.indexOf(e) === -1) {
++ recentEvents.push(e);
++ self.handlers.forEach(function(handler) {
++ handler(e)
++ });
++ runtime.setTimeout(function() {
++ recentEvents.splice(recentEvents.indexOf(e), 1)
++ }, 0)
+ }
- bookmark = bookmark || basePoint;
- bookmark.setIteratorPosition(iterator);
- return bookmark.steps
- };
- this.updateCacheAtPoint = function(inflectionStep, doUpdate) {
- var affectedBookmarks, updatedBuckets = {};
- affectedBookmarks = Object.keys(nodeToBookmark).map(function(nodeId) {
- return nodeToBookmark[nodeId]
- }).filter(function(bookmark) {
- return bookmark.steps > inflectionStep
- });
- affectedBookmarks.forEach(function(bookmark) {
- var originalCacheBucket = getDestinationBucket(bookmark.steps), newCacheBucket, existingBookmark;
- if(domUtils.containsNode(rootNode, bookmark.node)) {
- doUpdate(bookmark);
- newCacheBucket = getDestinationBucket(bookmark.steps);
- existingBookmark = updatedBuckets[newCacheBucket];
- if(!existingBookmark || bookmark.steps > existingBookmark.steps) {
- updatedBuckets[newCacheBucket] = bookmark
- }
- }else {
- delete nodeToBookmark[getNodeId(bookmark.node)]
- }
- if(stepToDomPoint[originalCacheBucket] === bookmark) {
- delete stepToDomPoint[originalCacheBucket]
- }
- });
- Object.keys(updatedBuckets).forEach(function(cacheBucket) {
- stepToDomPoint[cacheBucket] = updatedBuckets[cacheBucket]
- })
- };
- function init() {
- basePoint = new RootBookmark(0, rootNode)
+ }
- init()
+ }
- ops.StepsTranslator = function StepsTranslator(getRootNode, newIterator, filter, bucketSize) {
- var rootNode = getRootNode(), stepsCache = new StepsCache(rootNode, filter, bucketSize), domUtils = new core.DomUtils, iterator = newIterator(getRootNode()), FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT;
- function verifyRootNode() {
- var currentRootNode = getRootNode();
- if(currentRootNode !== rootNode) {
- runtime.log("Undo detected. Resetting steps cache");
- rootNode = currentRootNode;
- stepsCache = new StepsCache(rootNode, filter, bucketSize);
- iterator = newIterator(rootNode)
++ function WindowScrollState(window) {
++ var x = window.scrollX, y = window.scrollY;
++ this.restore = function() {
++ if(window.scrollX !== x || window.scrollY !== y) {
++ window.scrollTo(x, y)
+ }
+ }
- this.convertStepsToDomPoint = function(steps) {
- var stepsFromRoot, isWalkable;
- if(steps < 0) {
- runtime.log("warn", "Requested steps were negative (" + steps + ")");
- steps = 0
- }
- verifyRootNode();
- stepsFromRoot = stepsCache.setToClosestStep(steps, iterator);
- while(stepsFromRoot < steps && iterator.nextPosition()) {
- isWalkable = filter.acceptPosition(iterator) === FILTER_ACCEPT;
- if(isWalkable) {
- stepsFromRoot += 1
- }
- stepsCache.updateCache(stepsFromRoot, iterator.container(), iterator.unfilteredDomOffset(), isWalkable)
- }
- if(stepsFromRoot !== steps) {
- runtime.log("warn", "Requested " + steps + " steps but only " + stepsFromRoot + " are available")
- }
- return{node:iterator.container(), offset:iterator.unfilteredDomOffset()}
- };
- this.convertDomPointToSteps = function(node, offset, roundUp) {
- var stepsFromRoot, beforeRoot, destinationNode, destinationOffset, rounding = 0, isWalkable;
- verifyRootNode();
- if(!domUtils.containsNode(rootNode, node)) {
- beforeRoot = domUtils.comparePoints(rootNode, 0, node, offset) < 0;
- node = rootNode;
- offset = beforeRoot ? 0 : rootNode.childNodes.length
- }
- iterator.setUnfilteredPosition(node, offset);
- destinationNode = iterator.container();
- destinationOffset = iterator.unfilteredDomOffset();
- if(roundUp && filter.acceptPosition(iterator) !== FILTER_ACCEPT) {
- rounding = 1
++ }
++ function ElementScrollState(element) {
++ var top = element.scrollTop, left = element.scrollLeft;
++ this.restore = function() {
++ if(element.scrollTop !== top || element.scrollLeft !== left) {
++ element.scrollTop = top;
++ element.scrollLeft = left
+ }
- stepsFromRoot = stepsCache.setToClosestDomPoint(node, offset, iterator);
- if(domUtils.comparePoints(iterator.container(), iterator.unfilteredDomOffset(), destinationNode, destinationOffset) < 0) {
- return stepsFromRoot > 0 && !roundUp ? stepsFromRoot - 1 : stepsFromRoot
++ }
++ }
++ function listenEvent(eventTarget, eventType, eventHandler) {
++ var onVariant = "on" + eventType, bound = false;
++ if(eventTarget.attachEvent) {
++ bound = eventTarget.attachEvent(onVariant, eventHandler)
++ }
++ if(!bound && eventTarget.addEventListener) {
++ eventTarget.addEventListener(eventType, eventHandler, false);
++ bound = true
++ }
++ if((!bound || bindToDirectHandler[eventType]) && eventTarget.hasOwnProperty(onVariant)) {
++ eventTarget[onVariant] = eventHandler
++ }
++ }
++ function removeEvent(eventTarget, eventType, eventHandler) {
++ var onVariant = "on" + eventType;
++ if(eventTarget.detachEvent) {
++ eventTarget.detachEvent(onVariant, eventHandler)
++ }
++ if(eventTarget.removeEventListener) {
++ eventTarget.removeEventListener(eventType, eventHandler, false)
++ }
++ if(eventTarget[onVariant] === eventHandler) {
++ eventTarget[onVariant] = null
++ }
++ }
++ this.subscribe = function(eventName, handler) {
++ var delegate = window && bindToWindow[eventName];
++ if(delegate) {
++ delegate.handlers.push(handler);
++ if(!delegate.isSubscribed) {
++ delegate.isSubscribed = true;
++ listenEvent((window), eventName, delegate.handleEvent);
++ listenEvent(canvasElement, eventName, delegate.handleEvent)
+ }
- while(!(iterator.container() === destinationNode && iterator.unfilteredDomOffset() === destinationOffset) && iterator.nextPosition()) {
- isWalkable = filter.acceptPosition(iterator) === FILTER_ACCEPT;
- if(isWalkable) {
- stepsFromRoot += 1
- }
- stepsCache.updateCache(stepsFromRoot, iterator.container(), iterator.unfilteredDomOffset(), isWalkable)
++ }else {
++ listenEvent(canvasElement, eventName, handler)
++ }
++ };
++ this.unsubscribe = function(eventName, handler) {
++ var delegate = window && bindToWindow[eventName], handlerIndex = delegate && delegate.handlers.indexOf(handler);
++ if(delegate) {
++ if(handlerIndex !== -1) {
++ delegate.handlers.splice(handlerIndex, 1)
+ }
- return stepsFromRoot + rounding
- };
- this.prime = function() {
- var stepsFromRoot, isWalkable;
- verifyRootNode();
- stepsFromRoot = stepsCache.setToClosestStep(0, iterator);
- while(iterator.nextPosition()) {
- isWalkable = filter.acceptPosition(iterator) === FILTER_ACCEPT;
- if(isWalkable) {
- stepsFromRoot += 1
- }
- stepsCache.updateCache(stepsFromRoot, iterator.container(), iterator.unfilteredDomOffset(), isWalkable)
++ }else {
++ removeEvent(canvasElement, eventName, handler)
++ }
++ };
++ function hasFocus() {
++ var activeElement = odtDocument.getDOM().activeElement;
++ return activeElement === canvasElement
++ }
++ this.hasFocus = hasFocus;
++ function findScrollableParent(element) {
++ while(element && (!element.scrollTop && !element.scrollLeft)) {
++ element = (element.parentNode)
++ }
++ if(element) {
++ return new ElementScrollState(element)
++ }
++ if(window) {
++ return new WindowScrollState(window)
++ }
++ return null
++ }
++ this.focus = function() {
++ var scrollParent;
++ if(!hasFocus()) {
++ scrollParent = findScrollableParent(canvasElement);
++ canvasElement.focus();
++ if(scrollParent) {
++ scrollParent.restore()
+ }
- };
- this.handleStepsInserted = function(eventArgs) {
- verifyRootNode();
- stepsCache.updateCacheAtPoint(eventArgs.position, function(bucket) {
- bucket.steps += eventArgs.length
- })
- };
- this.handleStepsRemoved = function(eventArgs) {
- verifyRootNode();
- stepsCache.updateCacheAtPoint(eventArgs.position, function(bucket) {
- bucket.steps -= eventArgs.length;
- if(bucket.steps < 0) {
- bucket.steps = 0
- }
- })
+ }
+ };
- return ops.StepsTranslator
++ function init() {
++ bindToWindow = {"mousedown":new EventDelegate, "mouseup":new EventDelegate}
++ }
++ init()
++};
++runtime.loadClass("gui.SelectionMover");
++gui.ShadowCursor = function ShadowCursor(odtDocument) {
++ var selectedRange = (odtDocument.getDOM().createRange()), forwardSelection = true;
++ this.removeFromOdtDocument = function() {
++ };
++ this.getMemberId = function() {
++ return gui.ShadowCursor.ShadowCursorMemberId
++ };
++ this.getSelectedRange = function() {
++ return selectedRange
++ };
++ this.setSelectedRange = function(range, isForwardSelection) {
++ selectedRange = range;
++ forwardSelection = isForwardSelection !== false
++ };
++ this.hasForwardSelection = function() {
++ return forwardSelection
++ };
++ this.getOdtDocument = function() {
++ return odtDocument
++ };
++ this.getSelectionType = function() {
++ return ops.OdtCursor.RangeSelection
++ };
++ function init() {
++ selectedRange.setStart(odtDocument.getRootNode(), 0)
++ }
++ init()
++};
++gui.ShadowCursor.ShadowCursorMemberId = "";
++(function() {
++ return gui.ShadowCursor
++})();
++/*
++
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++gui.UndoManager = function UndoManager() {
++};
++gui.UndoManager.prototype.subscribe = function(signal, callback) {
++};
++gui.UndoManager.prototype.unsubscribe = function(signal, callback) {
++};
++gui.UndoManager.prototype.setOdtDocument = function(newDocument) {
++};
++gui.UndoManager.prototype.saveInitialState = function() {
++};
++gui.UndoManager.prototype.resetInitialState = function() {
++};
++gui.UndoManager.prototype.setPlaybackFunction = function(playback_func) {
++};
++gui.UndoManager.prototype.hasUndoStates = function() {
++};
++gui.UndoManager.prototype.hasRedoStates = function() {
++};
++gui.UndoManager.prototype.moveForward = function(states) {
++};
++gui.UndoManager.prototype.moveBackward = function(states) {
++};
++gui.UndoManager.prototype.onOperationExecuted = function(op) {
++};
++gui.UndoManager.signalUndoStackChanged = "undoStackChanged";
++gui.UndoManager.signalUndoStateCreated = "undoStateCreated";
++gui.UndoManager.signalUndoStateModified = "undoStateModified";
++(function() {
++ return gui.UndoManager
+})();
+/*
+
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.PositionFilter");
- runtime.loadClass("odf.OdfUtils");
- ops.TextPositionFilter = function TextPositionFilter(getRootNode) {
- var odfUtils = new odf.OdfUtils, ELEMENT_NODE = Node.ELEMENT_NODE, TEXT_NODE = Node.TEXT_NODE, FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT, FILTER_REJECT = core.PositionFilter.FilterResult.FILTER_REJECT;
- function checkLeftRight(container, leftNode, rightNode) {
- var r, firstPos, rightOfChar;
- if(leftNode) {
- r = odfUtils.lookLeftForCharacter(leftNode);
- if(r === 1) {
- return FILTER_ACCEPT
- }
- if(r === 2 && (odfUtils.scanRightForAnyCharacter(rightNode) || odfUtils.scanRightForAnyCharacter(odfUtils.nextNode(container)))) {
- return FILTER_ACCEPT
- }
- }
- firstPos = leftNode === null && odfUtils.isParagraph(container);
- rightOfChar = odfUtils.lookRightForCharacter(rightNode);
- if(firstPos) {
- if(rightOfChar) {
- return FILTER_ACCEPT
- }
- return odfUtils.scanRightForAnyCharacter(rightNode) ? FILTER_REJECT : FILTER_ACCEPT
- }
- if(!rightOfChar) {
- return FILTER_REJECT
- }
- leftNode = leftNode || odfUtils.previousNode(container);
- return odfUtils.scanLeftForAnyCharacter(leftNode) ? FILTER_REJECT : FILTER_ACCEPT
++gui.UndoStateRules = function UndoStateRules() {
++ function getOpType(op) {
++ return op.spec().optype
+ }
- this.acceptPosition = function(iterator) {
- var container = iterator.container(), nodeType = container.nodeType, offset, text, leftChar, rightChar, leftNode, rightNode, r;
- if(nodeType !== ELEMENT_NODE && nodeType !== TEXT_NODE) {
- return FILTER_REJECT
++ this.getOpType = getOpType;
++ function getOpPosition(op) {
++ return op.spec().position
++ }
++ function isEditOperation(op) {
++ return op.isEdit
++ }
++ this.isEditOperation = isEditOperation;
++ function canAggregateOperation(optype) {
++ switch(optype) {
++ case "RemoveText":
++ ;
++ case "InsertText":
++ return true;
++ default:
++ return false
+ }
- if(nodeType === TEXT_NODE) {
- if(!odfUtils.isGroupingElement(container.parentNode) || odfUtils.isWithinTrackedChanges(container.parentNode, getRootNode())) {
- return FILTER_REJECT
++ }
++ function isSameDirectionOfTravel(recentEditOps, thisOp) {
++ var existing1 = getOpPosition(recentEditOps[recentEditOps.length - 2]), existing2 = getOpPosition(recentEditOps[recentEditOps.length - 1]), thisPos = getOpPosition(thisOp), direction = existing2 - existing1;
++ return existing2 === thisPos - direction
++ }
++ function isContinuousOperation(recentEditOps, thisOp) {
++ var optype = getOpType(thisOp);
++ if(canAggregateOperation(optype) && optype === getOpType(recentEditOps[0])) {
++ if(recentEditOps.length === 1) {
++ return true
+ }
- offset = iterator.unfilteredDomOffset();
- text = container.data;
- runtime.assert(offset !== text.length, "Unexpected offset.");
- if(offset > 0) {
- leftChar = text[offset - 1];
- if(!odfUtils.isODFWhitespace(leftChar)) {
- return FILTER_ACCEPT
- }
- if(offset > 1) {
- leftChar = text[offset - 2];
- if(!odfUtils.isODFWhitespace(leftChar)) {
- r = FILTER_ACCEPT
- }else {
- if(!odfUtils.isODFWhitespace(text.substr(0, offset))) {
- return FILTER_REJECT
- }
- }
- }else {
- leftNode = odfUtils.previousNode(container);
- if(odfUtils.scanLeftForNonSpace(leftNode)) {
- r = FILTER_ACCEPT
- }
- }
- if(r === FILTER_ACCEPT) {
- return odfUtils.isTrailingWhitespace(container, offset) ? FILTER_REJECT : FILTER_ACCEPT
- }
- rightChar = text[offset];
- if(odfUtils.isODFWhitespace(rightChar)) {
- return FILTER_REJECT
- }
- return odfUtils.scanLeftForAnyCharacter(odfUtils.previousNode(container)) ? FILTER_REJECT : FILTER_ACCEPT
++ if(isSameDirectionOfTravel(recentEditOps, thisOp)) {
++ return true
+ }
- leftNode = iterator.leftNode();
- rightNode = container;
- container = (container.parentNode);
- r = checkLeftRight(container, leftNode, rightNode)
- }else {
- if(!odfUtils.isGroupingElement(container) || odfUtils.isWithinTrackedChanges(container, getRootNode())) {
- r = FILTER_REJECT
- }else {
- leftNode = iterator.leftNode();
- rightNode = iterator.rightNode();
- r = checkLeftRight(container, leftNode, rightNode)
++ }
++ return false
++ }
++ function isPartOfOperationSet(operation, lastOperations) {
++ if(isEditOperation(operation)) {
++ if(lastOperations.length === 0) {
++ return true
+ }
++ return isEditOperation(lastOperations[lastOperations.length - 1]) && isContinuousOperation(lastOperations.filter(isEditOperation), operation)
+ }
- return r
++ return true
+ }
++ this.isPartOfOperationSet = isPartOfOperationSet
+};
+/*
+
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2012 KO GmbH <aditya.bhatt at kogmbh.com>
+
+ @licstart
- This file is part of WebODF.
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
- WebODF is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License (GNU AGPL)
- as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version.
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
- WebODF is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
+
- You should have received a copy of the GNU Affero General Public License
- along with WebODF. If not, see <http://www.gnu.org/licenses/>.
- @licend
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
+
++ This license applies to this entire compilation.
++ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.OperationTransformMatrix = function OperationTransformMatrix() {
- function invertMoveCursorSpecRange(moveCursorSpec) {
- moveCursorSpec.position = moveCursorSpec.position + moveCursorSpec.length;
- moveCursorSpec.length *= -1
- }
- function invertMoveCursorSpecRangeOnNegativeLength(moveCursorSpec) {
- var isBackwards = moveCursorSpec.length < 0;
- if(isBackwards) {
- invertMoveCursorSpecRange(moveCursorSpec)
++ops.EditInfo = function EditInfo(container, odtDocument) {
++ var editInfoNode, editHistory = {};
++ function sortEdits() {
++ var arr = [], memberid;
++ for(memberid in editHistory) {
++ if(editHistory.hasOwnProperty(memberid)) {
++ arr.push({"memberid":memberid, "time":editHistory[memberid].time})
++ }
+ }
- return isBackwards
++ arr.sort(function(a, b) {
++ return a.time - b.time
++ });
++ return arr
+ }
- function getStyleReferencingAttributes(setProperties, styleName) {
- var attributes = [];
- if(setProperties) {
- ["style:parent-style-name", "style:next-style-name"].forEach(function(attributeName) {
- if(setProperties[attributeName] === styleName) {
- attributes.push(attributeName)
- }
- })
++ this.getNode = function() {
++ return editInfoNode
++ };
++ this.getOdtDocument = function() {
++ return odtDocument
++ };
++ this.getEdits = function() {
++ return editHistory
++ };
++ this.getSortedEdits = function() {
++ return sortEdits()
++ };
++ this.addEdit = function(memberid, timestamp) {
++ editHistory[memberid] = {time:timestamp}
++ };
++ this.clearEdits = function() {
++ editHistory = {}
++ };
++ this.destroy = function(callback) {
++ if(container.parentNode) {
++ container.removeChild(editInfoNode)
+ }
- return attributes
++ callback()
++ };
++ function init() {
++ var editInfons = "urn:webodf:names:editinfo", dom = odtDocument.getDOM();
++ editInfoNode = dom.createElementNS(editInfons, "editinfo");
++ container.insertBefore(editInfoNode, container.firstChild)
+ }
- function dropStyleReferencingAttributes(setProperties, deletedStyleName) {
- if(setProperties) {
- ["style:parent-style-name", "style:next-style-name"].forEach(function(attributeName) {
- if(setProperties[attributeName] === deletedStyleName) {
- delete setProperties[attributeName]
- }
- })
- }
++ init()
++};
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++runtime.loadClass("core.DomUtils");
++ops.OpAddAnnotation = function OpAddAnnotation() {
++ var memberid, timestamp, position, length, name, doc;
++ this.init = function(data) {
++ memberid = data.memberid;
++ timestamp = parseInt(data.timestamp, 10);
++ position = parseInt(data.position, 10);
++ length = parseInt(data.length, 10) || 0;
++ name = data.name
++ };
++ this.isEdit = true;
++ function createAnnotationNode(odtDocument, date) {
++ var annotationNode, creatorNode, dateNode, listNode, listItemNode, paragraphNode;
++ annotationNode = doc.createElementNS(odf.Namespaces.officens, "office:annotation");
++ annotationNode.setAttributeNS(odf.Namespaces.officens, "office:name", name);
++ creatorNode = doc.createElementNS(odf.Namespaces.dcns, "dc:creator");
++ creatorNode.setAttributeNS("urn:webodf:names:editinfo", "editinfo:memberid", memberid);
++ creatorNode.textContent = odtDocument.getMember(memberid).getProperties().fullName;
++ dateNode = doc.createElementNS(odf.Namespaces.dcns, "dc:date");
++ dateNode.appendChild(doc.createTextNode(date.toISOString()));
++ listNode = doc.createElementNS(odf.Namespaces.textns, "text:list");
++ listItemNode = doc.createElementNS(odf.Namespaces.textns, "text:list-item");
++ paragraphNode = doc.createElementNS(odf.Namespaces.textns, "text:p");
++ listItemNode.appendChild(paragraphNode);
++ listNode.appendChild(listItemNode);
++ annotationNode.appendChild(creatorNode);
++ annotationNode.appendChild(dateNode);
++ annotationNode.appendChild(listNode);
++ return annotationNode
+ }
- function cloneOpspec(opspec) {
- var result = {};
- Object.keys(opspec).forEach(function(key) {
- if(typeof opspec[key] === "object") {
- result[key] = cloneOpspec(opspec[key])
- }else {
- result[key] = opspec[key]
- }
- });
- return result
++ function createAnnotationEnd() {
++ var annotationEnd;
++ annotationEnd = doc.createElementNS(odf.Namespaces.officens, "office:annotation-end");
++ annotationEnd.setAttributeNS(odf.Namespaces.officens, "office:name", name);
++ return annotationEnd
+ }
- function dropOverruledAndUnneededAttributes(minorSetProperties, minorRemovedProperties, majorSetProperties, majorRemovedProperties) {
- var value, i, name, majorChanged = false, minorChanged = false, overrulingPropertyValue, removedPropertyNames, majorRemovedPropertyNames = majorRemovedProperties && majorRemovedProperties.attributes ? majorRemovedProperties.attributes.split(",") : [];
- if(minorSetProperties && (majorSetProperties || majorRemovedPropertyNames.length > 0)) {
- Object.keys(minorSetProperties).forEach(function(key) {
- value = minorSetProperties[key];
- if(typeof value !== "object") {
- overrulingPropertyValue = majorSetProperties && majorSetProperties[key];
- if(overrulingPropertyValue !== undefined) {
- delete minorSetProperties[key];
- minorChanged = true;
- if(overrulingPropertyValue === value) {
- delete majorSetProperties[key];
- majorChanged = true
- }
- }else {
- if(majorRemovedPropertyNames && majorRemovedPropertyNames.indexOf(key) !== -1) {
- delete minorSetProperties[key];
- minorChanged = true
- }
- }
- }
- })
- }
- if(minorRemovedProperties && (minorRemovedProperties.attributes && (majorSetProperties || majorRemovedPropertyNames.length > 0))) {
- removedPropertyNames = minorRemovedProperties.attributes.split(",");
- for(i = 0;i < removedPropertyNames.length;i += 1) {
- name = removedPropertyNames[i];
- if(majorSetProperties && majorSetProperties[name] !== undefined || majorRemovedPropertyNames && majorRemovedPropertyNames.indexOf(name) !== -1) {
- removedPropertyNames.splice(i, 1);
- i -= 1;
- minorChanged = true
- }
++ function insertNodeAtPosition(odtDocument, node, insertPosition) {
++ var previousNode, parentNode, domPosition = odtDocument.getTextNodeAtStep(insertPosition, memberid);
++ if(domPosition) {
++ previousNode = domPosition.textNode;
++ parentNode = previousNode.parentNode;
++ if(domPosition.offset !== previousNode.length) {
++ previousNode.splitText(domPosition.offset)
+ }
- if(removedPropertyNames.length > 0) {
- minorRemovedProperties.attributes = removedPropertyNames.join(",")
- }else {
- delete minorRemovedProperties.attributes
++ parentNode.insertBefore(node, previousNode.nextSibling);
++ if(previousNode.length === 0) {
++ parentNode.removeChild(previousNode)
+ }
+ }
- return{majorChanged:majorChanged, minorChanged:minorChanged}
+ }
- function hasProperties(properties) {
- var key;
- for(key in properties) {
- if(properties.hasOwnProperty(key)) {
- return true
- }
++ this.execute = function(odtDocument) {
++ var annotation = {}, cursor = odtDocument.getCursor(memberid), selectedRange, paragraphElement, domUtils = new core.DomUtils;
++ doc = odtDocument.getDOM();
++ annotation.node = createAnnotationNode(odtDocument, new Date(timestamp));
++ if(!annotation.node) {
++ return false
+ }
- return false
- }
- function hasRemovedProperties(properties) {
- var key;
- for(key in properties) {
- if(properties.hasOwnProperty(key)) {
- if(key !== "attributes" || properties.attributes.length > 0) {
- return true
- }
++ if(length) {
++ annotation.end = createAnnotationEnd();
++ if(!annotation.end) {
++ return false
+ }
++ insertNodeAtPosition(odtDocument, annotation.end, position + length)
+ }
- return false
- }
- function dropOverruledAndUnneededProperties(minorOpspec, majorOpspec, propertiesName) {
- var minorSP = minorOpspec.setProperties ? minorOpspec.setProperties[propertiesName] : null, minorRP = minorOpspec.removedProperties ? minorOpspec.removedProperties[propertiesName] : null, majorSP = majorOpspec.setProperties ? majorOpspec.setProperties[propertiesName] : null, majorRP = majorOpspec.removedProperties ? majorOpspec.removedProperties[propertiesName] : null, result;
- result = dropOverruledAndUnneededAttributes(minorSP, minorRP, majorSP, majorRP);
- if(minorSP && !hasProperties(minorSP)) {
- delete minorOpspec.setProperties[propertiesName]
- }
- if(minorRP && !hasRemovedProperties(minorRP)) {
- delete minorOpspec.removedProperties[propertiesName]
- }
- if(majorSP && !hasProperties(majorSP)) {
- delete majorOpspec.setProperties[propertiesName]
- }
- if(majorRP && !hasRemovedProperties(majorRP)) {
- delete majorOpspec.removedProperties[propertiesName]
- }
- return result
- }
- function transformAddStyleRemoveStyle(addStyleSpec, removeStyleSpec) {
- var setAttributes, helperOpspec, addStyleSpecResult = [addStyleSpec], removeStyleSpecResult = [removeStyleSpec];
- if(addStyleSpec.styleFamily === removeStyleSpec.styleFamily) {
- setAttributes = getStyleReferencingAttributes(addStyleSpec.setProperties, removeStyleSpec.styleName);
- if(setAttributes.length > 0) {
- helperOpspec = {optype:"UpdateParagraphStyle", memberid:removeStyleSpec.memberid, timestamp:removeStyleSpec.timestamp, styleName:addStyleSpec.styleName, removedProperties:{attributes:setAttributes.join(",")}};
- removeStyleSpecResult.unshift(helperOpspec)
- }
- dropStyleReferencingAttributes(addStyleSpec.setProperties, removeStyleSpec.styleName)
++ insertNodeAtPosition(odtDocument, annotation.node, position);
++ odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position:position, length:length});
++ if(cursor) {
++ selectedRange = doc.createRange();
++ paragraphElement = domUtils.getElementsByTagNameNS(annotation.node, odf.Namespaces.textns, "p")[0];
++ selectedRange.selectNodeContents(paragraphElement);
++ cursor.setSelectedRange(selectedRange);
++ odtDocument.emit(ops.OdtDocument.signalCursorMoved, cursor)
+ }
- return{opSpecsA:addStyleSpecResult, opSpecsB:removeStyleSpecResult}
++ odtDocument.getOdfCanvas().addAnnotation(annotation);
++ odtDocument.fixCursorPositions();
++ return true
++ };
++ this.spec = function() {
++ return{optype:"AddAnnotation", memberid:memberid, timestamp:timestamp, position:position, length:length, name:name}
+ }
- function transformApplyDirectStylingApplyDirectStyling(applyDirectStylingSpecA, applyDirectStylingSpecB, hasAPriority) {
- var majorSpec, minorSpec, majorSpecResult, minorSpecResult, majorSpecEnd, minorSpecEnd, dropResult, originalMajorSpec, originalMinorSpec, helperOpspecBefore, helperOpspecAfter, applyDirectStylingSpecAResult = [applyDirectStylingSpecA], applyDirectStylingSpecBResult = [applyDirectStylingSpecB];
- if(!(applyDirectStylingSpecA.position + applyDirectStylingSpecA.length <= applyDirectStylingSpecB.position || applyDirectStylingSpecA.position >= applyDirectStylingSpecB.position + applyDirectStylingSpecB.length)) {
- majorSpec = hasAPriority ? applyDirectStylingSpecA : applyDirectStylingSpecB;
- minorSpec = hasAPriority ? applyDirectStylingSpecB : applyDirectStylingSpecA;
- if(applyDirectStylingSpecA.position !== applyDirectStylingSpecB.position || applyDirectStylingSpecA.length !== applyDirectStylingSpecB.length) {
- originalMajorSpec = cloneOpspec(majorSpec);
- originalMinorSpec = cloneOpspec(minorSpec)
- }
- dropResult = dropOverruledAndUnneededProperties(minorSpec, majorSpec, "style:text-properties");
- if(dropResult.majorChanged || dropResult.minorChanged) {
- majorSpecResult = [];
- minorSpecResult = [];
- majorSpecEnd = majorSpec.position + majorSpec.length;
- minorSpecEnd = minorSpec.position + minorSpec.length;
- if(minorSpec.position < majorSpec.position) {
- if(dropResult.minorChanged) {
- helperOpspecBefore = cloneOpspec((originalMinorSpec));
- helperOpspecBefore.length = majorSpec.position - minorSpec.position;
- minorSpecResult.push(helperOpspecBefore);
- minorSpec.position = majorSpec.position;
- minorSpec.length = minorSpecEnd - minorSpec.position
- }
- }else {
- if(majorSpec.position < minorSpec.position) {
- if(dropResult.majorChanged) {
- helperOpspecBefore = cloneOpspec((originalMajorSpec));
- helperOpspecBefore.length = minorSpec.position - majorSpec.position;
- majorSpecResult.push(helperOpspecBefore);
- majorSpec.position = minorSpec.position;
- majorSpec.length = majorSpecEnd - majorSpec.position
- }
- }
- }
- if(minorSpecEnd > majorSpecEnd) {
- if(dropResult.minorChanged) {
- helperOpspecAfter = originalMinorSpec;
- helperOpspecAfter.position = majorSpecEnd;
- helperOpspecAfter.length = minorSpecEnd - majorSpecEnd;
- minorSpecResult.push(helperOpspecAfter);
- minorSpec.length = majorSpecEnd - minorSpec.position
- }
- }else {
- if(majorSpecEnd > minorSpecEnd) {
- if(dropResult.majorChanged) {
- helperOpspecAfter = originalMajorSpec;
- helperOpspecAfter.position = minorSpecEnd;
- helperOpspecAfter.length = majorSpecEnd - minorSpecEnd;
- majorSpecResult.push(helperOpspecAfter);
- majorSpec.length = minorSpecEnd - majorSpec.position
- }
- }
- }
- if(majorSpec.setProperties && hasProperties(majorSpec.setProperties)) {
- majorSpecResult.push(majorSpec)
- }
- if(minorSpec.setProperties && hasProperties(minorSpec.setProperties)) {
- minorSpecResult.push(minorSpec)
- }
- if(hasAPriority) {
- applyDirectStylingSpecAResult = majorSpecResult;
- applyDirectStylingSpecBResult = minorSpecResult
- }else {
- applyDirectStylingSpecAResult = minorSpecResult;
- applyDirectStylingSpecBResult = majorSpecResult
- }
- }
++};
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++ops.OpAddCursor = function OpAddCursor() {
++ var memberid, timestamp;
++ this.init = function(data) {
++ memberid = data.memberid;
++ timestamp = data.timestamp
++ };
++ this.isEdit = false;
++ this.execute = function(odtDocument) {
++ var cursor = odtDocument.getCursor(memberid);
++ if(cursor) {
++ return false
+ }
- return{opSpecsA:applyDirectStylingSpecAResult, opSpecsB:applyDirectStylingSpecBResult}
++ cursor = new ops.OdtCursor(memberid, odtDocument);
++ odtDocument.addCursor(cursor);
++ odtDocument.emit(ops.OdtDocument.signalCursorAdded, cursor);
++ return true
++ };
++ this.spec = function() {
++ return{optype:"AddCursor", memberid:memberid, timestamp:timestamp}
+ }
- function transformApplyDirectStylingInsertText(applyDirectStylingSpec, insertTextSpec) {
- if(insertTextSpec.position <= applyDirectStylingSpec.position) {
- applyDirectStylingSpec.position += insertTextSpec.text.length
- }else {
- if(insertTextSpec.position <= applyDirectStylingSpec.position + applyDirectStylingSpec.length) {
- applyDirectStylingSpec.length += insertTextSpec.text.length
- }
++};
++/*
++
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ This file is part of WebODF.
++
++ WebODF is free software: you can redistribute it and/or modify it
++ under the terms of the GNU Affero General Public License (GNU AGPL)
++ as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version.
++
++ WebODF is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU Affero General Public License for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
++ @licend
++
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++runtime.loadClass("ops.Member");
++ops.OpAddMember = function OpAddMember() {
++ var memberid, timestamp, setProperties;
++ this.init = function(data) {
++ memberid = data.memberid;
++ timestamp = parseInt(data.timestamp, 10);
++ setProperties = data.setProperties
++ };
++ this.isEdit = false;
++ this.execute = function(odtDocument) {
++ if(odtDocument.getMember(memberid)) {
++ return false
+ }
- return{opSpecsA:[applyDirectStylingSpec], opSpecsB:[insertTextSpec]}
++ var member = new ops.Member(memberid, setProperties);
++ odtDocument.addMember(member);
++ odtDocument.emit(ops.OdtDocument.signalMemberAdded, member);
++ return true
++ };
++ this.spec = function() {
++ return{optype:"AddMember", memberid:memberid, timestamp:timestamp, setProperties:setProperties}
+ }
- function transformApplyDirectStylingRemoveText(applyDirectStylingSpec, removeTextSpec) {
- var applyDirectStylingSpecEnd = applyDirectStylingSpec.position + applyDirectStylingSpec.length, removeTextSpecEnd = removeTextSpec.position + removeTextSpec.length, applyDirectStylingSpecResult = [applyDirectStylingSpec], removeTextSpecResult = [removeTextSpec];
- if(removeTextSpecEnd <= applyDirectStylingSpec.position) {
- applyDirectStylingSpec.position -= removeTextSpec.length
- }else {
- if(removeTextSpec.position < applyDirectStylingSpecEnd) {
- if(applyDirectStylingSpec.position < removeTextSpec.position) {
- if(removeTextSpecEnd < applyDirectStylingSpecEnd) {
- applyDirectStylingSpec.length -= removeTextSpec.length
- }else {
- applyDirectStylingSpec.length = removeTextSpec.position - applyDirectStylingSpec.position
- }
- }else {
- applyDirectStylingSpec.position = removeTextSpec.position;
- if(removeTextSpecEnd < applyDirectStylingSpecEnd) {
- applyDirectStylingSpec.length = applyDirectStylingSpecEnd - removeTextSpecEnd
- }else {
- applyDirectStylingSpecResult = []
- }
- }
- }
++};
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++runtime.loadClass("odf.Namespaces");
++ops.OpAddStyle = function OpAddStyle() {
++ var memberid, timestamp, styleName, styleFamily, isAutomaticStyle, setProperties, stylens = odf.Namespaces.stylens;
++ this.init = function(data) {
++ memberid = data.memberid;
++ timestamp = data.timestamp;
++ styleName = data.styleName;
++ styleFamily = data.styleFamily;
++ isAutomaticStyle = data.isAutomaticStyle === "true" || data.isAutomaticStyle === true;
++ setProperties = data.setProperties
++ };
++ this.isEdit = true;
++ this.execute = function(odtDocument) {
++ var odfContainer = odtDocument.getOdfCanvas().odfContainer(), formatting = odtDocument.getFormatting(), dom = odtDocument.getDOM(), styleNode = dom.createElementNS(stylens, "style:style");
++ if(!styleNode) {
++ return false
+ }
- return{opSpecsA:applyDirectStylingSpecResult, opSpecsB:removeTextSpecResult}
- }
- function transformApplyDirectStylingSplitParagraph(applyDirectStylingSpec, splitParagraphSpec) {
- if(splitParagraphSpec.position < applyDirectStylingSpec.position) {
- applyDirectStylingSpec.position += 1
++ if(setProperties) {
++ formatting.updateStyle(styleNode, setProperties)
++ }
++ styleNode.setAttributeNS(stylens, "style:family", styleFamily);
++ styleNode.setAttributeNS(stylens, "style:name", styleName);
++ if(isAutomaticStyle) {
++ odfContainer.rootElement.automaticStyles.appendChild(styleNode)
+ }else {
- if(splitParagraphSpec.position < applyDirectStylingSpec.position + applyDirectStylingSpec.length) {
- applyDirectStylingSpec.length += 1
- }
++ odfContainer.rootElement.styles.appendChild(styleNode)
+ }
- return{opSpecsA:[applyDirectStylingSpec], opSpecsB:[splitParagraphSpec]}
++ odtDocument.getOdfCanvas().refreshCSS();
++ if(!isAutomaticStyle) {
++ odtDocument.emit(ops.OdtDocument.signalCommonStyleCreated, {name:styleName, family:styleFamily})
++ }
++ return true
++ };
++ this.spec = function() {
++ return{optype:"AddStyle", memberid:memberid, timestamp:timestamp, styleName:styleName, styleFamily:styleFamily, isAutomaticStyle:isAutomaticStyle, setProperties:setProperties}
++ }
++};
++ops.OpAddStyle.Spec;
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++runtime.loadClass("gui.StyleHelper");
++runtime.loadClass("odf.OdfUtils");
++ops.OpApplyDirectStyling = function OpApplyDirectStyling() {
++ var memberid, timestamp, position, length, setProperties, odfUtils = new odf.OdfUtils;
++ this.init = function(data) {
++ memberid = data.memberid;
++ timestamp = data.timestamp;
++ position = parseInt(data.position, 10);
++ length = parseInt(data.length, 10);
++ setProperties = data.setProperties
++ };
++ this.isEdit = true;
++ function getRange(odtDocument) {
++ var point1 = length >= 0 ? position : position + length, point2 = length >= 0 ? position + length : position, p1 = odtDocument.getIteratorAtPosition(point1), p2 = length ? odtDocument.getIteratorAtPosition(point2) : p1, range = odtDocument.getDOM().createRange();
++ range.setStart(p1.container(), p1.unfilteredDomOffset());
++ range.setEnd(p2.container(), p2.unfilteredDomOffset());
++ return range
++ }
++ this.execute = function(odtDocument) {
++ var range = getRange(odtDocument), impactedParagraphs = odfUtils.getImpactedParagraphs(range), styleHelper = new gui.StyleHelper(odtDocument.getFormatting());
++ styleHelper.applyStyle(memberid, range, setProperties);
++ range.detach();
++ odtDocument.getOdfCanvas().refreshCSS();
++ odtDocument.fixCursorPositions();
++ impactedParagraphs.forEach(function(n) {
++ odtDocument.emit(ops.OdtDocument.signalParagraphChanged, {paragraphElement:n, memberId:memberid, timeStamp:timestamp})
++ });
++ odtDocument.getOdfCanvas().rerenderAnnotations();
++ return true
++ };
++ this.spec = function() {
++ return{optype:"ApplyDirectStyling", memberid:memberid, timestamp:timestamp, position:position, length:length, setProperties:setProperties}
+ }
- function transformInsertTextInsertText(insertTextSpecA, insertTextSpecB, hasAPriority) {
- if(insertTextSpecA.position < insertTextSpecB.position) {
- insertTextSpecB.position += insertTextSpecA.text.length
- }else {
- if(insertTextSpecA.position > insertTextSpecB.position) {
- insertTextSpecA.position += insertTextSpecB.text.length
- }else {
- if(hasAPriority) {
- insertTextSpecB.position += insertTextSpecA.text.length
- }else {
- insertTextSpecA.position += insertTextSpecB.text.length
- }
- return null
- }
- }
- return{opSpecsA:[insertTextSpecA], opSpecsB:[insertTextSpecB]}
++};
++ops.OpApplyDirectStyling.Spec;
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++ops.OpInsertImage = function OpInsertImage() {
++ var memberid, timestamp, position, filename, frameWidth, frameHeight, frameStyleName, frameName, drawns = odf.Namespaces.drawns, svgns = odf.Namespaces.svgns, textns = odf.Namespaces.textns, xlinkns = odf.Namespaces.xlinkns;
++ this.init = function(data) {
++ memberid = data.memberid;
++ timestamp = data.timestamp;
++ position = data.position;
++ filename = data.filename;
++ frameWidth = data.frameWidth;
++ frameHeight = data.frameHeight;
++ frameStyleName = data.frameStyleName;
++ frameName = data.frameName
++ };
++ this.isEdit = true;
++ function createFrameElement(document) {
++ var imageNode = document.createElementNS(drawns, "draw:image"), frameNode = document.createElementNS(drawns, "draw:frame");
++ imageNode.setAttributeNS(xlinkns, "xlink:href", filename);
++ imageNode.setAttributeNS(xlinkns, "xlink:type", "simple");
++ imageNode.setAttributeNS(xlinkns, "xlink:show", "embed");
++ imageNode.setAttributeNS(xlinkns, "xlink:actuate", "onLoad");
++ frameNode.setAttributeNS(drawns, "draw:style-name", frameStyleName);
++ frameNode.setAttributeNS(drawns, "draw:name", frameName);
++ frameNode.setAttributeNS(textns, "text:anchor-type", "as-char");
++ frameNode.setAttributeNS(svgns, "svg:width", frameWidth);
++ frameNode.setAttributeNS(svgns, "svg:height", frameHeight);
++ frameNode.appendChild(imageNode);
++ return frameNode
+ }
- function transformInsertTextMoveCursor(insertTextSpec, moveCursorSpec) {
- var isMoveCursorSpecRangeInverted = invertMoveCursorSpecRangeOnNegativeLength(moveCursorSpec);
- if(insertTextSpec.position < moveCursorSpec.position) {
- moveCursorSpec.position += insertTextSpec.text.length
- }else {
- if(insertTextSpec.position < moveCursorSpec.position + moveCursorSpec.length) {
- moveCursorSpec.length += insertTextSpec.text.length
- }
- }
- if(isMoveCursorSpecRangeInverted) {
- invertMoveCursorSpecRange(moveCursorSpec)
++ this.execute = function(odtDocument) {
++ var odfCanvas = odtDocument.getOdfCanvas(), domPosition = odtDocument.getTextNodeAtStep(position, memberid), textNode, refNode, paragraphElement, frameElement;
++ if(!domPosition) {
++ return false
+ }
- return{opSpecsA:[insertTextSpec], opSpecsB:[moveCursorSpec]}
- }
- function transformInsertTextRemoveText(insertTextSpec, removeTextSpec) {
- var helperOpspec, removeTextSpecEnd = removeTextSpec.position + removeTextSpec.length, insertTextSpecResult = [insertTextSpec], removeTextSpecResult = [removeTextSpec];
- if(removeTextSpecEnd <= insertTextSpec.position) {
- insertTextSpec.position -= removeTextSpec.length
- }else {
- if(insertTextSpec.position <= removeTextSpec.position) {
- removeTextSpec.position += insertTextSpec.text.length
- }else {
- removeTextSpec.length = insertTextSpec.position - removeTextSpec.position;
- helperOpspec = {optype:"RemoveText", memberid:removeTextSpec.memberid, timestamp:removeTextSpec.timestamp, position:insertTextSpec.position + insertTextSpec.text.length, length:removeTextSpecEnd - insertTextSpec.position};
- removeTextSpecResult.unshift(helperOpspec);
- insertTextSpec.position = removeTextSpec.position
- }
++ textNode = domPosition.textNode;
++ paragraphElement = odtDocument.getParagraphElement(textNode);
++ refNode = domPosition.offset !== textNode.length ? textNode.splitText(domPosition.offset) : textNode.nextSibling;
++ frameElement = createFrameElement(odtDocument.getDOM());
++ textNode.parentNode.insertBefore(frameElement, refNode);
++ odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position:position, length:1});
++ if(textNode.length === 0) {
++ textNode.parentNode.removeChild(textNode)
+ }
- return{opSpecsA:insertTextSpecResult, opSpecsB:removeTextSpecResult}
++ odfCanvas.addCssForFrameWithImage(frameElement);
++ odfCanvas.refreshCSS();
++ odtDocument.emit(ops.OdtDocument.signalParagraphChanged, {paragraphElement:paragraphElement, memberId:memberid, timeStamp:timestamp});
++ odfCanvas.rerenderAnnotations();
++ return true
++ };
++ this.spec = function() {
++ return{optype:"InsertImage", memberid:memberid, timestamp:timestamp, filename:filename, position:position, frameWidth:frameWidth, frameHeight:frameHeight, frameStyleName:frameStyleName, frameName:frameName}
+ }
- function transformInsertTextSplitParagraph(insertTextSpec, splitParagraphSpec, hasAPriority) {
- if(insertTextSpec.position < splitParagraphSpec.position) {
- splitParagraphSpec.position += insertTextSpec.text.length
++};
++/*
++
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++ops.OpInsertTable = function OpInsertTable() {
++ var memberid, timestamp, initialRows, initialColumns, position, tableName, tableStyleName, tableColumnStyleName, tableCellStyleMatrix, tablens = "urn:oasis:names:tc:opendocument:xmlns:table:1.0", textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0";
++ this.init = function(data) {
++ memberid = data.memberid;
++ timestamp = data.timestamp;
++ position = data.position;
++ initialRows = data.initialRows;
++ initialColumns = data.initialColumns;
++ tableName = data.tableName;
++ tableStyleName = data.tableStyleName;
++ tableColumnStyleName = data.tableColumnStyleName;
++ tableCellStyleMatrix = data.tableCellStyleMatrix
++ };
++ this.isEdit = true;
++ function getCellStyleName(row, column) {
++ var rowStyles;
++ if(tableCellStyleMatrix.length === 1) {
++ rowStyles = tableCellStyleMatrix[0]
+ }else {
- if(insertTextSpec.position > splitParagraphSpec.position) {
- insertTextSpec.position += 1
- }else {
- if(hasAPriority) {
- splitParagraphSpec.position += insertTextSpec.text.length
- }else {
- insertTextSpec.position += 1
- }
- return null
- }
- }
- return{opSpecsA:[insertTextSpec], opSpecsB:[splitParagraphSpec]}
- }
- function transformUpdateParagraphStyleUpdateParagraphStyle(updateParagraphStyleSpecA, updateParagraphStyleSpecB, hasAPriority) {
- var majorSpec, minorSpec, updateParagraphStyleSpecAResult = [updateParagraphStyleSpecA], updateParagraphStyleSpecBResult = [updateParagraphStyleSpecB];
- if(updateParagraphStyleSpecA.styleName === updateParagraphStyleSpecB.styleName) {
- majorSpec = hasAPriority ? updateParagraphStyleSpecA : updateParagraphStyleSpecB;
- minorSpec = hasAPriority ? updateParagraphStyleSpecB : updateParagraphStyleSpecA;
- dropOverruledAndUnneededProperties(minorSpec, majorSpec, "style:paragraph-properties");
- dropOverruledAndUnneededProperties(minorSpec, majorSpec, "style:text-properties");
- dropOverruledAndUnneededAttributes(minorSpec.setProperties || null, minorSpec.removedProperties || null, majorSpec.setProperties || null, majorSpec.removedProperties || null);
- if(!(majorSpec.setProperties && hasProperties(majorSpec.setProperties)) && !(majorSpec.removedProperties && hasRemovedProperties(majorSpec.removedProperties))) {
- if(hasAPriority) {
- updateParagraphStyleSpecAResult = []
- }else {
- updateParagraphStyleSpecBResult = []
- }
- }
- if(!(minorSpec.setProperties && hasProperties(minorSpec.setProperties)) && !(minorSpec.removedProperties && hasRemovedProperties(minorSpec.removedProperties))) {
- if(hasAPriority) {
- updateParagraphStyleSpecBResult = []
- }else {
- updateParagraphStyleSpecAResult = []
++ if(tableCellStyleMatrix.length === 3) {
++ switch(row) {
++ case 0:
++ rowStyles = tableCellStyleMatrix[0];
++ break;
++ case initialRows - 1:
++ rowStyles = tableCellStyleMatrix[2];
++ break;
++ default:
++ rowStyles = tableCellStyleMatrix[1];
++ break
+ }
- }
- }
- return{opSpecsA:updateParagraphStyleSpecAResult, opSpecsB:updateParagraphStyleSpecBResult}
- }
- function transformUpdateMetadataUpdateMetadata(updateMetadataSpecA, updateMetadataSpecB, hasAPriority) {
- var majorSpec, minorSpec, updateMetadataSpecAResult = [updateMetadataSpecA], updateMetadataSpecBResult = [updateMetadataSpecB];
- majorSpec = hasAPriority ? updateMetadataSpecA : updateMetadataSpecB;
- minorSpec = hasAPriority ? updateMetadataSpecB : updateMetadataSpecA;
- dropOverruledAndUnneededAttributes(minorSpec.setProperties || null, minorSpec.removedProperties || null, majorSpec.setProperties || null, majorSpec.removedProperties || null);
- if(!(majorSpec.setProperties && hasProperties(majorSpec.setProperties)) && !(majorSpec.removedProperties && hasRemovedProperties(majorSpec.removedProperties))) {
- if(hasAPriority) {
- updateMetadataSpecAResult = []
- }else {
- updateMetadataSpecBResult = []
- }
- }
- if(!(minorSpec.setProperties && hasProperties(minorSpec.setProperties)) && !(minorSpec.removedProperties && hasRemovedProperties(minorSpec.removedProperties))) {
- if(hasAPriority) {
- updateMetadataSpecBResult = []
+ }else {
- updateMetadataSpecAResult = []
++ rowStyles = tableCellStyleMatrix[row]
+ }
+ }
- return{opSpecsA:updateMetadataSpecAResult, opSpecsB:updateMetadataSpecBResult}
++ if(rowStyles.length === 1) {
++ return rowStyles[0]
++ }
++ if(rowStyles.length === 3) {
++ switch(column) {
++ case 0:
++ return rowStyles[0];
++ case initialColumns - 1:
++ return rowStyles[2];
++ default:
++ return rowStyles[1]
++ }
++ }
++ return rowStyles[column]
+ }
- function transformSplitParagraphSplitParagraph(splitParagraphSpecA, splitParagraphSpecB, hasAPriority) {
- if(splitParagraphSpecA.position < splitParagraphSpecB.position) {
- splitParagraphSpecB.position += 1
- }else {
- if(splitParagraphSpecA.position > splitParagraphSpecB.position) {
- splitParagraphSpecA.position += 1
- }else {
- if(splitParagraphSpecA.position === splitParagraphSpecB.position) {
- if(hasAPriority) {
- splitParagraphSpecB.position += 1
- }else {
- splitParagraphSpecA.position += 1
- }
- return null
++ function createTableNode(document) {
++ var tableNode = document.createElementNS(tablens, "table:table"), columns = document.createElementNS(tablens, "table:table-column"), row, cell, paragraph, rowCounter, columnCounter, cellStyleName;
++ if(tableStyleName) {
++ tableNode.setAttributeNS(tablens, "table:style-name", tableStyleName)
++ }
++ if(tableName) {
++ tableNode.setAttributeNS(tablens, "table:name", tableName)
++ }
++ columns.setAttributeNS(tablens, "table:number-columns-repeated", initialColumns);
++ if(tableColumnStyleName) {
++ columns.setAttributeNS(tablens, "table:style-name", tableColumnStyleName)
++ }
++ tableNode.appendChild(columns);
++ for(rowCounter = 0;rowCounter < initialRows;rowCounter += 1) {
++ row = document.createElementNS(tablens, "table:table-row");
++ for(columnCounter = 0;columnCounter < initialColumns;columnCounter += 1) {
++ cell = document.createElementNS(tablens, "table:table-cell");
++ cellStyleName = getCellStyleName(rowCounter, columnCounter);
++ if(cellStyleName) {
++ cell.setAttributeNS(tablens, "table:style-name", cellStyleName)
+ }
++ paragraph = document.createElementNS(textns, "text:p");
++ cell.appendChild(paragraph);
++ row.appendChild(cell)
+ }
++ tableNode.appendChild(row)
+ }
- return{opSpecsA:[splitParagraphSpecA], opSpecsB:[splitParagraphSpecB]}
++ return tableNode
+ }
- function transformMoveCursorRemoveCursor(moveCursorSpec, removeCursorSpec) {
- var isSameCursorRemoved = moveCursorSpec.memberid === removeCursorSpec.memberid;
- return{opSpecsA:isSameCursorRemoved ? [] : [moveCursorSpec], opSpecsB:[removeCursorSpec]}
++ this.execute = function(odtDocument) {
++ var domPosition = odtDocument.getTextNodeAtStep(position), rootNode = odtDocument.getRootNode(), previousSibling, tableNode;
++ if(domPosition) {
++ tableNode = createTableNode(odtDocument.getDOM());
++ previousSibling = odtDocument.getParagraphElement(domPosition.textNode);
++ rootNode.insertBefore(tableNode, previousSibling.nextSibling);
++ odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position:position, length:initialColumns * initialRows + 1});
++ odtDocument.getOdfCanvas().refreshSize();
++ odtDocument.emit(ops.OdtDocument.signalTableAdded, {tableElement:tableNode, memberId:memberid, timeStamp:timestamp});
++ odtDocument.getOdfCanvas().rerenderAnnotations();
++ return true
++ }
++ return false
++ };
++ this.spec = function() {
++ return{optype:"InsertTable", memberid:memberid, timestamp:timestamp, position:position, initialRows:initialRows, initialColumns:initialColumns, tableName:tableName, tableStyleName:tableStyleName, tableColumnStyleName:tableColumnStyleName, tableCellStyleMatrix:tableCellStyleMatrix}
+ }
- function transformMoveCursorRemoveText(moveCursorSpec, removeTextSpec) {
- var isMoveCursorSpecRangeInverted = invertMoveCursorSpecRangeOnNegativeLength(moveCursorSpec), moveCursorSpecEnd = moveCursorSpec.position + moveCursorSpec.length, removeTextSpecEnd = removeTextSpec.position + removeTextSpec.length;
- if(removeTextSpecEnd <= moveCursorSpec.position) {
- moveCursorSpec.position -= removeTextSpec.length
- }else {
- if(removeTextSpec.position < moveCursorSpecEnd) {
- if(moveCursorSpec.position < removeTextSpec.position) {
- if(removeTextSpecEnd < moveCursorSpecEnd) {
- moveCursorSpec.length -= removeTextSpec.length
- }else {
- moveCursorSpec.length = removeTextSpec.position - moveCursorSpec.position
- }
- }else {
- moveCursorSpec.position = removeTextSpec.position;
- if(removeTextSpecEnd < moveCursorSpecEnd) {
- moveCursorSpec.length = moveCursorSpecEnd - removeTextSpecEnd
++};
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++ops.OpInsertText = function OpInsertText() {
++ var space = " ", tab = "\t", memberid, timestamp, position, text;
++ this.init = function(data) {
++ memberid = data.memberid;
++ timestamp = data.timestamp;
++ position = data.position;
++ text = data.text
++ };
++ this.isEdit = true;
++ function triggerLayoutInWebkit(textNode) {
++ var parent = textNode.parentNode, next = textNode.nextSibling;
++ parent.removeChild(textNode);
++ parent.insertBefore(textNode, next)
++ }
++ function requiresSpaceElement(text, index) {
++ return text[index] === space && (index === 0 || (index === text.length - 1 || text[index - 1] === space))
++ }
++ this.execute = function(odtDocument) {
++ var domPosition, previousNode, parentElement, nextNode = null, ownerDocument = odtDocument.getDOM(), paragraphElement, textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0", toInsertIndex = 0, spaceTag, spaceElement, i;
++ function insertTextNode(toInsertText) {
++ parentElement.insertBefore(ownerDocument.createTextNode(toInsertText), nextNode)
++ }
++ odtDocument.upgradeWhitespacesAtPosition(position);
++ domPosition = odtDocument.getTextNodeAtStep(position, memberid);
++ if(domPosition) {
++ previousNode = domPosition.textNode;
++ nextNode = previousNode.nextSibling;
++ parentElement = previousNode.parentNode;
++ paragraphElement = odtDocument.getParagraphElement(previousNode);
++ for(i = 0;i < text.length;i += 1) {
++ if(requiresSpaceElement(text, i) || text[i] === tab) {
++ if(toInsertIndex === 0) {
++ if(domPosition.offset !== previousNode.length) {
++ nextNode = previousNode.splitText(domPosition.offset)
++ }
++ if(0 < i) {
++ previousNode.appendData(text.substring(0, i))
++ }
+ }else {
- moveCursorSpec.length = 0
++ if(toInsertIndex < i) {
++ insertTextNode(text.substring(toInsertIndex, i))
++ }
+ }
++ toInsertIndex = i + 1;
++ spaceTag = text[i] === space ? "text:s" : "text:tab";
++ spaceElement = ownerDocument.createElementNS(textns, spaceTag);
++ spaceElement.appendChild(ownerDocument.createTextNode(text[i]));
++ parentElement.insertBefore(spaceElement, nextNode)
+ }
+ }
- }
- if(isMoveCursorSpecRangeInverted) {
- invertMoveCursorSpecRange(moveCursorSpec)
- }
- return{opSpecsA:[moveCursorSpec], opSpecsB:[removeTextSpec]}
- }
- function transformMoveCursorSplitParagraph(moveCursorSpec, splitParagraphSpec) {
- var isMoveCursorSpecRangeInverted = invertMoveCursorSpecRangeOnNegativeLength(moveCursorSpec);
- if(splitParagraphSpec.position < moveCursorSpec.position) {
- moveCursorSpec.position += 1
- }else {
- if(splitParagraphSpec.position < moveCursorSpec.position + moveCursorSpec.length) {
- moveCursorSpec.length += 1
++ if(toInsertIndex === 0) {
++ previousNode.insertData(domPosition.offset, text)
++ }else {
++ if(toInsertIndex < text.length) {
++ insertTextNode(text.substring(toInsertIndex))
++ }
++ }
++ triggerLayoutInWebkit(previousNode);
++ if(previousNode.length === 0) {
++ previousNode.parentNode.removeChild(previousNode)
+ }
++ odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position:position, length:text.length});
++ if(position > 0) {
++ if(position > 1) {
++ odtDocument.downgradeWhitespacesAtPosition(position - 2)
++ }
++ odtDocument.downgradeWhitespacesAtPosition(position - 1)
++ }
++ odtDocument.downgradeWhitespacesAtPosition(position);
++ odtDocument.downgradeWhitespacesAtPosition(position + text.length - 1);
++ odtDocument.downgradeWhitespacesAtPosition(position + text.length);
++ odtDocument.getOdfCanvas().refreshSize();
++ odtDocument.emit(ops.OdtDocument.signalParagraphChanged, {paragraphElement:paragraphElement, memberId:memberid, timeStamp:timestamp});
++ odtDocument.getOdfCanvas().rerenderAnnotations();
++ return true
+ }
- if(isMoveCursorSpecRangeInverted) {
- invertMoveCursorSpecRange(moveCursorSpec)
++ return false
++ };
++ this.spec = function() {
++ return{optype:"InsertText", memberid:memberid, timestamp:timestamp, position:position, text:text}
++ }
++};
++ops.OpInsertText.Spec;
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++ops.OpMoveCursor = function OpMoveCursor() {
++ var memberid, timestamp, position, length, selectionType;
++ this.init = function(data) {
++ memberid = data.memberid;
++ timestamp = data.timestamp;
++ position = data.position;
++ length = data.length || 0;
++ selectionType = data.selectionType || ops.OdtCursor.RangeSelection
++ };
++ this.isEdit = false;
++ this.execute = function(odtDocument) {
++ var cursor = odtDocument.getCursor(memberid), selectedRange;
++ if(!cursor) {
++ return false
+ }
- return{opSpecsA:[moveCursorSpec], opSpecsB:[splitParagraphSpec]}
- }
- function transformRemoveCursorRemoveCursor(removeCursorSpecA, removeCursorSpecB) {
- var isSameMemberid = removeCursorSpecA.memberid === removeCursorSpecB.memberid;
- return{opSpecsA:isSameMemberid ? [] : [removeCursorSpecA], opSpecsB:isSameMemberid ? [] : [removeCursorSpecB]}
- }
- function transformRemoveStyleRemoveStyle(removeStyleSpecA, removeStyleSpecB) {
- var isSameStyle = removeStyleSpecA.styleName === removeStyleSpecB.styleName && removeStyleSpecA.styleFamily === removeStyleSpecB.styleFamily;
- return{opSpecsA:isSameStyle ? [] : [removeStyleSpecA], opSpecsB:isSameStyle ? [] : [removeStyleSpecB]}
++ selectedRange = odtDocument.convertCursorToDomRange(position, length);
++ cursor.setSelectedRange(selectedRange, length >= 0);
++ cursor.setSelectionType(selectionType);
++ odtDocument.emit(ops.OdtDocument.signalCursorMoved, cursor);
++ return true
++ };
++ this.spec = function() {
++ return{optype:"MoveCursor", memberid:memberid, timestamp:timestamp, position:position, length:length, selectionType:selectionType}
+ }
- function transformRemoveStyleSetParagraphStyle(removeStyleSpec, setParagraphStyleSpec) {
- var helperOpspec, removeStyleSpecResult = [removeStyleSpec], setParagraphStyleSpecResult = [setParagraphStyleSpec];
- if(removeStyleSpec.styleFamily === "paragraph" && removeStyleSpec.styleName === setParagraphStyleSpec.styleName) {
- helperOpspec = {optype:"SetParagraphStyle", memberid:removeStyleSpec.memberid, timestamp:removeStyleSpec.timestamp, position:setParagraphStyleSpec.position, styleName:""};
- removeStyleSpecResult.unshift(helperOpspec);
- setParagraphStyleSpec.styleName = ""
++};
++ops.OpMoveCursor.Spec;
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++runtime.loadClass("odf.Namespaces");
++runtime.loadClass("core.DomUtils");
++ops.OpRemoveAnnotation = function OpRemoveAnnotation() {
++ var memberid, timestamp, position, length, domUtils;
++ this.init = function(data) {
++ memberid = data.memberid;
++ timestamp = data.timestamp;
++ position = parseInt(data.position, 10);
++ length = parseInt(data.length, 10);
++ domUtils = new core.DomUtils
++ };
++ this.isEdit = true;
++ this.execute = function(odtDocument) {
++ var iterator = odtDocument.getIteratorAtPosition(position), container = iterator.container(), annotationName, annotationNode, annotationEnd, cursors;
++ while(!(container.namespaceURI === odf.Namespaces.officens && container.localName === "annotation")) {
++ container = container.parentNode
+ }
- return{opSpecsA:removeStyleSpecResult, opSpecsB:setParagraphStyleSpecResult}
- }
- function transformRemoveStyleUpdateParagraphStyle(removeStyleSpec, updateParagraphStyleSpec) {
- var setAttributes, helperOpspec, removeStyleSpecResult = [removeStyleSpec], updateParagraphStyleSpecResult = [updateParagraphStyleSpec];
- if(removeStyleSpec.styleFamily === "paragraph") {
- setAttributes = getStyleReferencingAttributes(updateParagraphStyleSpec.setProperties, removeStyleSpec.styleName);
- if(setAttributes.length > 0) {
- helperOpspec = {optype:"UpdateParagraphStyle", memberid:removeStyleSpec.memberid, timestamp:removeStyleSpec.timestamp, styleName:updateParagraphStyleSpec.styleName, removedProperties:{attributes:setAttributes.join(",")}};
- removeStyleSpecResult.unshift(helperOpspec)
- }
- if(removeStyleSpec.styleName === updateParagraphStyleSpec.styleName) {
- updateParagraphStyleSpecResult = []
- }else {
- dropStyleReferencingAttributes(updateParagraphStyleSpec.setProperties, removeStyleSpec.styleName)
- }
++ if(container === null) {
++ return false
+ }
- return{opSpecsA:removeStyleSpecResult, opSpecsB:updateParagraphStyleSpecResult}
- }
- function transformRemoveTextRemoveText(removeTextSpecA, removeTextSpecB) {
- var removeTextSpecAEnd = removeTextSpecA.position + removeTextSpecA.length, removeTextSpecBEnd = removeTextSpecB.position + removeTextSpecB.length, removeTextSpecAResult = [removeTextSpecA], removeTextSpecBResult = [removeTextSpecB];
- if(removeTextSpecBEnd <= removeTextSpecA.position) {
- removeTextSpecA.position -= removeTextSpecB.length
- }else {
- if(removeTextSpecAEnd <= removeTextSpecB.position) {
- removeTextSpecB.position -= removeTextSpecA.length
- }else {
- if(removeTextSpecB.position < removeTextSpecAEnd) {
- if(removeTextSpecA.position < removeTextSpecB.position) {
- if(removeTextSpecBEnd < removeTextSpecAEnd) {
- removeTextSpecA.length = removeTextSpecA.length - removeTextSpecB.length
- }else {
- removeTextSpecA.length = removeTextSpecB.position - removeTextSpecA.position
- }
- if(removeTextSpecAEnd < removeTextSpecBEnd) {
- removeTextSpecB.position = removeTextSpecA.position;
- removeTextSpecB.length = removeTextSpecBEnd - removeTextSpecAEnd
- }else {
- removeTextSpecBResult = []
- }
- }else {
- if(removeTextSpecAEnd < removeTextSpecBEnd) {
- removeTextSpecB.length = removeTextSpecB.length - removeTextSpecA.length
- }else {
- if(removeTextSpecB.position < removeTextSpecA.position) {
- removeTextSpecB.length = removeTextSpecA.position - removeTextSpecB.position
- }else {
- removeTextSpecBResult = []
- }
- }
- if(removeTextSpecBEnd < removeTextSpecAEnd) {
- removeTextSpecA.position = removeTextSpecB.position;
- removeTextSpecA.length = removeTextSpecAEnd - removeTextSpecBEnd
- }else {
- removeTextSpecAResult = []
- }
- }
- }
- }
++ annotationNode = container;
++ annotationName = annotationNode.getAttributeNS(odf.Namespaces.officens, "name");
++ if(annotationName) {
++ annotationEnd = domUtils.getElementsByTagNameNS(odtDocument.getRootNode(), odf.Namespaces.officens, "annotation-end").filter(function(element) {
++ return annotationName === element.getAttributeNS(odf.Namespaces.officens, "name")
++ })[0] || null
+ }
- return{opSpecsA:removeTextSpecAResult, opSpecsB:removeTextSpecBResult}
- }
- function transformRemoveTextSplitParagraph(removeTextSpec, splitParagraphSpec) {
- var removeTextSpecEnd = removeTextSpec.position + removeTextSpec.length, helperOpspec, removeTextSpecResult = [removeTextSpec], splitParagraphSpecResult = [splitParagraphSpec];
- if(splitParagraphSpec.position <= removeTextSpec.position) {
- removeTextSpec.position += 1
- }else {
- if(splitParagraphSpec.position < removeTextSpecEnd) {
- removeTextSpec.length = splitParagraphSpec.position - removeTextSpec.position;
- helperOpspec = {optype:"RemoveText", memberid:removeTextSpec.memberid, timestamp:removeTextSpec.timestamp, position:splitParagraphSpec.position + 1, length:removeTextSpecEnd - splitParagraphSpec.position};
- removeTextSpecResult.unshift(helperOpspec)
- }
++ odtDocument.getOdfCanvas().forgetAnnotations();
++ cursors = domUtils.getElementsByTagNameNS(annotationNode, "urn:webodf:names:cursor", "cursor");
++ while(cursors.length) {
++ annotationNode.parentNode.insertBefore(cursors.pop(), annotationNode)
+ }
- if(removeTextSpec.position + removeTextSpec.length <= splitParagraphSpec.position) {
- splitParagraphSpec.position -= removeTextSpec.length
- }else {
- if(removeTextSpec.position < splitParagraphSpec.position) {
- splitParagraphSpec.position = removeTextSpec.position
- }
++ annotationNode.parentNode.removeChild(annotationNode);
++ if(annotationEnd) {
++ annotationEnd.parentNode.removeChild(annotationEnd)
+ }
- return{opSpecsA:removeTextSpecResult, opSpecsB:splitParagraphSpecResult}
- }
- function passUnchanged(opSpecA, opSpecB) {
- return{opSpecsA:[opSpecA], opSpecsB:[opSpecB]}
++ odtDocument.emit(ops.OdtDocument.signalStepsRemoved, {position:position > 0 ? position - 1 : position, length:length});
++ odtDocument.fixCursorPositions();
++ odtDocument.getOdfCanvas().refreshAnnotations();
++ return true
++ };
++ this.spec = function() {
++ return{optype:"RemoveAnnotation", memberid:memberid, timestamp:timestamp, position:position, length:length}
+ }
- var transformations = {"AddCursor":{"AddCursor":passUnchanged, "AddMember":passUnchanged, "AddStyle":passUnchanged, "ApplyDirectStyling":passUnchanged, "InsertText":passUnchanged, "MoveCursor":passUnchanged, "RemoveCursor":passUnchanged, "RemoveMember":passUnchanged, "RemoveStyle":passUnchanged, "RemoveText":passUnchanged, "SetParagraphStyle":passUnchanged, "SplitParagraph":passUnchanged, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchange [...]
- "InsertText":passUnchanged, "MoveCursor":passUnchanged, "RemoveCursor":passUnchanged, "RemoveStyle":passUnchanged, "RemoveText":passUnchanged, "SetParagraphStyle":passUnchanged, "SplitParagraph":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "AddStyle":{"AddStyle":passUnchanged, "ApplyDirectStyling":passUnchanged, "InsertText":passUnchanged, "MoveCursor":passUnchanged, "RemoveCursor":passUnchanged, "RemoveMember":passUnchanged, "RemoveStyle":tran [...]
- "RemoveText":passUnchanged, "SetParagraphStyle":passUnchanged, "SplitParagraph":passUnchanged, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "ApplyDirectStyling":{"ApplyDirectStyling":transformApplyDirectStylingApplyDirectStyling, "InsertText":transformApplyDirectStylingInsertText, "MoveCursor":passUnchanged, "RemoveCursor":passUnchanged, "RemoveStyle":passUnchanged, "RemoveText":transformApplyDirectStylingRemoveText, "SetParagrap [...]
- "SplitParagraph":transformApplyDirectStylingSplitParagraph, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "InsertText":{"InsertText":transformInsertTextInsertText, "MoveCursor":transformInsertTextMoveCursor, "RemoveCursor":passUnchanged, "RemoveMember":passUnchanged, "RemoveStyle":passUnchanged, "RemoveText":transformInsertTextRemoveText, "SplitParagraph":transformInsertTextSplitParagraph, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdatePa [...]
- "MoveCursor":{"MoveCursor":passUnchanged, "RemoveCursor":transformMoveCursorRemoveCursor, "RemoveMember":passUnchanged, "RemoveStyle":passUnchanged, "RemoveText":transformMoveCursorRemoveText, "SetParagraphStyle":passUnchanged, "SplitParagraph":transformMoveCursorSplitParagraph, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "RemoveCursor":{"RemoveCursor":transformRemoveCursorRemoveCursor, "RemoveMember":passUnchanged, "RemoveStyle [...]
- "RemoveText":passUnchanged, "SetParagraphStyle":passUnchanged, "SplitParagraph":passUnchanged, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "RemoveMember":{"RemoveStyle":passUnchanged, "RemoveText":passUnchanged, "SetParagraphStyle":passUnchanged, "SplitParagraph":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "RemoveStyle":{"RemoveStyle":transformRemoveStyleRemoveStyle, "RemoveText":passUnc [...]
- "SplitParagraph":passUnchanged, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":transformRemoveStyleUpdateParagraphStyle}, "RemoveText":{"RemoveText":transformRemoveTextRemoveText, "SplitParagraph":transformRemoveTextSplitParagraph, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "SetParagraphStyle":{"UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchange [...]
- "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "UpdateMember":{"UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "UpdateMetadata":{"UpdateMetadata":transformUpdateMetadataUpdateMetadata, "UpdateParagraphStyle":passUnchanged}, "UpdateParagraphStyle":{"UpdateParagraphStyle":transformUpdateParagraphStyleUpdateParagraphStyle}};
- this.passUnchanged = passUnchanged;
- this.extendTransformations = function(moreTransformations) {
- Object.keys(moreTransformations).forEach(function(optypeA) {
- var moreTransformationsOptypeAMap = moreTransformations[optypeA], optypeAMap, isExtendingOptypeAMap = transformations.hasOwnProperty(optypeA);
- runtime.log((isExtendingOptypeAMap ? "Extending" : "Adding") + " map for optypeA: " + optypeA);
- if(!isExtendingOptypeAMap) {
- transformations[optypeA] = {}
- }
- optypeAMap = transformations[optypeA];
- Object.keys(moreTransformationsOptypeAMap).forEach(function(optypeB) {
- var isOverwritingOptypeBEntry = optypeAMap.hasOwnProperty(optypeB);
- runtime.assert(optypeA <= optypeB, "Wrong order:" + optypeA + ", " + optypeB);
- runtime.log(" " + (isOverwritingOptypeBEntry ? "Overwriting" : "Adding") + " entry for optypeB: " + optypeB);
- optypeAMap[optypeB] = moreTransformationsOptypeAMap[optypeB]
- })
- })
++};
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++ops.OpRemoveBlob = function OpRemoveBlob() {
++ var memberid, timestamp, filename;
++ this.init = function(data) {
++ memberid = data.memberid;
++ timestamp = data.timestamp;
++ filename = data.filename
+ };
- this.transformOpspecVsOpspec = function(opSpecA, opSpecB) {
- var isOptypeAAlphaNumericSmaller = opSpecA.optype <= opSpecB.optype, helper, transformationFunctionMap, transformationFunction, result;
- runtime.log("Crosstransforming:");
- runtime.log(runtime.toJson(opSpecA));
- runtime.log(runtime.toJson(opSpecB));
- if(!isOptypeAAlphaNumericSmaller) {
- helper = opSpecA;
- opSpecA = opSpecB;
- opSpecB = helper
- }
- transformationFunctionMap = transformations[opSpecA.optype];
- transformationFunction = transformationFunctionMap && transformationFunctionMap[opSpecB.optype];
- if(transformationFunction) {
- result = transformationFunction(opSpecA, opSpecB, !isOptypeAAlphaNumericSmaller);
- if(!isOptypeAAlphaNumericSmaller && result !== null) {
- result = {opSpecsA:result.opSpecsB, opSpecsB:result.opSpecsA}
- }
- }else {
- result = null
- }
- runtime.log("result:");
- if(result) {
- runtime.log(runtime.toJson(result.opSpecsA));
- runtime.log(runtime.toJson(result.opSpecsB))
- }else {
- runtime.log("null")
++ this.isEdit = true;
++ this.execute = function(odtDocument) {
++ odtDocument.getOdfCanvas().odfContainer().removeBlob(filename);
++ return true
++ };
++ this.spec = function() {
++ return{optype:"RemoveBlob", memberid:memberid, timestamp:timestamp, filename:filename}
++ }
++};
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++ops.OpRemoveCursor = function OpRemoveCursor() {
++ var memberid, timestamp;
++ this.init = function(data) {
++ memberid = data.memberid;
++ timestamp = data.timestamp
++ };
++ this.isEdit = false;
++ this.execute = function(odtDocument) {
++ if(!odtDocument.removeCursor(memberid)) {
++ return false
+ }
- return result
++ return true
++ };
++ this.spec = function() {
++ return{optype:"RemoveCursor", memberid:memberid, timestamp:timestamp}
+ }
+};
++ops.OpRemoveCursor.Spec;
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ This file is part of WebODF.
+
+ WebODF is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License (GNU AGPL)
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ WebODF is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ @licend
+
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("ops.OperationFactory");
- runtime.loadClass("ops.OperationTransformMatrix");
- ops.OperationTransformer = function OperationTransformer() {
- var operationFactory, operationTransformMatrix = new ops.OperationTransformMatrix;
- function operations(opspecs) {
- var ops = [];
- opspecs.forEach(function(opspec) {
- ops.push(operationFactory.create(opspec))
- });
- return ops
- }
- function transformOpVsOp(opSpecA, opSpecB) {
- return operationTransformMatrix.transformOpspecVsOpspec(opSpecA, opSpecB)
- }
- function transformOpListVsOp(opSpecsA, opSpecB) {
- var transformResult, transformListResult, transformedOpspecsA = [], transformedOpspecsB = [];
- while(opSpecsA.length > 0 && opSpecB) {
- transformResult = transformOpVsOp(opSpecsA.shift(), (opSpecB));
- if(!transformResult) {
- return null
- }
- transformedOpspecsA = transformedOpspecsA.concat(transformResult.opSpecsA);
- if(transformResult.opSpecsB.length === 0) {
- transformedOpspecsA = transformedOpspecsA.concat(opSpecsA);
- opSpecB = null;
- break
- }
- while(transformResult.opSpecsB.length > 1) {
- transformListResult = transformOpListVsOp(opSpecsA, transformResult.opSpecsB.shift());
- if(!transformListResult) {
- return null
- }
- transformedOpspecsB = transformedOpspecsB.concat(transformListResult.opSpecsB);
- opSpecsA = transformListResult.opSpecsA
- }
- opSpecB = transformResult.opSpecsB.pop()
- }
- if(opSpecB) {
- transformedOpspecsB.push(opSpecB)
- }
- return{opSpecsA:transformedOpspecsA, opSpecsB:transformedOpspecsB}
- }
- this.setOperationFactory = function(f) {
- operationFactory = f
- };
- this.getOperationTransformMatrix = function() {
- return operationTransformMatrix
++runtime.loadClass("ops.Member");
++ops.OpRemoveMember = function OpRemoveMember() {
++ var memberid, timestamp;
++ this.init = function(data) {
++ memberid = data.memberid;
++ timestamp = parseInt(data.timestamp, 10)
+ };
- this.transform = function(opSpecsA, opSpecsB) {
- var transformResult, transformedOpspecsB = [];
- while(opSpecsB.length > 0) {
- transformResult = transformOpListVsOp(opSpecsA, opSpecsB.shift());
- if(!transformResult) {
- return null
- }
- opSpecsA = transformResult.opSpecsA;
- transformedOpspecsB = transformedOpspecsB.concat(transformResult.opSpecsB)
++ this.isEdit = false;
++ this.execute = function(odtDocument) {
++ if(!odtDocument.getMember(memberid)) {
++ return false
+ }
- return{opsA:operations(opSpecsA), opsB:operations(transformedOpspecsB)}
++ odtDocument.removeMember(memberid);
++ odtDocument.emit(ops.OdtDocument.signalMemberRemoved, memberid);
++ return true
++ };
++ this.spec = function() {
++ return{optype:"RemoveMember", memberid:memberid, timestamp:timestamp}
+ }
+};
- runtime.loadClass("core.Cursor");
- runtime.loadClass("gui.SelectionMover");
- ops.OdtCursor = function OdtCursor(memberId, odtDocument) {
- var self = this, validSelectionTypes = {}, selectionType, selectionMover, cursor;
- this.removeFromOdtDocument = function() {
- cursor.remove()
- };
- this.move = function(number, extend) {
- var moved = 0;
- if(number > 0) {
- moved = selectionMover.movePointForward(number, extend)
- }else {
- if(number <= 0) {
- moved = -selectionMover.movePointBackward(-number, extend)
- }
- }
- self.handleUpdate();
- return moved
- };
- this.handleUpdate = function() {
- };
- this.getStepCounter = function() {
- return selectionMover.getStepCounter()
- };
- this.getMemberId = function() {
- return memberId
- };
- this.getNode = function() {
- return cursor.getNode()
- };
- this.getAnchorNode = function() {
- return cursor.getAnchorNode()
- };
- this.getSelectedRange = function() {
- return cursor.getSelectedRange()
- };
- this.setSelectedRange = function(range, isForwardSelection) {
- cursor.setSelectedRange(range, isForwardSelection);
- self.handleUpdate()
- };
- this.hasForwardSelection = function() {
- return cursor.hasForwardSelection()
- };
- this.getOdtDocument = function() {
- return odtDocument
- };
- this.getSelectionType = function() {
- return selectionType
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++ops.OpRemoveStyle = function OpRemoveStyle() {
++ var memberid, timestamp, styleName, styleFamily;
++ this.init = function(data) {
++ memberid = data.memberid;
++ timestamp = data.timestamp;
++ styleName = data.styleName;
++ styleFamily = data.styleFamily
+ };
- this.setSelectionType = function(value) {
- if(validSelectionTypes.hasOwnProperty(value)) {
- selectionType = value
- }else {
- runtime.log("Invalid selection type: " + value)
++ this.isEdit = true;
++ this.execute = function(odtDocument) {
++ var styleNode = odtDocument.getStyleElement(styleName, styleFamily);
++ if(!styleNode) {
++ return false
+ }
++ styleNode.parentNode.removeChild(styleNode);
++ odtDocument.getOdfCanvas().refreshCSS();
++ odtDocument.emit(ops.OdtDocument.signalCommonStyleDeleted, {name:styleName, family:styleFamily});
++ return true
+ };
- this.resetSelectionType = function() {
- self.setSelectionType(ops.OdtCursor.RangeSelection)
- };
- function init() {
- cursor = new core.Cursor(odtDocument.getDOM(), memberId);
- selectionMover = new gui.SelectionMover(cursor, odtDocument.getRootNode());
- validSelectionTypes[ops.OdtCursor.RangeSelection] = true;
- validSelectionTypes[ops.OdtCursor.RegionSelection] = true;
- self.resetSelectionType()
++ this.spec = function() {
++ return{optype:"RemoveStyle", memberid:memberid, timestamp:timestamp, styleName:styleName, styleFamily:styleFamily}
+ }
- init()
+};
- ops.OdtCursor.RangeSelection = "Range";
- ops.OdtCursor.RegionSelection = "Region";
- (function() {
- return ops.OdtCursor
- })();
++ops.OpRemoveStyle.Spec;
+/*
+
- Copyright (C) 2012 KO GmbH <aditya.bhatt at kogmbh.com>
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.EditInfo = function EditInfo(container, odtDocument) {
- var editInfoNode, editHistory = {};
- function sortEdits() {
- var arr = [], memberid;
- for(memberid in editHistory) {
- if(editHistory.hasOwnProperty(memberid)) {
- arr.push({"memberid":memberid, "time":editHistory[memberid].time})
- }
- }
- arr.sort(function(a, b) {
- return a.time - b.time
- });
- return arr
- }
- this.getNode = function() {
- return editInfoNode
- };
- this.getOdtDocument = function() {
- return odtDocument
- };
- this.getEdits = function() {
- return editHistory
- };
- this.getSortedEdits = function() {
- return sortEdits()
- };
- this.addEdit = function(memberid, timestamp) {
- editHistory[memberid] = {time:timestamp}
- };
- this.clearEdits = function() {
- editHistory = {}
- };
- this.destroy = function(callback) {
- if(container.parentNode) {
- container.removeChild(editInfoNode)
- }
- callback()
- };
- function init() {
- var editInfons = "urn:webodf:names:editinfo", dom = odtDocument.getDOM();
- editInfoNode = dom.createElementNS(editInfons, "editinfo");
- container.insertBefore(editInfoNode, container.firstChild)
- }
- init()
- };
- runtime.loadClass("gui.SelectionMover");
- gui.ShadowCursor = function ShadowCursor(odtDocument) {
- var selectedRange = odtDocument.getDOM().createRange(), forwardSelection = true;
- this.removeFromOdtDocument = function() {
- };
- this.getMemberId = function() {
- return gui.ShadowCursor.ShadowCursorMemberId
- };
- this.getSelectedRange = function() {
- return selectedRange
- };
- this.setSelectedRange = function(range, isForwardSelection) {
- selectedRange = range;
- forwardSelection = isForwardSelection !== false
- };
- this.hasForwardSelection = function() {
- return forwardSelection
- };
- this.getOdtDocument = function() {
- return odtDocument
- };
- this.getSelectionType = function() {
- return ops.OdtCursor.RangeSelection
- };
- function init() {
- selectedRange.setStart(odtDocument.getRootNode(), 0)
- }
- init()
- };
- gui.ShadowCursor.ShadowCursorMemberId = "";
- (function() {
- return gui.ShadowCursor
- })();
- gui.Avatar = function Avatar(parentElement, avatarInitiallyVisible) {
- var self = this, handle, image, pendingImageUrl, displayShown = "block", displayHidden = "none";
- this.setColor = function(color) {
- image.style.borderColor = color
- };
- this.setImageUrl = function(url) {
- if(self.isVisible()) {
- image.src = url
- }else {
- pendingImageUrl = url
- }
- };
- this.isVisible = function() {
- return handle.style.display === displayShown
++runtime.loadClass("odf.Namespaces");
++runtime.loadClass("odf.OdfUtils");
++runtime.loadClass("core.DomUtils");
++ops.OpRemoveText = function OpRemoveText() {
++ var memberid, timestamp, position, length, odfUtils, domUtils, editinfons = "urn:webodf:names:editinfo", odfNodeNamespaceMap = {};
++ this.init = function(data) {
++ runtime.assert(data.length >= 0, "OpRemoveText only supports positive lengths");
++ memberid = data.memberid;
++ timestamp = data.timestamp;
++ position = parseInt(data.position, 10);
++ length = parseInt(data.length, 10);
++ odfUtils = new odf.OdfUtils;
++ domUtils = new core.DomUtils;
++ odfNodeNamespaceMap[odf.Namespaces.dbns] = true;
++ odfNodeNamespaceMap[odf.Namespaces.dcns] = true;
++ odfNodeNamespaceMap[odf.Namespaces.dr3dns] = true;
++ odfNodeNamespaceMap[odf.Namespaces.drawns] = true;
++ odfNodeNamespaceMap[odf.Namespaces.chartns] = true;
++ odfNodeNamespaceMap[odf.Namespaces.formns] = true;
++ odfNodeNamespaceMap[odf.Namespaces.numberns] = true;
++ odfNodeNamespaceMap[odf.Namespaces.officens] = true;
++ odfNodeNamespaceMap[odf.Namespaces.presentationns] = true;
++ odfNodeNamespaceMap[odf.Namespaces.stylens] = true;
++ odfNodeNamespaceMap[odf.Namespaces.svgns] = true;
++ odfNodeNamespaceMap[odf.Namespaces.tablens] = true;
++ odfNodeNamespaceMap[odf.Namespaces.textns] = true
+ };
- this.show = function() {
- if(pendingImageUrl) {
- image.src = pendingImageUrl;
- pendingImageUrl = undefined
++ this.isEdit = true;
++ function CollapsingRules(rootNode) {
++ function isOdfNode(node) {
++ return odfNodeNamespaceMap.hasOwnProperty(node.namespaceURI)
+ }
- handle.style.display = displayShown
- };
- this.hide = function() {
- handle.style.display = displayHidden
- };
- this.markAsFocussed = function(isFocussed) {
- handle.className = isFocussed ? "active" : ""
- };
- this.destroy = function(callback) {
- parentElement.removeChild(handle);
- callback()
- };
- function init() {
- var document = (parentElement.ownerDocument), htmlns = document.documentElement.namespaceURI;
- handle = document.createElementNS(htmlns, "div");
- image = document.createElementNS(htmlns, "img");
- image.width = 64;
- image.height = 64;
- handle.appendChild(image);
- handle.style.width = "64px";
- handle.style.height = "70px";
- handle.style.position = "absolute";
- handle.style.top = "-80px";
- handle.style.left = "-34px";
- handle.style.display = avatarInitiallyVisible ? displayShown : displayHidden;
- parentElement.appendChild(handle)
- }
- init()
- };
- runtime.loadClass("core.DomUtils");
- runtime.loadClass("gui.Avatar");
- runtime.loadClass("ops.OdtCursor");
- gui.Caret = function Caret(cursor, avatarInitiallyVisible, blinkOnRangeSelect) {
- var MIN_CARET_HEIGHT_PX = 8, DEFAULT_CARET_TOP = "5%", DEFAULT_CARET_HEIGHT = "1em", span, avatar, cursorNode, isShown = true, shouldBlink = false, blinking = false, blinkTimeout, domUtils = new core.DomUtils;
- function blink(reset) {
- if(!shouldBlink || !cursorNode.parentNode) {
- return
++ function shouldRemove(node) {
++ return isOdfNode(node) || (node.localName === "br" && odfUtils.isLineBreak(node.parentNode) || node.nodeType === Node.TEXT_NODE && isOdfNode((node.parentNode)))
+ }
- if(!blinking || reset) {
- if(reset && blinkTimeout !== undefined) {
- runtime.clearTimeout(blinkTimeout)
++ function isEmpty(node) {
++ var childNode;
++ if(odfUtils.isCharacterElement(node)) {
++ return false
+ }
- blinking = true;
- span.style.opacity = reset || span.style.opacity === "0" ? "1" : "0";
- blinkTimeout = runtime.setTimeout(function() {
- blinking = false;
- blink(false)
- }, 500)
++ if(node.nodeType === Node.TEXT_NODE) {
++ return node.textContent.length === 0
++ }
++ childNode = node.firstChild;
++ while(childNode) {
++ if(isOdfNode(childNode) || !isEmpty(childNode)) {
++ return false
++ }
++ childNode = childNode.nextSibling
++ }
++ return true
+ }
- }
- function getCaretClientRectWithMargin(caretElement, margin) {
- var caretRect = caretElement.getBoundingClientRect();
- return{left:caretRect.left - margin.left, top:caretRect.top - margin.top, right:caretRect.right + margin.right, bottom:caretRect.bottom + margin.bottom}
- }
- function length(node) {
- return node.nodeType === Node.TEXT_NODE ? node.textContent.length : node.childNodes.length
- }
- function verticalOverlap(cursorNode, rangeRect) {
- var cursorRect = cursorNode.getBoundingClientRect(), intersectTop = 0, intersectBottom = 0;
- if(cursorRect && rangeRect) {
- intersectTop = Math.max(cursorRect.top, rangeRect.top);
- intersectBottom = Math.min(cursorRect.bottom, rangeRect.bottom)
++ this.isEmpty = isEmpty;
++ function isCollapsibleContainer(node) {
++ return!odfUtils.isParagraph(node) && (node !== rootNode && isEmpty(node))
+ }
- return intersectBottom - intersectTop
- }
- function getSelectionRect() {
- var range = cursor.getSelectedRange().cloneRange(), node = cursor.getNode(), nextRectangle, selectionRectangle = null, nodeLength;
- if(node.previousSibling) {
- nodeLength = length(node.previousSibling);
- range.setStart(node.previousSibling, nodeLength > 0 ? nodeLength - 1 : 0);
- range.setEnd(node.previousSibling, nodeLength);
- nextRectangle = range.getBoundingClientRect();
- if(nextRectangle && nextRectangle.height) {
- selectionRectangle = nextRectangle
++ function mergeChildrenIntoParent(targetNode) {
++ var parent;
++ if(targetNode.nodeType === Node.TEXT_NODE) {
++ parent = targetNode.parentNode;
++ parent.removeChild(targetNode)
++ }else {
++ parent = domUtils.removeUnwantedNodes(targetNode, shouldRemove)
+ }
- }
- if(node.nextSibling) {
- range.setStart(node.nextSibling, 0);
- range.setEnd(node.nextSibling, length(node.nextSibling) > 0 ? 1 : 0);
- nextRectangle = range.getBoundingClientRect();
- if(nextRectangle && nextRectangle.height) {
- if(!selectionRectangle || verticalOverlap(node, nextRectangle) > verticalOverlap(node, selectionRectangle)) {
- selectionRectangle = nextRectangle
- }
++ if(isCollapsibleContainer(parent)) {
++ return mergeChildrenIntoParent(parent)
+ }
++ return parent
+ }
- return selectionRectangle
++ this.mergeChildrenIntoParent = mergeChildrenIntoParent
+ }
- function handleUpdate() {
- var selectionRect = getSelectionRect(), zoomLevel = cursor.getOdtDocument().getOdfCanvas().getZoomLevel(), caretRect;
- if(isShown && cursor.getSelectionType() === ops.OdtCursor.RangeSelection) {
- span.style.visibility = "visible"
- }else {
- span.style.visibility = "hidden"
- }
- if(selectionRect) {
- span.style.top = "0";
- caretRect = domUtils.getBoundingClientRect(span);
- if(selectionRect.height < MIN_CARET_HEIGHT_PX) {
- selectionRect = {top:selectionRect.top - (MIN_CARET_HEIGHT_PX - selectionRect.height) / 2, height:MIN_CARET_HEIGHT_PX}
++ function mergeParagraphs(first, second, collapseRules) {
++ var child, mergeForward = false, destination = first, source = second, secondParent, insertionPoint = null;
++ if(collapseRules.isEmpty(first)) {
++ mergeForward = true;
++ if(second.parentNode !== first.parentNode) {
++ secondParent = second.parentNode;
++ first.parentNode.insertBefore(second, first.nextSibling)
+ }
- span.style.height = domUtils.adaptRangeDifferenceToZoomLevel(selectionRect.height, zoomLevel) + "px";
- span.style.top = domUtils.adaptRangeDifferenceToZoomLevel(selectionRect.top - caretRect.top, zoomLevel) + "px"
- }else {
- span.style.height = DEFAULT_CARET_HEIGHT;
- span.style.top = DEFAULT_CARET_TOP
- }
- }
- this.handleUpdate = handleUpdate;
- this.refreshCursorBlinking = function() {
- if(blinkOnRangeSelect || cursor.getSelectedRange().collapsed) {
- shouldBlink = true;
- blink(true)
- }else {
- shouldBlink = false;
- span.style.opacity = "0"
- }
- };
- this.setFocus = function() {
- shouldBlink = true;
- avatar.markAsFocussed(true);
- blink(true)
- };
- this.removeFocus = function() {
- shouldBlink = false;
- avatar.markAsFocussed(false);
- span.style.opacity = "1"
- };
- this.show = function() {
- isShown = true;
- handleUpdate();
- avatar.markAsFocussed(true)
- };
- this.hide = function() {
- isShown = false;
- handleUpdate();
- avatar.markAsFocussed(false)
- };
- this.setAvatarImageUrl = function(url) {
- avatar.setImageUrl(url)
- };
- this.setColor = function(newColor) {
- span.style.borderColor = newColor;
- avatar.setColor(newColor)
- };
- this.getCursor = function() {
- return cursor
- };
- this.getFocusElement = function() {
- return span
- };
- this.toggleHandleVisibility = function() {
- if(avatar.isVisible()) {
- avatar.hide()
- }else {
- avatar.show()
++ source = first;
++ destination = second;
++ insertionPoint = destination.getElementsByTagNameNS(editinfons, "editinfo")[0] || destination.firstChild
+ }
- };
- this.showHandle = function() {
- avatar.show()
- };
- this.hideHandle = function() {
- avatar.hide()
- };
- this.ensureVisible = function() {
- var canvasElement = cursor.getOdtDocument().getOdfCanvas().getElement(), canvasContainerElement = canvasElement.parentNode, caretRect, canvasContainerRect, horizontalMargin = canvasContainerElement.offsetWidth - canvasContainerElement.clientWidth + 5, verticalMargin = canvasContainerElement.offsetHeight - canvasContainerElement.clientHeight + 5;
- caretRect = getCaretClientRectWithMargin(span, {top:verticalMargin, left:horizontalMargin, bottom:verticalMargin, right:horizontalMargin});
- canvasContainerRect = canvasContainerElement.getBoundingClientRect();
- if(caretRect.top < canvasContainerRect.top) {
- canvasContainerElement.scrollTop -= canvasContainerRect.top - caretRect.top
- }else {
- if(caretRect.bottom > canvasContainerRect.bottom) {
- canvasContainerElement.scrollTop += caretRect.bottom - canvasContainerRect.bottom
++ while(source.hasChildNodes()) {
++ child = mergeForward ? source.lastChild : source.firstChild;
++ source.removeChild(child);
++ if(child.localName !== "editinfo") {
++ destination.insertBefore(child, insertionPoint)
+ }
+ }
- if(caretRect.left < canvasContainerRect.left) {
- canvasContainerElement.scrollLeft -= canvasContainerRect.left - caretRect.left
- }else {
- if(caretRect.right > canvasContainerRect.right) {
- canvasContainerElement.scrollLeft += caretRect.right - canvasContainerRect.right
- }
++ if(secondParent && collapseRules.isEmpty(secondParent)) {
++ collapseRules.mergeChildrenIntoParent(secondParent)
+ }
- handleUpdate()
- };
- this.destroy = function(callback) {
- avatar.destroy(function(err) {
- if(err) {
- callback(err)
- }else {
- cursorNode.removeChild(span);
- callback()
- }
- })
++ collapseRules.mergeChildrenIntoParent(source);
++ return destination
++ }
++ this.execute = function(odtDocument) {
++ var paragraphElement, destinationParagraph, range, textNodes, paragraphs, cursor = odtDocument.getCursor(memberid), collapseRules = new CollapsingRules(odtDocument.getRootNode());
++ odtDocument.upgradeWhitespacesAtPosition(position);
++ odtDocument.upgradeWhitespacesAtPosition(position + length);
++ range = odtDocument.convertCursorToDomRange(position, length);
++ domUtils.splitBoundaries(range);
++ paragraphElement = odtDocument.getParagraphElement(range.startContainer);
++ textNodes = odfUtils.getTextElements(range, false, true);
++ paragraphs = odfUtils.getParagraphElements(range);
++ range.detach();
++ textNodes.forEach(function(element) {
++ collapseRules.mergeChildrenIntoParent(element)
++ });
++ destinationParagraph = paragraphs.reduce(function(destination, paragraph) {
++ return mergeParagraphs(destination, paragraph, collapseRules)
++ });
++ odtDocument.emit(ops.OdtDocument.signalStepsRemoved, {position:position, length:length});
++ odtDocument.downgradeWhitespacesAtPosition(position);
++ odtDocument.fixCursorPositions();
++ odtDocument.getOdfCanvas().refreshSize();
++ odtDocument.emit(ops.OdtDocument.signalParagraphChanged, {paragraphElement:destinationParagraph || paragraphElement, memberId:memberid, timeStamp:timestamp});
++ if(cursor) {
++ cursor.resetSelectionType();
++ odtDocument.emit(ops.OdtDocument.signalCursorMoved, cursor)
++ }
++ odtDocument.getOdfCanvas().rerenderAnnotations();
++ return true
+ };
- function init() {
- var dom = cursor.getOdtDocument().getDOM(), htmlns = dom.documentElement.namespaceURI;
- span = dom.createElementNS(htmlns, "span");
- span.style.top = DEFAULT_CARET_TOP;
- cursorNode = cursor.getNode();
- cursorNode.appendChild(span);
- avatar = new gui.Avatar(cursorNode, avatarInitiallyVisible);
- handleUpdate()
++ this.spec = function() {
++ return{optype:"RemoveText", memberid:memberid, timestamp:timestamp, position:position, length:length}
+ }
- init()
+};
++ops.OpRemoveText.Spec;
+/*
+
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- gui.PlainTextPasteboard = function PlainTextPasteboard(odtDocument, inputMemberId) {
- function createOp(op, data) {
- op.init(data);
- return op
- }
- this.createPasteOps = function(data) {
- var originalCursorPosition = odtDocument.getCursorPosition(inputMemberId), cursorPosition = originalCursorPosition, operations = [], paragraphs;
- paragraphs = data.replace(/\r/g, "").split("\n");
- paragraphs.forEach(function(text) {
- operations.push(createOp(new ops.OpSplitParagraph, {memberid:inputMemberId, position:cursorPosition}));
- cursorPosition += 1;
- operations.push(createOp(new ops.OpInsertText, {memberid:inputMemberId, position:cursorPosition, text:text}));
- cursorPosition += text.length
- });
- operations.push(createOp(new ops.OpRemoveText, {memberid:inputMemberId, position:originalCursorPosition, length:1}));
- return operations
++ops.OpSetBlob = function OpSetBlob() {
++ var memberid, timestamp, filename, mimetype, content;
++ this.init = function(data) {
++ memberid = data.memberid;
++ timestamp = data.timestamp;
++ filename = data.filename;
++ mimetype = data.mimetype;
++ content = data.content
++ };
++ this.isEdit = true;
++ this.execute = function(odtDocument) {
++ odtDocument.getOdfCanvas().odfContainer().setBlob(filename, mimetype, content);
++ return true
++ };
++ this.spec = function() {
++ return{optype:"SetBlob", memberid:memberid, timestamp:timestamp, filename:filename, mimetype:mimetype, content:content}
+ }
+};
+/*
+
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("odf.Namespaces");
- runtime.loadClass("xmldom.LSSerializer");
- runtime.loadClass("odf.OdfNodeFilter");
- runtime.loadClass("odf.TextSerializer");
- gui.Clipboard = function Clipboard() {
- var xmlSerializer, textSerializer, filter;
- this.setDataFromRange = function(e, range) {
- var result = true, setDataResult, clipboard = e.clipboardData, window = runtime.getWindow(), document = range.startContainer.ownerDocument, fragmentContainer;
- if(!clipboard && window) {
- clipboard = window.clipboardData
- }
- if(clipboard) {
- fragmentContainer = document.createElement("span");
- fragmentContainer.appendChild(range.cloneContents());
- setDataResult = clipboard.setData("text/plain", textSerializer.writeToString(fragmentContainer));
- result = result && setDataResult;
- setDataResult = clipboard.setData("text/html", xmlSerializer.writeToString(fragmentContainer, odf.Namespaces.namespaceMap));
- result = result && setDataResult;
- e.preventDefault()
- }else {
- result = false
- }
- return result
++ops.OpSetParagraphStyle = function OpSetParagraphStyle() {
++ var memberid, timestamp, position, styleName, textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0";
++ this.init = function(data) {
++ memberid = data.memberid;
++ timestamp = data.timestamp;
++ position = data.position;
++ styleName = data.styleName
+ };
- function init() {
- xmlSerializer = new xmldom.LSSerializer;
- textSerializer = new odf.TextSerializer;
- filter = new odf.OdfNodeFilter;
- xmlSerializer.filter = filter;
- textSerializer.filter = filter
++ this.isEdit = true;
++ this.execute = function(odtDocument) {
++ var iterator, paragraphNode;
++ iterator = odtDocument.getIteratorAtPosition(position);
++ paragraphNode = odtDocument.getParagraphElement(iterator.container());
++ if(paragraphNode) {
++ if(styleName !== "") {
++ paragraphNode.setAttributeNS(textns, "text:style-name", styleName)
++ }else {
++ paragraphNode.removeAttributeNS(textns, "style-name")
++ }
++ odtDocument.getOdfCanvas().refreshSize();
++ odtDocument.emit(ops.OdtDocument.signalParagraphChanged, {paragraphElement:paragraphNode, timeStamp:timestamp, memberId:memberid});
++ odtDocument.getOdfCanvas().rerenderAnnotations();
++ return true
++ }
++ return false
++ };
++ this.spec = function() {
++ return{optype:"SetParagraphStyle", memberid:memberid, timestamp:timestamp, position:position, styleName:styleName}
+ }
- init()
+};
++ops.OpSetParagraphStyle.Spec;
+/*
+
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.EventNotifier");
- runtime.loadClass("core.Utils");
- runtime.loadClass("ops.OpApplyDirectStyling");
- runtime.loadClass("gui.StyleHelper");
- gui.DirectTextStyler = function DirectTextStyler(session, inputMemberId) {
- var self = this, utils = new core.Utils, odtDocument = session.getOdtDocument(), styleHelper = new gui.StyleHelper(odtDocument.getFormatting()), eventNotifier = new core.EventNotifier([gui.DirectTextStyler.textStylingChanged]), directCursorStyleProperties, currentSelectionStyles = [], isBoldValue = false, isItalicValue = false, hasUnderlineValue = false, hasStrikeThroughValue = false, fontSizeValue, fontNameValue;
- function get(obj, keys) {
- var i = 0, key = keys[i];
- while(key && obj) {
- obj = obj[key];
- i += 1;
- key = keys[i]
- }
- return keys.length === i ? obj : undefined
- }
- function getCommonValue(objArray, keys) {
- var value = get(objArray[0], keys);
- return objArray.every(function(obj) {
- return value === get(obj, keys)
- }) ? value : undefined
- }
- function getAppliedStyles() {
- var cursor = odtDocument.getCursor(inputMemberId), range = cursor && cursor.getSelectedRange(), selectionStyles = range && styleHelper.getAppliedStyles(range) || [];
- if(selectionStyles[0] && directCursorStyleProperties) {
- selectionStyles[0] = utils.mergeObjects(selectionStyles[0], (directCursorStyleProperties))
- }
- return selectionStyles
- }
- function updatedCachedValues() {
- var fontSize, diffMap;
- currentSelectionStyles = getAppliedStyles();
- function noteChange(oldValue, newValue, id) {
- if(oldValue !== newValue) {
- if(diffMap === undefined) {
- diffMap = {}
- }
- diffMap[id] = newValue
- }
- return newValue
++ops.OpSplitParagraph = function OpSplitParagraph() {
++ var memberid, timestamp, position, odfUtils;
++ this.init = function(data) {
++ memberid = data.memberid;
++ timestamp = data.timestamp;
++ position = data.position;
++ odfUtils = new odf.OdfUtils
++ };
++ this.isEdit = true;
++ this.execute = function(odtDocument) {
++ var domPosition, paragraphNode, targetNode, node, splitNode, splitChildNode, keptChildNode;
++ odtDocument.upgradeWhitespacesAtPosition(position);
++ domPosition = odtDocument.getTextNodeAtStep(position, memberid);
++ if(!domPosition) {
++ return false
+ }
- isBoldValue = noteChange(isBoldValue, currentSelectionStyles ? styleHelper.isBold(currentSelectionStyles) : false, "isBold");
- isItalicValue = noteChange(isItalicValue, currentSelectionStyles ? styleHelper.isItalic(currentSelectionStyles) : false, "isItalic");
- hasUnderlineValue = noteChange(hasUnderlineValue, currentSelectionStyles ? styleHelper.hasUnderline(currentSelectionStyles) : false, "hasUnderline");
- hasStrikeThroughValue = noteChange(hasStrikeThroughValue, currentSelectionStyles ? styleHelper.hasStrikeThrough(currentSelectionStyles) : false, "hasStrikeThrough");
- fontSize = currentSelectionStyles && getCommonValue(currentSelectionStyles, ["style:text-properties", "fo:font-size"]);
- fontSizeValue = noteChange(fontSizeValue, fontSize && parseFloat(fontSize), "fontSize");
- fontNameValue = noteChange(fontNameValue, currentSelectionStyles && getCommonValue(currentSelectionStyles, ["style:text-properties", "style:font-name"]), "fontName");
- if(diffMap) {
- eventNotifier.emit(gui.DirectTextStyler.textStylingChanged, diffMap)
++ paragraphNode = odtDocument.getParagraphElement(domPosition.textNode);
++ if(!paragraphNode) {
++ return false
+ }
- }
- function onCursorAdded(cursor) {
- if(cursor.getMemberId() === inputMemberId) {
- updatedCachedValues()
++ if(odfUtils.isListItem(paragraphNode.parentNode)) {
++ targetNode = paragraphNode.parentNode
++ }else {
++ targetNode = paragraphNode
+ }
- }
- function onCursorRemoved(memberId) {
- if(memberId === inputMemberId) {
- updatedCachedValues()
++ if(domPosition.offset === 0) {
++ keptChildNode = domPosition.textNode.previousSibling;
++ splitChildNode = null
++ }else {
++ keptChildNode = domPosition.textNode;
++ if(domPosition.offset >= domPosition.textNode.length) {
++ splitChildNode = null
++ }else {
++ splitChildNode = (domPosition.textNode.splitText(domPosition.offset))
++ }
+ }
- }
- function onCursorMoved(cursor) {
- if(cursor.getMemberId() === inputMemberId) {
- updatedCachedValues()
++ node = domPosition.textNode;
++ while(node !== targetNode) {
++ node = node.parentNode;
++ splitNode = node.cloneNode(false);
++ if(splitChildNode) {
++ splitNode.appendChild(splitChildNode)
++ }
++ if(keptChildNode) {
++ while(keptChildNode && keptChildNode.nextSibling) {
++ splitNode.appendChild(keptChildNode.nextSibling)
++ }
++ }else {
++ while(node.firstChild) {
++ splitNode.appendChild(node.firstChild)
++ }
++ }
++ node.parentNode.insertBefore(splitNode, node.nextSibling);
++ keptChildNode = node;
++ splitChildNode = splitNode
+ }
- }
- function onParagraphStyleModified() {
- updatedCachedValues()
- }
- function onParagraphChanged(args) {
- var cursor = odtDocument.getCursor(inputMemberId);
- if(cursor && odtDocument.getParagraphElement(cursor.getNode()) === args.paragraphElement) {
- updatedCachedValues()
++ if(odfUtils.isListItem(splitChildNode)) {
++ splitChildNode = splitChildNode.childNodes[0]
+ }
- }
- function toggle(predicate, toggleMethod) {
- var cursor = odtDocument.getCursor(inputMemberId), appliedStyles;
- if(!cursor) {
- return false
++ if(domPosition.textNode.length === 0) {
++ domPosition.textNode.parentNode.removeChild(domPosition.textNode)
+ }
- appliedStyles = styleHelper.getAppliedStyles(cursor.getSelectedRange());
- toggleMethod(!predicate(appliedStyles));
++ odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position:position, length:1});
++ odtDocument.fixCursorPositions();
++ odtDocument.getOdfCanvas().refreshSize();
++ odtDocument.emit(ops.OdtDocument.signalParagraphChanged, {paragraphElement:paragraphNode, memberId:memberid, timeStamp:timestamp});
++ odtDocument.emit(ops.OdtDocument.signalParagraphChanged, {paragraphElement:splitChildNode, memberId:memberid, timeStamp:timestamp});
++ odtDocument.getOdfCanvas().rerenderAnnotations();
+ return true
- }
- function formatTextSelection(textProperties) {
- var selection = odtDocument.getCursorSelection(inputMemberId), op, properties = {"style:text-properties":textProperties};
- if(selection.length !== 0) {
- op = new ops.OpApplyDirectStyling;
- op.init({memberid:inputMemberId, position:selection.position, length:selection.length, setProperties:properties});
- session.enqueue([op])
- }else {
- directCursorStyleProperties = utils.mergeObjects(directCursorStyleProperties || {}, properties);
- updatedCachedValues()
- }
- }
- this.formatTextSelection = formatTextSelection;
- function applyTextPropertyToSelection(propertyName, propertyValue) {
- var textProperties = {};
- textProperties[propertyName] = propertyValue;
- formatTextSelection(textProperties)
- }
- this.createCursorStyleOp = function(position, length) {
- var styleOp = null;
- if(directCursorStyleProperties) {
- styleOp = new ops.OpApplyDirectStyling;
- styleOp.init({memberid:inputMemberId, position:position, length:length, setProperties:directCursorStyleProperties});
- directCursorStyleProperties = null;
- updatedCachedValues()
- }
- return styleOp
+ };
- function clearCursorStyle(op) {
- var spec = op.spec();
- if(directCursorStyleProperties && spec.memberid === inputMemberId) {
- if(spec.optype !== "SplitParagraph") {
- directCursorStyleProperties = null;
- updatedCachedValues()
- }
- }
- }
- function setBold(checked) {
- var value = checked ? "bold" : "normal";
- applyTextPropertyToSelection("fo:font-weight", value)
- }
- this.setBold = setBold;
- function setItalic(checked) {
- var value = checked ? "italic" : "normal";
- applyTextPropertyToSelection("fo:font-style", value)
- }
- this.setItalic = setItalic;
- function setHasUnderline(checked) {
- var value = checked ? "solid" : "none";
- applyTextPropertyToSelection("style:text-underline-style", value)
- }
- this.setHasUnderline = setHasUnderline;
- function setHasStrikethrough(checked) {
- var value = checked ? "solid" : "none";
- applyTextPropertyToSelection("style:text-line-through-style", value)
- }
- this.setHasStrikethrough = setHasStrikethrough;
- function setFontSize(value) {
- applyTextPropertyToSelection("fo:font-size", value + "pt")
- }
- this.setFontSize = setFontSize;
- function setFontName(value) {
- applyTextPropertyToSelection("style:font-name", value)
++ this.spec = function() {
++ return{optype:"SplitParagraph", memberid:memberid, timestamp:timestamp, position:position}
+ }
- this.setFontName = setFontName;
- this.getAppliedStyles = function() {
- return currentSelectionStyles
- };
- this.toggleBold = toggle.bind(self, styleHelper.isBold, setBold);
- this.toggleItalic = toggle.bind(self, styleHelper.isItalic, setItalic);
- this.toggleUnderline = toggle.bind(self, styleHelper.hasUnderline, setHasUnderline);
- this.toggleStrikethrough = toggle.bind(self, styleHelper.hasStrikeThrough, setHasStrikethrough);
- this.isBold = function() {
- return isBoldValue
- };
- this.isItalic = function() {
- return isItalicValue
- };
- this.hasUnderline = function() {
- return hasUnderlineValue
- };
- this.hasStrikeThrough = function() {
- return hasStrikeThroughValue
- };
- this.fontSize = function() {
- return fontSizeValue
- };
- this.fontName = function() {
- return fontNameValue
++};
++ops.OpSplitParagraph.Spec;
++/*
++
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ This file is part of WebODF.
++
++ WebODF is free software: you can redistribute it and/or modify it
++ under the terms of the GNU Affero General Public License (GNU AGPL)
++ as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version.
++
++ WebODF is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU Affero General Public License for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
++ @licend
++
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++runtime.loadClass("ops.Member");
++runtime.loadClass("xmldom.XPath");
++ops.OpUpdateMember = function OpUpdateMember() {
++ var memberid, timestamp, setProperties, removedProperties, doc;
++ this.init = function(data) {
++ memberid = data.memberid;
++ timestamp = parseInt(data.timestamp, 10);
++ setProperties = data.setProperties;
++ removedProperties = data.removedProperties
+ };
- this.subscribe = function(eventid, cb) {
- eventNotifier.subscribe(eventid, cb)
++ this.isEdit = false;
++ function updateCreators() {
++ var xpath = xmldom.XPath, xp = "//dc:creator[@editinfo:memberid='" + memberid + "']", creators = xpath.getODFElementsWithXPath(doc.getRootNode(), xp, function(prefix) {
++ if(prefix === "editinfo") {
++ return"urn:webodf:names:editinfo"
++ }
++ return odf.Namespaces.lookupNamespaceURI(prefix)
++ }), i;
++ for(i = 0;i < creators.length;i += 1) {
++ creators[i].textContent = setProperties.fullName
++ }
++ }
++ this.execute = function(odtDocument) {
++ doc = odtDocument;
++ var member = odtDocument.getMember(memberid);
++ if(!member) {
++ return false
++ }
++ if(removedProperties) {
++ member.removeProperties(removedProperties)
++ }
++ if(setProperties) {
++ member.setProperties(setProperties);
++ if(setProperties.fullName) {
++ updateCreators()
++ }
++ }
++ odtDocument.emit(ops.OdtDocument.signalMemberUpdated, member);
++ return true
+ };
- this.unsubscribe = function(eventid, cb) {
- eventNotifier.unsubscribe(eventid, cb)
++ this.spec = function() {
++ return{optype:"UpdateMember", memberid:memberid, timestamp:timestamp, setProperties:setProperties, removedProperties:removedProperties}
++ }
++};
++/*
++
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ This file is part of WebODF.
++
++ WebODF is free software: you can redistribute it and/or modify it
++ under the terms of the GNU Affero General Public License (GNU AGPL)
++ as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version.
++
++ WebODF is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU Affero General Public License for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
++ @licend
++
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++ops.OpUpdateMetadata = function OpUpdateMetadata() {
++ var memberid, timestamp, setProperties, removedProperties;
++ this.init = function(data) {
++ memberid = data.memberid;
++ timestamp = parseInt(data.timestamp, 10);
++ setProperties = data.setProperties;
++ removedProperties = data.removedProperties
+ };
- this.destroy = function(callback) {
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
- odtDocument.unsubscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified);
- odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged);
- odtDocument.unsubscribe(ops.OdtDocument.signalOperationExecuted, clearCursorStyle);
- callback()
++ this.isEdit = true;
++ this.execute = function(odtDocument) {
++ var metadataManager = odtDocument.getOdfCanvas().odfContainer().getMetadataManager(), removedPropertiesArray = [], blockedProperties = ["dc:date", "dc:creator", "meta:editing-cycles"];
++ if(setProperties) {
++ blockedProperties.forEach(function(el) {
++ if(setProperties[el]) {
++ return false
++ }
++ })
++ }
++ if(removedProperties) {
++ blockedProperties.forEach(function(el) {
++ if(removedPropertiesArray.indexOf(el) !== -1) {
++ return false
++ }
++ });
++ removedPropertiesArray = removedProperties.attributes.split(",")
++ }
++ metadataManager.setMetadata(setProperties, removedPropertiesArray);
++ return true
+ };
- function init() {
- odtDocument.subscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
- odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
- odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
- odtDocument.subscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified);
- odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged);
- odtDocument.subscribe(ops.OdtDocument.signalOperationExecuted, clearCursorStyle);
- updatedCachedValues()
++ this.spec = function() {
++ return{optype:"UpdateMetadata", memberid:memberid, timestamp:timestamp, setProperties:setProperties, removedProperties:removedProperties}
+ }
- init()
+};
- gui.DirectTextStyler.textStylingChanged = "textStyling/changed";
- (function() {
- return gui.DirectTextStyler
- })();
+/*
+
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.EventNotifier");
- runtime.loadClass("core.Utils");
- runtime.loadClass("odf.OdfUtils");
- runtime.loadClass("ops.OpAddStyle");
- runtime.loadClass("ops.OpSetParagraphStyle");
- runtime.loadClass("gui.StyleHelper");
- gui.DirectParagraphStyler = function DirectParagraphStyler(session, inputMemberId, objectNameGenerator) {
- var odtDocument = session.getOdtDocument(), utils = new core.Utils, odfUtils = new odf.OdfUtils, styleHelper = new gui.StyleHelper(odtDocument.getFormatting()), eventNotifier = new core.EventNotifier([gui.DirectParagraphStyler.paragraphStylingChanged]), isAlignedLeftValue, isAlignedCenterValue, isAlignedRightValue, isAlignedJustifiedValue;
- function updatedCachedValues() {
- var cursor = odtDocument.getCursor(inputMemberId), range = cursor && cursor.getSelectedRange(), diffMap;
- function noteChange(oldValue, newValue, id) {
- if(oldValue !== newValue) {
- if(diffMap === undefined) {
- diffMap = {}
- }
- diffMap[id] = newValue
- }
- return newValue
- }
- isAlignedLeftValue = noteChange(isAlignedLeftValue, range ? styleHelper.isAlignedLeft(range) : false, "isAlignedLeft");
- isAlignedCenterValue = noteChange(isAlignedCenterValue, range ? styleHelper.isAlignedCenter(range) : false, "isAlignedCenter");
- isAlignedRightValue = noteChange(isAlignedRightValue, range ? styleHelper.isAlignedRight(range) : false, "isAlignedRight");
- isAlignedJustifiedValue = noteChange(isAlignedJustifiedValue, range ? styleHelper.isAlignedJustified(range) : false, "isAlignedJustified");
- if(diffMap) {
- eventNotifier.emit(gui.DirectParagraphStyler.paragraphStylingChanged, diffMap)
- }
- }
- function onCursorAdded(cursor) {
- if(cursor.getMemberId() === inputMemberId) {
- updatedCachedValues()
- }
- }
- function onCursorRemoved(memberId) {
- if(memberId === inputMemberId) {
- updatedCachedValues()
- }
- }
- function onCursorMoved(cursor) {
- if(cursor.getMemberId() === inputMemberId) {
- updatedCachedValues()
- }
- }
- function onParagraphStyleModified() {
- updatedCachedValues()
- }
- function onParagraphChanged(args) {
- var cursor = odtDocument.getCursor(inputMemberId);
- if(cursor && odtDocument.getParagraphElement(cursor.getNode()) === args.paragraphElement) {
- updatedCachedValues()
++runtime.loadClass("odf.Namespaces");
++ops.OpUpdateParagraphStyle = function OpUpdateParagraphStyle() {
++ var memberid, timestamp, styleName, setProperties, removedProperties, paragraphPropertiesName = "style:paragraph-properties", textPropertiesName = "style:text-properties", stylens = odf.Namespaces.stylens;
++ function removedAttributesFromStyleNode(node, removedAttributeNames) {
++ var i, attributeNameParts, attributeNameList = removedAttributeNames ? removedAttributeNames.split(",") : [];
++ for(i = 0;i < attributeNameList.length;i += 1) {
++ attributeNameParts = attributeNameList[i].split(":");
++ node.removeAttributeNS(odf.Namespaces.lookupNamespaceURI(attributeNameParts[0]), attributeNameParts[1])
+ }
+ }
- this.isAlignedLeft = function() {
- return isAlignedLeftValue
- };
- this.isAlignedCenter = function() {
- return isAlignedCenterValue
- };
- this.isAlignedRight = function() {
- return isAlignedRightValue
- };
- this.isAlignedJustified = function() {
- return isAlignedJustifiedValue
- };
- function applyParagraphDirectStyling(applyDirectStyling) {
- var range = odtDocument.getCursor(inputMemberId).getSelectedRange(), position = odtDocument.getCursorPosition(inputMemberId), paragraphs = odfUtils.getParagraphElements(range), formatting = odtDocument.getFormatting();
- paragraphs.forEach(function(paragraph) {
- var paragraphStartPoint = position + odtDocument.getDistanceFromCursor(inputMemberId, paragraph, 0), paragraphStyleName = paragraph.getAttributeNS(odf.Namespaces.textns, "style-name"), newParagraphStyleName = objectNameGenerator.generateStyleName(), opAddStyle, opSetParagraphStyle, paragraphProperties;
- paragraphStartPoint += 1;
- if(paragraphStyleName) {
- paragraphProperties = formatting.createDerivedStyleObject(paragraphStyleName, "paragraph", {})
- }
- paragraphProperties = applyDirectStyling(paragraphProperties || {});
- opAddStyle = new ops.OpAddStyle;
- opAddStyle.init({memberid:inputMemberId, styleName:newParagraphStyleName, styleFamily:"paragraph", isAutomaticStyle:true, setProperties:paragraphProperties});
- opSetParagraphStyle = new ops.OpSetParagraphStyle;
- opSetParagraphStyle.init({memberid:inputMemberId, styleName:newParagraphStyleName, position:paragraphStartPoint});
- session.enqueue([opAddStyle, opSetParagraphStyle])
- })
- }
- function applySimpleParagraphDirectStyling(styleOverrides) {
- applyParagraphDirectStyling(function(paragraphStyle) {
- return utils.mergeObjects(paragraphStyle, styleOverrides)
- })
- }
- function alignParagraph(alignment) {
- applySimpleParagraphDirectStyling({"style:paragraph-properties":{"fo:text-align":alignment}})
- }
- this.alignParagraphLeft = function() {
- alignParagraph("left");
- return true
- };
- this.alignParagraphCenter = function() {
- alignParagraph("center");
- return true
- };
- this.alignParagraphRight = function() {
- alignParagraph("right");
- return true
- };
- this.alignParagraphJustified = function() {
- alignParagraph("justify");
- return true
++ this.init = function(data) {
++ memberid = data.memberid;
++ timestamp = data.timestamp;
++ styleName = data.styleName;
++ setProperties = data.setProperties;
++ removedProperties = data.removedProperties
+ };
- function modifyParagraphIndent(direction, paragraphStyle) {
- var tabStopDistance = odtDocument.getFormatting().getDefaultTabStopDistance(), paragraphProperties = paragraphStyle["style:paragraph-properties"], indentValue = paragraphProperties && paragraphProperties["fo:margin-left"], indent = indentValue && odfUtils.parseLength(indentValue), newIndent;
- if(indent && indent.unit === tabStopDistance.unit) {
- newIndent = indent.value + direction * tabStopDistance.value + indent.unit
++ this.isEdit = true;
++ this.execute = function(odtDocument) {
++ var formatting = odtDocument.getFormatting(), styleNode, paragraphPropertiesNode, textPropertiesNode;
++ if(styleName !== "") {
++ styleNode = odtDocument.getParagraphStyleElement(styleName)
+ }else {
- newIndent = direction * tabStopDistance.value + tabStopDistance.unit
++ styleNode = formatting.getDefaultStyleElement("paragraph")
++ }
++ if(styleNode) {
++ paragraphPropertiesNode = styleNode.getElementsByTagNameNS(stylens, "paragraph-properties")[0];
++ textPropertiesNode = styleNode.getElementsByTagNameNS(stylens, "text-properties")[0];
++ if(setProperties) {
++ formatting.updateStyle(styleNode, setProperties)
++ }
++ if(removedProperties) {
++ if(removedProperties[paragraphPropertiesName]) {
++ removedAttributesFromStyleNode(paragraphPropertiesNode, removedProperties[paragraphPropertiesName].attributes);
++ if(paragraphPropertiesNode.attributes.length === 0) {
++ styleNode.removeChild(paragraphPropertiesNode)
++ }
++ }
++ if(removedProperties[textPropertiesName]) {
++ removedAttributesFromStyleNode(textPropertiesNode, removedProperties[textPropertiesName].attributes);
++ if(textPropertiesNode.attributes.length === 0) {
++ styleNode.removeChild(textPropertiesNode)
++ }
++ }
++ removedAttributesFromStyleNode(styleNode, removedProperties.attributes)
++ }
++ odtDocument.getOdfCanvas().refreshCSS();
++ odtDocument.emit(ops.OdtDocument.signalParagraphStyleModified, styleName);
++ odtDocument.getOdfCanvas().rerenderAnnotations();
++ return true
+ }
- return utils.mergeObjects(paragraphStyle, {"style:paragraph-properties":{"fo:margin-left":newIndent}})
- }
- this.indent = function() {
- applyParagraphDirectStyling(modifyParagraphIndent.bind(null, 1));
- return true
- };
- this.outdent = function() {
- applyParagraphDirectStyling(modifyParagraphIndent.bind(null, -1));
- return true
- };
- this.subscribe = function(eventid, cb) {
- eventNotifier.subscribe(eventid, cb)
- };
- this.unsubscribe = function(eventid, cb) {
- eventNotifier.unsubscribe(eventid, cb)
- };
- this.destroy = function(callback) {
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
- odtDocument.unsubscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified);
- odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged);
- callback()
++ return false
+ };
- function init() {
- odtDocument.subscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
- odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
- odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
- odtDocument.subscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified);
- odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged);
- updatedCachedValues()
++ this.spec = function() {
++ return{optype:"UpdateParagraphStyle", memberid:memberid, timestamp:timestamp, styleName:styleName, setProperties:setProperties, removedProperties:removedProperties}
+ }
- init()
+};
- gui.DirectParagraphStyler.paragraphStylingChanged = "paragraphStyling/changed";
- (function() {
- return gui.DirectParagraphStyler
- })();
++ops.OpUpdateParagraphStyle.Spec;
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- gui.KeyboardHandler = function KeyboardHandler() {
- var modifier = gui.KeyboardHandler.Modifier, defaultBinding = null, bindings = {};
- function getModifiers(e) {
- var modifiers = modifier.None;
- if(e.metaKey) {
- modifiers |= modifier.Meta
- }
- if(e.ctrlKey) {
- modifiers |= modifier.Ctrl
- }
- if(e.altKey) {
- modifiers |= modifier.Alt
- }
- if(e.shiftKey) {
- modifiers |= modifier.Shift
- }
- return modifiers
- }
- function getKeyCombo(keyCode, modifiers) {
- if(!modifiers) {
- modifiers = modifier.None
- }
- return keyCode + ":" + modifiers
- }
- this.setDefault = function(callback) {
- defaultBinding = callback
- };
- this.bind = function(keyCode, modifiers, callback) {
- var keyCombo = getKeyCombo(keyCode, modifiers);
- runtime.assert(bindings.hasOwnProperty(keyCombo) === false, "tried to overwrite the callback handler of key combo: " + keyCombo);
- bindings[keyCombo] = callback
- };
- this.unbind = function(keyCode, modifiers) {
- var keyCombo = getKeyCombo(keyCode, modifiers);
- delete bindings[keyCombo]
- };
- this.reset = function() {
- defaultBinding = null;
- bindings = {}
++runtime.loadClass("ops.OpAddMember");
++runtime.loadClass("ops.OpUpdateMember");
++runtime.loadClass("ops.OpRemoveMember");
++runtime.loadClass("ops.OpAddCursor");
++runtime.loadClass("ops.OpApplyDirectStyling");
++runtime.loadClass("ops.OpRemoveCursor");
++runtime.loadClass("ops.OpMoveCursor");
++runtime.loadClass("ops.OpSetBlob");
++runtime.loadClass("ops.OpRemoveBlob");
++runtime.loadClass("ops.OpInsertImage");
++runtime.loadClass("ops.OpInsertTable");
++runtime.loadClass("ops.OpInsertText");
++runtime.loadClass("ops.OpRemoveText");
++runtime.loadClass("ops.OpSplitParagraph");
++runtime.loadClass("ops.OpSetParagraphStyle");
++runtime.loadClass("ops.OpUpdateParagraphStyle");
++runtime.loadClass("ops.OpAddStyle");
++runtime.loadClass("ops.OpRemoveStyle");
++runtime.loadClass("ops.OpAddAnnotation");
++runtime.loadClass("ops.OpRemoveAnnotation");
++runtime.loadClass("ops.OpUpdateMetadata");
++ops.OperationFactory = function OperationFactory() {
++ var specs;
++ this.register = function(specName, specConstructor) {
++ specs[specName] = specConstructor
+ };
- this.handleEvent = function(e) {
- var keyCombo = getKeyCombo(e.keyCode, getModifiers(e)), callback = bindings[keyCombo], handled = false;
- if(callback) {
- handled = callback()
- }else {
- if(defaultBinding !== null) {
- handled = defaultBinding(e)
- }
- }
- if(handled) {
- if(e.preventDefault) {
- e.preventDefault()
- }else {
- e.returnValue = false
- }
++ this.create = function(spec) {
++ var op = null, specConstructor = specs[spec.optype];
++ if(specConstructor) {
++ op = specConstructor(spec);
++ op.init(spec)
+ }
- }
- };
- gui.KeyboardHandler.Modifier = {None:0, Meta:1, Ctrl:2, Alt:4, CtrlAlt:6, Shift:8, MetaShift:9, CtrlShift:10, AltShift:12};
- gui.KeyboardHandler.KeyCode = {Backspace:8, Tab:9, Clear:12, Enter:13, End:35, Home:36, Left:37, Up:38, Right:39, Down:40, Delete:46, A:65, B:66, C:67, D:68, E:69, F:70, G:71, H:72, I:73, J:74, K:75, L:76, M:77, N:78, O:79, P:80, Q:81, R:82, S:83, T:84, U:85, V:86, W:87, X:88, Y:89, Z:90};
- (function() {
- return gui.KeyboardHandler
- })();
- runtime.loadClass("odf.Namespaces");
- runtime.loadClass("odf.ObjectNameGenerator");
- gui.ImageManager = function ImageManager(session, inputMemberId, objectNameGenerator) {
- var cmPerPixel = 0.0264583333333334, fileExtensionByMimetype = {"image/gif":".gif", "image/jpeg":".jpg", "image/png":".png"}, textns = odf.Namespaces.textns, odtDocument = session.getOdtDocument(), formatting = odtDocument.getFormatting(), paragraphStyleToPageContentSizeMap = {};
- function createAddGraphicsStyleOp(name) {
- var op = new ops.OpAddStyle;
- op.init({memberid:inputMemberId, styleName:name, styleFamily:"graphic", isAutomaticStyle:false, setProperties:{"style:graphic-properties":{"text:anchor-type":"paragraph", "svg:x":"0cm", "svg:y":"0cm", "style:wrap":"dynamic", "style:number-wrapped-paragraphs":"no-limit", "style:wrap-contour":"false", "style:vertical-pos":"top", "style:vertical-rel":"paragraph", "style:horizontal-pos":"center", "style:horizontal-rel":"paragraph"}}});
- return op
- }
- function createAddFrameStyleOp(styleName, parentStyleName) {
- var op = new ops.OpAddStyle;
- op.init({memberid:inputMemberId, styleName:styleName, styleFamily:"graphic", isAutomaticStyle:true, setProperties:{"style:parent-style-name":parentStyleName, "style:graphic-properties":{"style:vertical-pos":"top", "style:vertical-rel":"baseline", "style:horizontal-pos":"center", "style:horizontal-rel":"paragraph", "fo:background-color":"transparent", "style:background-transparency":"100%", "style:shadow":"none", "style:mirror":"none", "fo:clip":"rect(0cm, 0cm, 0cm, 0cm)", "draw:lumi [...]
- "draw:contrast":"0%", "draw:red":"0%", "draw:green":"0%", "draw:blue":"0%", "draw:gamma":"100%", "draw:color-inversion":"false", "draw:image-opacity":"100%", "draw:color-mode":"standard"}}});
+ return op
- }
- function getFileExtension(mimetype) {
- mimetype = mimetype.toLowerCase();
- return fileExtensionByMimetype.hasOwnProperty(mimetype) ? fileExtensionByMimetype[mimetype] : null
- }
- function insertImageInternal(mimetype, content, widthInCm, heightInCm) {
- var graphicsStyleName = "Graphics", stylesElement = odtDocument.getOdfCanvas().odfContainer().rootElement.styles, fileExtension = getFileExtension(mimetype), fileName, graphicsStyleElement, frameStyleName, op, operations = [];
- runtime.assert(fileExtension !== null, "Image type is not supported: " + mimetype);
- fileName = "Pictures/" + objectNameGenerator.generateImageName() + fileExtension;
- op = new ops.OpSetBlob;
- op.init({memberid:inputMemberId, filename:fileName, mimetype:mimetype, content:content});
- operations.push(op);
- graphicsStyleElement = formatting.getStyleElement(graphicsStyleName, "graphic", [stylesElement]);
- if(!graphicsStyleElement) {
- op = createAddGraphicsStyleOp(graphicsStyleName);
- operations.push(op)
- }
- frameStyleName = objectNameGenerator.generateStyleName();
- op = createAddFrameStyleOp(frameStyleName, graphicsStyleName);
- operations.push(op);
- op = new ops.OpInsertImage;
- op.init({memberid:inputMemberId, position:odtDocument.getCursorPosition(inputMemberId), filename:fileName, frameWidth:widthInCm + "cm", frameHeight:heightInCm + "cm", frameStyleName:frameStyleName, frameName:objectNameGenerator.generateFrameName()});
- operations.push(op);
- session.enqueue(operations)
- }
- function trimmedSize(originalSize, pageContentSize) {
- var widthRatio = 1, heightRatio = 1, ratio;
- if(originalSize.width > pageContentSize.width) {
- widthRatio = pageContentSize.width / originalSize.width
- }
- if(originalSize.height > pageContentSize.height) {
- heightRatio = pageContentSize.height / originalSize.height
- }
- ratio = Math.min(widthRatio, heightRatio);
- return{width:originalSize.width * ratio, height:originalSize.height * ratio}
- }
- this.insertImage = function(mimetype, content, widthInPx, heightInPx) {
- var paragraphElement, styleName, pageContentSize, originalSize, newSize;
- runtime.assert(widthInPx > 0 && heightInPx > 0, "Both width and height of the image should be greater than 0px.");
- paragraphElement = odtDocument.getParagraphElement(odtDocument.getCursor(inputMemberId).getNode());
- styleName = paragraphElement.getAttributeNS(textns, "style-name");
- if(!paragraphStyleToPageContentSizeMap.hasOwnProperty(styleName)) {
- paragraphStyleToPageContentSizeMap[styleName] = formatting.getContentSize(styleName, "paragraph")
- }
- pageContentSize = paragraphStyleToPageContentSizeMap[styleName];
- originalSize = {width:widthInPx * cmPerPixel, height:heightInPx * cmPerPixel};
- newSize = trimmedSize(originalSize, pageContentSize);
- insertImageInternal(mimetype, content, newSize.width, newSize.height)
- }
- };
- runtime.loadClass("odf.Namespaces");
- gui.ImageSelector = function ImageSelector(odfCanvas) {
- var svgns = odf.Namespaces.svgns, imageSelectorId = "imageSelector", selectorBorderWidth = 1, squareClassNames = ["topLeft", "topRight", "bottomRight", "bottomLeft", "topMiddle", "rightMiddle", "bottomMiddle", "leftMiddle"], document = odfCanvas.getElement().ownerDocument, hasSelection = false;
- function createSelectorElement() {
- var sizerElement = odfCanvas.getSizer(), selectorElement, squareElement;
- selectorElement = document.createElement("div");
- selectorElement.id = "imageSelector";
- selectorElement.style.borderWidth = selectorBorderWidth + "px";
- sizerElement.appendChild(selectorElement);
- squareClassNames.forEach(function(className) {
- squareElement = document.createElement("div");
- squareElement.className = className;
- selectorElement.appendChild(squareElement)
- });
- return selectorElement
- }
- function getPosition(element, referenceElement) {
- var rect = element.getBoundingClientRect(), refRect = referenceElement.getBoundingClientRect(), zoomLevel = odfCanvas.getZoomLevel();
- return{left:(rect.left - refRect.left) / zoomLevel - selectorBorderWidth, top:(rect.top - refRect.top) / zoomLevel - selectorBorderWidth}
- }
- this.select = function(frameElement) {
- var selectorElement = document.getElementById(imageSelectorId), position;
- if(!selectorElement) {
- selectorElement = createSelectorElement()
- }
- hasSelection = true;
- position = getPosition(frameElement, (selectorElement.parentNode));
- selectorElement.style.display = "block";
- selectorElement.style.left = position.left + "px";
- selectorElement.style.top = position.top + "px";
- selectorElement.style.width = frameElement.getAttributeNS(svgns, "width");
- selectorElement.style.height = frameElement.getAttributeNS(svgns, "height")
- };
- this.clearSelection = function() {
- var selectorElement;
- if(hasSelection) {
- selectorElement = document.getElementById(imageSelectorId);
- if(selectorElement) {
- selectorElement.style.display = "none"
- }
- }
- hasSelection = false
+ };
- this.isSelectorElement = function(node) {
- var selectorElement = document.getElementById(imageSelectorId);
- if(!selectorElement) {
- return false
++ function constructor(OperationType) {
++ return function() {
++ return new OperationType
+ }
- return node === selectorElement || node.parentNode === selectorElement
+ }
++ function init() {
++ specs = {AddMember:constructor(ops.OpAddMember), UpdateMember:constructor(ops.OpUpdateMember), RemoveMember:constructor(ops.OpRemoveMember), AddCursor:constructor(ops.OpAddCursor), ApplyDirectStyling:constructor(ops.OpApplyDirectStyling), SetBlob:constructor(ops.OpSetBlob), RemoveBlob:constructor(ops.OpRemoveBlob), InsertImage:constructor(ops.OpInsertImage), InsertTable:constructor(ops.OpInsertTable), InsertText:constructor(ops.OpInsertText), RemoveText:constructor(ops.OpRemoveText) [...]
++ SetParagraphStyle:constructor(ops.OpSetParagraphStyle), UpdateParagraphStyle:constructor(ops.OpUpdateParagraphStyle), AddStyle:constructor(ops.OpAddStyle), RemoveStyle:constructor(ops.OpRemoveStyle), MoveCursor:constructor(ops.OpMoveCursor), RemoveCursor:constructor(ops.OpRemoveCursor), AddAnnotation:constructor(ops.OpAddAnnotation), RemoveAnnotation:constructor(ops.OpRemoveAnnotation), UpdateMetadata:constructor(ops.OpUpdateMetadata)}
++ }
++ init()
+};
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.PositionFilter");
- gui.TextManipulator = function TextManipulator(session, inputMemberId, directStyleOp) {
- var odtDocument = session.getOdtDocument(), FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT;
- function createOpRemoveSelection(selection) {
- var op = new ops.OpRemoveText;
- op.init({memberid:inputMemberId, position:selection.position, length:selection.length});
- return op
- }
- function toForwardSelection(selection) {
- if(selection.length < 0) {
- selection.position += selection.length;
- selection.length = -selection.length
- }
- return selection
- }
- this.enqueueParagraphSplittingOps = function() {
- var selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op, operations = [];
- if(selection.length > 0) {
- op = createOpRemoveSelection(selection);
- operations.push(op)
- }
- op = new ops.OpSplitParagraph;
- op.init({memberid:inputMemberId, position:selection.position});
- operations.push(op);
- session.enqueue(operations);
- return true
- };
- function hasPositionInDirection(cursorNode, forward) {
- var rootConstrainedFilter = new core.PositionFilterChain, iterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootElement(cursorNode)), nextPosition = (forward ? iterator.nextPosition : iterator.previousPosition);
- rootConstrainedFilter.addFilter("BaseFilter", odtDocument.getPositionFilter());
- rootConstrainedFilter.addFilter("RootFilter", odtDocument.createRootFilter(inputMemberId));
- iterator.setUnfilteredPosition(cursorNode, 0);
- while(nextPosition()) {
- if(rootConstrainedFilter.acceptPosition(iterator) === FILTER_ACCEPT) {
- return true
- }
- }
- return false
- }
- this.removeTextByBackspaceKey = function() {
- var cursor = odtDocument.getCursor(inputMemberId), selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op = null;
- if(selection.length === 0) {
- if(hasPositionInDirection(cursor.getNode(), false)) {
- op = new ops.OpRemoveText;
- op.init({memberid:inputMemberId, position:selection.position - 1, length:1});
- session.enqueue([op])
- }
- }else {
- op = createOpRemoveSelection(selection);
- session.enqueue([op])
- }
- return op !== null
- };
- this.removeTextByDeleteKey = function() {
- var cursor = odtDocument.getCursor(inputMemberId), selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op = null;
- if(selection.length === 0) {
- if(hasPositionInDirection(cursor.getNode(), true)) {
- op = new ops.OpRemoveText;
- op.init({memberid:inputMemberId, position:selection.position, length:1});
- session.enqueue([op])
- }
- }else {
- op = createOpRemoveSelection(selection);
- session.enqueue([op])
- }
- return op !== null
- };
- this.removeCurrentSelection = function() {
- var selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op;
- if(selection.length !== 0) {
- op = createOpRemoveSelection(selection);
- session.enqueue([op])
- }
- return true
- };
- function insertText(text) {
- var selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op, stylingOp, operations = [];
- if(selection.length > 0) {
- op = createOpRemoveSelection(selection);
- operations.push(op)
- }
- op = new ops.OpInsertText;
- op.init({memberid:inputMemberId, position:selection.position, text:text});
- operations.push(op);
- if(directStyleOp) {
- stylingOp = directStyleOp(selection.position, text.length);
- if(stylingOp) {
- operations.push(stylingOp)
- }
- }
- session.enqueue(operations)
- }
- this.insertText = insertText
++ops.OperationRouter = function OperationRouter() {
++};
++ops.OperationRouter.prototype.setOperationFactory = function(f) {
++};
++ops.OperationRouter.prototype.setPlaybackFunction = function(playback_func) {
++};
++ops.OperationRouter.prototype.push = function(operations) {
++};
++ops.OperationRouter.prototype.close = function(callback) {
++};
++ops.OperationRouter.prototype.subscribe = function(eventId, cb) {
++};
++ops.OperationRouter.prototype.unsubscribe = function(eventId, cb) {
++};
++ops.OperationRouter.prototype.hasLocalUnsyncedOps = function() {
++};
++ops.OperationRouter.prototype.hasSessionHostConnection = function() {
+};
- (function() {
- return gui.TextManipulator
- })();
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ This file is part of WebODF.
+
+ WebODF is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License (GNU AGPL)
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ WebODF is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ @licend
+
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.EventNotifier");
- runtime.loadClass("core.PositionFilter");
- runtime.loadClass("ops.OpAddAnnotation");
- runtime.loadClass("ops.OpRemoveAnnotation");
- runtime.loadClass("gui.SelectionMover");
- gui.AnnotationController = function AnnotationController(session, inputMemberId) {
- var odtDocument = session.getOdtDocument(), isAnnotatable = false, eventNotifier = new core.EventNotifier([gui.AnnotationController.annotatableChanged]), officens = odf.Namespaces.officens;
- function isWithinAnnotation(node, container) {
- while(node && node !== container) {
- if(node.namespaceURI === officens && node.localName === "annotation") {
- return true
- }
- node = node.parentNode
- }
- return false
- }
- function updatedCachedValues() {
- var cursor = odtDocument.getCursor(inputMemberId), cursorNode = cursor && cursor.getNode(), newIsAnnotatable = cursorNode && !isWithinAnnotation(cursorNode, odtDocument.getRootNode());
- if(newIsAnnotatable !== isAnnotatable) {
- isAnnotatable = newIsAnnotatable;
- eventNotifier.emit(gui.AnnotationController.annotatableChanged, isAnnotatable)
- }
- }
- function onCursorAdded(cursor) {
- if(cursor.getMemberId() === inputMemberId) {
- updatedCachedValues()
- }
- }
- function onCursorRemoved(memberId) {
- if(memberId === inputMemberId) {
- updatedCachedValues()
- }
- }
- function onCursorMoved(cursor) {
- if(cursor.getMemberId() === inputMemberId) {
- updatedCachedValues()
- }
- }
- this.isAnnotatable = function() {
- return isAnnotatable
- };
- this.addAnnotation = function() {
- var op = new ops.OpAddAnnotation, selection = odtDocument.getCursorSelection(inputMemberId), length = selection.length, position = selection.position;
- if(!isAnnotatable) {
- return
- }
- position = length >= 0 ? position : position + length;
- length = Math.abs(length);
- op.init({memberid:inputMemberId, position:position, length:length, name:inputMemberId + Date.now()});
- session.enqueue([op])
- };
- this.removeAnnotation = function(annotationNode) {
- var startStep, endStep, op, moveCursor;
- startStep = odtDocument.convertDomPointToCursorStep(annotationNode, 0) + 1;
- endStep = odtDocument.convertDomPointToCursorStep(annotationNode, annotationNode.childNodes.length);
- op = new ops.OpRemoveAnnotation;
- op.init({memberid:inputMemberId, position:startStep, length:endStep - startStep});
- moveCursor = new ops.OpMoveCursor;
- moveCursor.init({memberid:inputMemberId, position:startStep > 0 ? startStep - 1 : startStep, length:0});
- session.enqueue([op, moveCursor])
- };
- this.subscribe = function(eventid, cb) {
- eventNotifier.subscribe(eventid, cb)
- };
- this.unsubscribe = function(eventid, cb) {
- eventNotifier.unsubscribe(eventid, cb)
- };
- this.destroy = function(callback) {
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
- callback()
- };
- function init() {
- odtDocument.subscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
- odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
- odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
- updatedCachedValues()
- }
- init()
- };
- gui.AnnotationController.annotatableChanged = "annotatable/changed";
- (function() {
- return gui.AnnotationController
- })();
- gui.EventManager = function EventManager(odtDocument) {
- var canvasElement = odtDocument.getOdfCanvas().getElement(), window = runtime.getWindow(), bindToDirectHandler = {"beforecut":true, "beforepaste":true}, bindToWindow;
- function EventDelegate() {
- var self = this, recentEvents = [];
- this.handlers = [];
- this.isSubscribed = false;
- this.handleEvent = function(e) {
- if(recentEvents.indexOf(e) === -1) {
- recentEvents.push(e);
- self.handlers.forEach(function(handler) {
- handler(e)
- });
- runtime.setTimeout(function() {
- recentEvents.splice(recentEvents.indexOf(e), 1)
- }, 0)
- }
- }
- }
- function WindowScrollState(window) {
- var x = window.scrollX, y = window.scrollY;
- this.restore = function() {
- if(window.scrollX !== x || window.scrollY !== y) {
- window.scrollTo(x, y)
- }
- }
++ops.OperationTransformMatrix = function OperationTransformMatrix() {
++ function invertMoveCursorSpecRange(moveCursorSpec) {
++ moveCursorSpec.position = moveCursorSpec.position + moveCursorSpec.length;
++ moveCursorSpec.length *= -1
+ }
- function ElementScrollState(element) {
- var top = element.scrollTop, left = element.scrollLeft;
- this.restore = function() {
- if(element.scrollTop !== top || element.scrollLeft !== left) {
- element.scrollTop = top;
- element.scrollLeft = left
- }
++ function invertMoveCursorSpecRangeOnNegativeLength(moveCursorSpec) {
++ var isBackwards = moveCursorSpec.length < 0;
++ if(isBackwards) {
++ invertMoveCursorSpecRange(moveCursorSpec)
+ }
++ return isBackwards
+ }
- function listenEvent(eventTarget, eventType, eventHandler) {
- var onVariant = "on" + eventType, bound = false;
- if(eventTarget.attachEvent) {
- bound = eventTarget.attachEvent(onVariant, eventHandler)
- }
- if(!bound && eventTarget.addEventListener) {
- eventTarget.addEventListener(eventType, eventHandler, false);
- bound = true
- }
- if((!bound || bindToDirectHandler[eventType]) && eventTarget.hasOwnProperty(onVariant)) {
- eventTarget[onVariant] = eventHandler
++ function getStyleReferencingAttributes(setProperties, styleName) {
++ var attributes = [];
++ if(setProperties) {
++ ["style:parent-style-name", "style:next-style-name"].forEach(function(attributeName) {
++ if(setProperties[attributeName] === styleName) {
++ attributes.push(attributeName)
++ }
++ })
+ }
++ return attributes
+ }
- function removeEvent(eventTarget, eventType, eventHandler) {
- var onVariant = "on" + eventType;
- if(eventTarget.detachEvent) {
- eventTarget.detachEvent(onVariant, eventHandler)
- }
- if(eventTarget.removeEventListener) {
- eventTarget.removeEventListener(eventType, eventHandler, false)
- }
- if(eventTarget[onVariant] === eventHandler) {
- eventTarget[onVariant] = null
++ function dropStyleReferencingAttributes(setProperties, deletedStyleName) {
++ if(setProperties) {
++ ["style:parent-style-name", "style:next-style-name"].forEach(function(attributeName) {
++ if(setProperties[attributeName] === deletedStyleName) {
++ delete setProperties[attributeName]
++ }
++ })
+ }
+ }
- this.subscribe = function(eventName, handler) {
- var delegate = window && bindToWindow[eventName];
- if(delegate) {
- delegate.handlers.push(handler);
- if(!delegate.isSubscribed) {
- delegate.isSubscribed = true;
- listenEvent((window), eventName, delegate.handleEvent);
- listenEvent(canvasElement, eventName, delegate.handleEvent)
++ function cloneOpspec(opspec) {
++ var result = {};
++ Object.keys(opspec).forEach(function(key) {
++ if(typeof opspec[key] === "object") {
++ result[key] = cloneOpspec(opspec[key])
++ }else {
++ result[key] = opspec[key]
+ }
- }else {
- listenEvent(canvasElement, eventName, handler)
++ });
++ return result
++ }
++ function dropOverruledAndUnneededAttributes(minorSetProperties, minorRemovedProperties, majorSetProperties, majorRemovedProperties) {
++ var value, i, name, majorChanged = false, minorChanged = false, overrulingPropertyValue, removedPropertyNames, majorRemovedPropertyNames = majorRemovedProperties && majorRemovedProperties.attributes ? majorRemovedProperties.attributes.split(",") : [];
++ if(minorSetProperties && (majorSetProperties || majorRemovedPropertyNames.length > 0)) {
++ Object.keys(minorSetProperties).forEach(function(key) {
++ value = minorSetProperties[key];
++ if(typeof value !== "object") {
++ overrulingPropertyValue = majorSetProperties && majorSetProperties[key];
++ if(overrulingPropertyValue !== undefined) {
++ delete minorSetProperties[key];
++ minorChanged = true;
++ if(overrulingPropertyValue === value) {
++ delete majorSetProperties[key];
++ majorChanged = true
++ }
++ }else {
++ if(majorRemovedPropertyNames && majorRemovedPropertyNames.indexOf(key) !== -1) {
++ delete minorSetProperties[key];
++ minorChanged = true
++ }
++ }
++ }
++ })
+ }
- };
- this.unsubscribe = function(eventName, handler) {
- var delegate = window && bindToWindow[eventName], handlerIndex = delegate && delegate.handlers.indexOf(handler);
- if(delegate) {
- if(handlerIndex !== -1) {
- delegate.handlers.splice(handlerIndex, 1)
++ if(minorRemovedProperties && (minorRemovedProperties.attributes && (majorSetProperties || majorRemovedPropertyNames.length > 0))) {
++ removedPropertyNames = minorRemovedProperties.attributes.split(",");
++ for(i = 0;i < removedPropertyNames.length;i += 1) {
++ name = removedPropertyNames[i];
++ if(majorSetProperties && majorSetProperties[name] !== undefined || majorRemovedPropertyNames && majorRemovedPropertyNames.indexOf(name) !== -1) {
++ removedPropertyNames.splice(i, 1);
++ i -= 1;
++ minorChanged = true
++ }
++ }
++ if(removedPropertyNames.length > 0) {
++ minorRemovedProperties.attributes = removedPropertyNames.join(",")
++ }else {
++ delete minorRemovedProperties.attributes
+ }
- }else {
- removeEvent(canvasElement, eventName, handler)
+ }
- };
- function hasFocus() {
- var activeElement = odtDocument.getDOM().activeElement;
- return activeElement === canvasElement
++ return{majorChanged:majorChanged, minorChanged:minorChanged}
+ }
- this.hasFocus = hasFocus;
- function findScrollableParent(element) {
- while(element && (!element.scrollTop && !element.scrollLeft)) {
- element = (element.parentNode)
- }
- if(element) {
- return new ElementScrollState(element)
- }
- if(window) {
- return new WindowScrollState(window)
++ function hasProperties(properties) {
++ var key;
++ for(key in properties) {
++ if(properties.hasOwnProperty(key)) {
++ return true
++ }
+ }
- return null
++ return false
+ }
- this.focus = function() {
- var scrollParent;
- if(!hasFocus()) {
- scrollParent = findScrollableParent(canvasElement);
- canvasElement.focus();
- if(scrollParent) {
- scrollParent.restore()
++ function hasRemovedProperties(properties) {
++ var key;
++ for(key in properties) {
++ if(properties.hasOwnProperty(key)) {
++ if(key !== "attributes" || properties.attributes.length > 0) {
++ return true
++ }
+ }
+ }
- };
- function init() {
- bindToWindow = {"mousedown":new EventDelegate, "mouseup":new EventDelegate}
++ return false
+ }
- init()
- };
- runtime.loadClass("core.DomUtils");
- runtime.loadClass("core.Async");
- runtime.loadClass("core.ScheduledTask");
- runtime.loadClass("odf.OdfUtils");
- runtime.loadClass("odf.ObjectNameGenerator");
- runtime.loadClass("ops.OdtCursor");
- runtime.loadClass("ops.OpAddCursor");
- runtime.loadClass("ops.OpRemoveCursor");
- runtime.loadClass("gui.Clipboard");
- runtime.loadClass("gui.DirectTextStyler");
- runtime.loadClass("gui.DirectParagraphStyler");
- runtime.loadClass("gui.KeyboardHandler");
- runtime.loadClass("gui.ImageManager");
- runtime.loadClass("gui.ImageSelector");
- runtime.loadClass("gui.TextManipulator");
- runtime.loadClass("gui.AnnotationController");
- runtime.loadClass("gui.EventManager");
- runtime.loadClass("gui.PlainTextPasteboard");
- gui.SessionController = function() {
- var FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT;
- gui.SessionController = function SessionController(session, inputMemberId, shadowCursor, args) {
- var window = (runtime.getWindow()), odtDocument = session.getOdtDocument(), async = new core.Async, domUtils = new core.DomUtils, odfUtils = new odf.OdfUtils, clipboard = new gui.Clipboard, keyDownHandler = new gui.KeyboardHandler, keyPressHandler = new gui.KeyboardHandler, keyboardMovementsFilter = new core.PositionFilterChain, baseFilter = odtDocument.getPositionFilter(), clickStartedWithinContainer = false, objectNameGenerator = new odf.ObjectNameGenerator(odtDocument.getOdfCanva [...]
- inputMemberId), isMouseMoved = false, mouseDownRootFilter = null, undoManager = null, eventManager = new gui.EventManager(odtDocument), annotationController = new gui.AnnotationController(session, inputMemberId), directTextStyler = new gui.DirectTextStyler(session, inputMemberId), directParagraphStyler = args && args.directParagraphStylingEnabled ? new gui.DirectParagraphStyler(session, inputMemberId, objectNameGenerator) : null, createCursorStyleOp = (directTextStyler.createCursorS [...]
- new gui.TextManipulator(session, inputMemberId, createCursorStyleOp), imageManager = new gui.ImageManager(session, inputMemberId, objectNameGenerator), imageSelector = new gui.ImageSelector(odtDocument.getOdfCanvas()), shadowCursorIterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode()), drawShadowCursorTask, suppressFocusEvent = false, pasteHandler = new gui.PlainTextPasteboard(odtDocument, inputMemberId);
- runtime.assert(window !== null, "Expected to be run in an environment which has a global window, like a browser.");
- keyboardMovementsFilter.addFilter("BaseFilter", baseFilter);
- keyboardMovementsFilter.addFilter("RootFilter", odtDocument.createRootFilter(inputMemberId));
- function getTarget(e) {
- return e.target || e.srcElement
++ function dropOverruledAndUnneededProperties(minorOpspec, majorOpspec, propertiesName) {
++ var minorSP = minorOpspec.setProperties ? minorOpspec.setProperties[propertiesName] : null, minorRP = minorOpspec.removedProperties ? minorOpspec.removedProperties[propertiesName] : null, majorSP = majorOpspec.setProperties ? majorOpspec.setProperties[propertiesName] : null, majorRP = majorOpspec.removedProperties ? majorOpspec.removedProperties[propertiesName] : null, result;
++ result = dropOverruledAndUnneededAttributes(minorSP, minorRP, majorSP, majorRP);
++ if(minorSP && !hasProperties(minorSP)) {
++ delete minorOpspec.setProperties[propertiesName]
+ }
- function cancelEvent(event) {
- if(event.preventDefault) {
- event.preventDefault()
- }else {
- event.returnValue = false
- }
++ if(minorRP && !hasRemovedProperties(minorRP)) {
++ delete minorOpspec.removedProperties[propertiesName]
+ }
- function dummyHandler(e) {
- cancelEvent(e)
++ if(majorSP && !hasProperties(majorSP)) {
++ delete majorOpspec.setProperties[propertiesName]
+ }
- function createOpMoveCursor(position, length, selectionType) {
- var op = new ops.OpMoveCursor;
- op.init({memberid:inputMemberId, position:position, length:length || 0, selectionType:selectionType});
- return op
++ if(majorRP && !hasRemovedProperties(majorRP)) {
++ delete majorOpspec.removedProperties[propertiesName]
+ }
- function caretPositionFromPoint(x, y) {
- var doc = odtDocument.getDOM(), result;
- if(doc.caretRangeFromPoint) {
- result = doc.caretRangeFromPoint(x, y);
- return{container:result.startContainer, offset:result.startOffset}
- }
- if(doc.caretPositionFromPoint) {
- result = doc.caretPositionFromPoint(x, y);
- return{container:result.offsetNode, offset:result.offset}
++ return result
++ }
++ function transformAddStyleRemoveStyle(addStyleSpec, removeStyleSpec) {
++ var setAttributes, helperOpspec, addStyleSpecResult = [addStyleSpec], removeStyleSpecResult = [removeStyleSpec];
++ if(addStyleSpec.styleFamily === removeStyleSpec.styleFamily) {
++ setAttributes = getStyleReferencingAttributes(addStyleSpec.setProperties, removeStyleSpec.styleName);
++ if(setAttributes.length > 0) {
++ helperOpspec = {optype:"UpdateParagraphStyle", memberid:removeStyleSpec.memberid, timestamp:removeStyleSpec.timestamp, styleName:addStyleSpec.styleName, removedProperties:{attributes:setAttributes.join(",")}};
++ removeStyleSpecResult.unshift(helperOpspec)
+ }
- return null
++ dropStyleReferencingAttributes(addStyleSpec.setProperties, removeStyleSpec.styleName)
+ }
- function expandToWordBoundaries(selection) {
- var alphaNumeric = /[A-Za-z0-9]/, iterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode()), isForwardSelection = domUtils.comparePoints(selection.anchorNode, selection.anchorOffset, selection.focusNode, selection.focusOffset) > 0, startPoint, endPoint, currentNode, c;
- if(isForwardSelection) {
- startPoint = {node:selection.anchorNode, offset:selection.anchorOffset};
- endPoint = {node:selection.focusNode, offset:selection.focusOffset}
- }else {
- startPoint = {node:selection.focusNode, offset:selection.focusOffset};
- endPoint = {node:selection.anchorNode, offset:selection.anchorOffset}
++ return{opSpecsA:addStyleSpecResult, opSpecsB:removeStyleSpecResult}
++ }
++ function transformApplyDirectStylingApplyDirectStyling(applyDirectStylingSpecA, applyDirectStylingSpecB, hasAPriority) {
++ var majorSpec, minorSpec, majorSpecResult, minorSpecResult, majorSpecEnd, minorSpecEnd, dropResult, originalMajorSpec, originalMinorSpec, helperOpspecBefore, helperOpspecAfter, applyDirectStylingSpecAResult = [applyDirectStylingSpecA], applyDirectStylingSpecBResult = [applyDirectStylingSpecB];
++ if(!(applyDirectStylingSpecA.position + applyDirectStylingSpecA.length <= applyDirectStylingSpecB.position || applyDirectStylingSpecA.position >= applyDirectStylingSpecB.position + applyDirectStylingSpecB.length)) {
++ majorSpec = hasAPriority ? applyDirectStylingSpecA : applyDirectStylingSpecB;
++ minorSpec = hasAPriority ? applyDirectStylingSpecB : applyDirectStylingSpecA;
++ if(applyDirectStylingSpecA.position !== applyDirectStylingSpecB.position || applyDirectStylingSpecA.length !== applyDirectStylingSpecB.length) {
++ originalMajorSpec = cloneOpspec(majorSpec);
++ originalMinorSpec = cloneOpspec(minorSpec)
+ }
- iterator.setUnfilteredPosition(startPoint.node, startPoint.offset);
- while(iterator.previousPosition()) {
- currentNode = iterator.getCurrentNode();
- if(currentNode.nodeType === Node.TEXT_NODE) {
- c = currentNode.data[iterator.unfilteredDomOffset()];
- if(!alphaNumeric.test(c)) {
- break
++ dropResult = dropOverruledAndUnneededProperties(minorSpec, majorSpec, "style:text-properties");
++ if(dropResult.majorChanged || dropResult.minorChanged) {
++ majorSpecResult = [];
++ minorSpecResult = [];
++ majorSpecEnd = majorSpec.position + majorSpec.length;
++ minorSpecEnd = minorSpec.position + minorSpec.length;
++ if(minorSpec.position < majorSpec.position) {
++ if(dropResult.minorChanged) {
++ helperOpspecBefore = cloneOpspec((originalMinorSpec));
++ helperOpspecBefore.length = majorSpec.position - minorSpec.position;
++ minorSpecResult.push(helperOpspecBefore);
++ minorSpec.position = majorSpec.position;
++ minorSpec.length = minorSpecEnd - minorSpec.position
+ }
+ }else {
- if(!odfUtils.isTextSpan(currentNode)) {
- break
++ if(majorSpec.position < minorSpec.position) {
++ if(dropResult.majorChanged) {
++ helperOpspecBefore = cloneOpspec((originalMajorSpec));
++ helperOpspecBefore.length = minorSpec.position - majorSpec.position;
++ majorSpecResult.push(helperOpspecBefore);
++ majorSpec.position = minorSpec.position;
++ majorSpec.length = majorSpecEnd - majorSpec.position
++ }
+ }
+ }
- startPoint.node = iterator.container();
- startPoint.offset = iterator.unfilteredDomOffset()
- }
- iterator.setUnfilteredPosition(endPoint.node, endPoint.offset);
- do {
- currentNode = iterator.getCurrentNode();
- if(currentNode.nodeType === Node.TEXT_NODE) {
- c = currentNode.data[iterator.unfilteredDomOffset()];
- if(!alphaNumeric.test(c)) {
- break
++ if(minorSpecEnd > majorSpecEnd) {
++ if(dropResult.minorChanged) {
++ helperOpspecAfter = originalMinorSpec;
++ helperOpspecAfter.position = majorSpecEnd;
++ helperOpspecAfter.length = minorSpecEnd - majorSpecEnd;
++ minorSpecResult.push(helperOpspecAfter);
++ minorSpec.length = majorSpecEnd - minorSpec.position
++ }
++ }else {
++ if(majorSpecEnd > minorSpecEnd) {
++ if(dropResult.majorChanged) {
++ helperOpspecAfter = originalMajorSpec;
++ helperOpspecAfter.position = minorSpecEnd;
++ helperOpspecAfter.length = majorSpecEnd - minorSpecEnd;
++ majorSpecResult.push(helperOpspecAfter);
++ majorSpec.length = minorSpecEnd - majorSpec.position
++ }
+ }
++ }
++ if(majorSpec.setProperties && hasProperties(majorSpec.setProperties)) {
++ majorSpecResult.push(majorSpec)
++ }
++ if(minorSpec.setProperties && hasProperties(minorSpec.setProperties)) {
++ minorSpecResult.push(minorSpec)
++ }
++ if(hasAPriority) {
++ applyDirectStylingSpecAResult = majorSpecResult;
++ applyDirectStylingSpecBResult = minorSpecResult
+ }else {
- if(!odfUtils.isTextSpan(currentNode)) {
- break
- }
++ applyDirectStylingSpecAResult = minorSpecResult;
++ applyDirectStylingSpecBResult = majorSpecResult
+ }
- }while(iterator.nextPosition());
- endPoint.node = iterator.container();
- endPoint.offset = iterator.unfilteredDomOffset();
- if(isForwardSelection) {
- selection.anchorNode = startPoint.node;
- selection.anchorOffset = startPoint.offset;
- selection.focusNode = endPoint.node;
- selection.focusOffset = endPoint.offset
- }else {
- selection.focusNode = startPoint.node;
- selection.focusOffset = startPoint.offset;
- selection.anchorNode = endPoint.node;
- selection.anchorOffset = endPoint.offset
- }
- }
- function expandToParagraphBoundaries(selection) {
- var anchorParagraph = odtDocument.getParagraphElement(selection.anchorNode), focusParagraph = odtDocument.getParagraphElement(selection.focusNode);
- if(anchorParagraph) {
- selection.anchorNode = anchorParagraph;
- selection.anchorOffset = 0
- }
- if(focusParagraph) {
- selection.focusNode = focusParagraph;
- selection.focusOffset = focusParagraph.childNodes.length
+ }
+ }
- function selectImage(frameNode) {
- var stepsToAnchor = odtDocument.getDistanceFromCursor(inputMemberId, frameNode, 0), stepsToFocus = stepsToAnchor !== null ? stepsToAnchor + 1 : null, oldPosition, op;
- if(stepsToFocus || stepsToAnchor) {
- oldPosition = odtDocument.getCursorPosition(inputMemberId);
- op = createOpMoveCursor(oldPosition + stepsToAnchor, stepsToFocus - stepsToAnchor, ops.OdtCursor.RegionSelection);
- session.enqueue([op])
++ return{opSpecsA:applyDirectStylingSpecAResult, opSpecsB:applyDirectStylingSpecBResult}
++ }
++ function transformApplyDirectStylingInsertText(applyDirectStylingSpec, insertTextSpec) {
++ if(insertTextSpec.position <= applyDirectStylingSpec.position) {
++ applyDirectStylingSpec.position += insertTextSpec.text.length
++ }else {
++ if(insertTextSpec.position <= applyDirectStylingSpec.position + applyDirectStylingSpec.length) {
++ applyDirectStylingSpec.length += insertTextSpec.text.length
+ }
- eventManager.focus()
+ }
- function selectRange(selection, capturedDetails) {
- var canvasElement = odtDocument.getOdfCanvas().getElement(), validSelection, clickCount = capturedDetails.detail, caretPos, anchorNodeInsideCanvas, focusNodeInsideCanvas, existingSelection, newSelection, op;
- if(!selection) {
- return
- }
- if(!selection.anchorNode && !selection.focusNode) {
- caretPos = caretPositionFromPoint(capturedDetails.clientX, capturedDetails.clientY);
- if(!caretPos) {
- return
- }
- selection.anchorNode = (caretPos.container);
- selection.anchorOffset = caretPos.offset;
- selection.focusNode = selection.anchorNode;
- selection.focusOffset = selection.anchorOffset
- }
- runtime.assert(selection.anchorNode !== null && selection.focusNode !== null, "anchorNode or focusNode is null");
- validSelection = (selection);
- anchorNodeInsideCanvas = domUtils.containsNode(canvasElement, validSelection.anchorNode);
- focusNodeInsideCanvas = domUtils.containsNode(canvasElement, validSelection.focusNode);
- if(!anchorNodeInsideCanvas && !focusNodeInsideCanvas) {
- return
- }
- if(anchorNodeInsideCanvas && focusNodeInsideCanvas) {
- if(clickCount === 2) {
- expandToWordBoundaries(validSelection)
++ return{opSpecsA:[applyDirectStylingSpec], opSpecsB:[insertTextSpec]}
++ }
++ function transformApplyDirectStylingRemoveText(applyDirectStylingSpec, removeTextSpec) {
++ var applyDirectStylingSpecEnd = applyDirectStylingSpec.position + applyDirectStylingSpec.length, removeTextSpecEnd = removeTextSpec.position + removeTextSpec.length, applyDirectStylingSpecResult = [applyDirectStylingSpec], removeTextSpecResult = [removeTextSpec];
++ if(removeTextSpecEnd <= applyDirectStylingSpec.position) {
++ applyDirectStylingSpec.position -= removeTextSpec.length
++ }else {
++ if(removeTextSpec.position < applyDirectStylingSpecEnd) {
++ if(applyDirectStylingSpec.position < removeTextSpec.position) {
++ if(removeTextSpecEnd < applyDirectStylingSpecEnd) {
++ applyDirectStylingSpec.length -= removeTextSpec.length
++ }else {
++ applyDirectStylingSpec.length = removeTextSpec.position - applyDirectStylingSpec.position
++ }
+ }else {
- if(clickCount >= 3) {
- expandToParagraphBoundaries(validSelection)
++ applyDirectStylingSpec.position = removeTextSpec.position;
++ if(removeTextSpecEnd < applyDirectStylingSpecEnd) {
++ applyDirectStylingSpec.length = applyDirectStylingSpecEnd - removeTextSpecEnd
++ }else {
++ applyDirectStylingSpecResult = []
+ }
+ }
+ }
- newSelection = odtDocument.convertDomToCursorRange(validSelection.anchorNode, validSelection.anchorOffset, validSelection.focusNode, validSelection.focusOffset);
- existingSelection = odtDocument.getCursorSelection(inputMemberId);
- if(newSelection.position !== existingSelection.position || newSelection.length !== existingSelection.length) {
- op = createOpMoveCursor(newSelection.position, newSelection.length, ops.OdtCursor.RangeSelection);
- session.enqueue([op])
- }
- eventManager.focus()
+ }
- this.selectRange = selectRange;
- function extendCursorByAdjustment(lengthAdjust) {
- var selection = odtDocument.getCursorSelection(inputMemberId), stepCounter = odtDocument.getCursor(inputMemberId).getStepCounter(), newLength;
- if(lengthAdjust !== 0) {
- lengthAdjust = lengthAdjust > 0 ? stepCounter.convertForwardStepsBetweenFilters(lengthAdjust, keyboardMovementsFilter, baseFilter) : -stepCounter.convertBackwardStepsBetweenFilters(-lengthAdjust, keyboardMovementsFilter, baseFilter);
- newLength = selection.length + lengthAdjust;
- session.enqueue([createOpMoveCursor(selection.position, newLength)])
++ return{opSpecsA:applyDirectStylingSpecResult, opSpecsB:removeTextSpecResult}
++ }
++ function transformApplyDirectStylingSplitParagraph(applyDirectStylingSpec, splitParagraphSpec) {
++ if(splitParagraphSpec.position < applyDirectStylingSpec.position) {
++ applyDirectStylingSpec.position += 1
++ }else {
++ if(splitParagraphSpec.position < applyDirectStylingSpec.position + applyDirectStylingSpec.length) {
++ applyDirectStylingSpec.length += 1
+ }
+ }
- function moveCursorByAdjustment(positionAdjust) {
- var position = odtDocument.getCursorPosition(inputMemberId), stepCounter = odtDocument.getCursor(inputMemberId).getStepCounter();
- if(positionAdjust !== 0) {
- positionAdjust = positionAdjust > 0 ? stepCounter.convertForwardStepsBetweenFilters(positionAdjust, keyboardMovementsFilter, baseFilter) : -stepCounter.convertBackwardStepsBetweenFilters(-positionAdjust, keyboardMovementsFilter, baseFilter);
- position = position + positionAdjust;
- session.enqueue([createOpMoveCursor(position, 0)])
++ return{opSpecsA:[applyDirectStylingSpec], opSpecsB:[splitParagraphSpec]}
++ }
++ function transformInsertTextInsertText(insertTextSpecA, insertTextSpecB, hasAPriority) {
++ if(insertTextSpecA.position < insertTextSpecB.position) {
++ insertTextSpecB.position += insertTextSpecA.text.length
++ }else {
++ if(insertTextSpecA.position > insertTextSpecB.position) {
++ insertTextSpecA.position += insertTextSpecB.text.length
++ }else {
++ if(hasAPriority) {
++ insertTextSpecB.position += insertTextSpecA.text.length
++ }else {
++ insertTextSpecA.position += insertTextSpecB.text.length
++ }
++ return null
+ }
+ }
- function moveCursorToLeft() {
- moveCursorByAdjustment(-1);
- return true
- }
- this.moveCursorToLeft = moveCursorToLeft;
- function moveCursorToRight() {
- moveCursorByAdjustment(1);
- return true
- }
- function extendSelectionToLeft() {
- extendCursorByAdjustment(-1);
- return true
++ return{opSpecsA:[insertTextSpecA], opSpecsB:[insertTextSpecB]}
++ }
++ function transformInsertTextMoveCursor(insertTextSpec, moveCursorSpec) {
++ var isMoveCursorSpecRangeInverted = invertMoveCursorSpecRangeOnNegativeLength(moveCursorSpec);
++ if(insertTextSpec.position < moveCursorSpec.position) {
++ moveCursorSpec.position += insertTextSpec.text.length
++ }else {
++ if(insertTextSpec.position < moveCursorSpec.position + moveCursorSpec.length) {
++ moveCursorSpec.length += insertTextSpec.text.length
++ }
+ }
- function extendSelectionToRight() {
- extendCursorByAdjustment(1);
- return true
++ if(isMoveCursorSpecRangeInverted) {
++ invertMoveCursorSpecRange(moveCursorSpec)
+ }
- function moveCursorByLine(direction, extend) {
- var paragraphNode = odtDocument.getParagraphElement(odtDocument.getCursor(inputMemberId).getNode()), steps;
- runtime.assert(Boolean(paragraphNode), "SessionController: Cursor outside paragraph");
- steps = odtDocument.getCursor(inputMemberId).getStepCounter().countLinesSteps(direction, keyboardMovementsFilter);
- if(extend) {
- extendCursorByAdjustment(steps)
++ return{opSpecsA:[insertTextSpec], opSpecsB:[moveCursorSpec]}
++ }
++ function transformInsertTextRemoveText(insertTextSpec, removeTextSpec) {
++ var helperOpspec, removeTextSpecEnd = removeTextSpec.position + removeTextSpec.length, insertTextSpecResult = [insertTextSpec], removeTextSpecResult = [removeTextSpec];
++ if(removeTextSpecEnd <= insertTextSpec.position) {
++ insertTextSpec.position -= removeTextSpec.length
++ }else {
++ if(insertTextSpec.position <= removeTextSpec.position) {
++ removeTextSpec.position += insertTextSpec.text.length
+ }else {
- moveCursorByAdjustment(steps)
++ removeTextSpec.length = insertTextSpec.position - removeTextSpec.position;
++ helperOpspec = {optype:"RemoveText", memberid:removeTextSpec.memberid, timestamp:removeTextSpec.timestamp, position:insertTextSpec.position + insertTextSpec.text.length, length:removeTextSpecEnd - insertTextSpec.position};
++ removeTextSpecResult.unshift(helperOpspec);
++ insertTextSpec.position = removeTextSpec.position
+ }
+ }
- function moveCursorUp() {
- moveCursorByLine(-1, false);
- return true
- }
- function moveCursorDown() {
- moveCursorByLine(1, false);
- return true
- }
- function extendSelectionUp() {
- moveCursorByLine(-1, true);
- return true
- }
- function extendSelectionDown() {
- moveCursorByLine(1, true);
- return true
- }
- function moveCursorToLineBoundary(direction, extend) {
- var steps = odtDocument.getCursor(inputMemberId).getStepCounter().countStepsToLineBoundary(direction, keyboardMovementsFilter);
- if(extend) {
- extendCursorByAdjustment(steps)
++ return{opSpecsA:insertTextSpecResult, opSpecsB:removeTextSpecResult}
++ }
++ function transformInsertTextSplitParagraph(insertTextSpec, splitParagraphSpec, hasAPriority) {
++ if(insertTextSpec.position < splitParagraphSpec.position) {
++ splitParagraphSpec.position += insertTextSpec.text.length
++ }else {
++ if(insertTextSpec.position > splitParagraphSpec.position) {
++ insertTextSpec.position += 1
+ }else {
- moveCursorByAdjustment(steps)
++ if(hasAPriority) {
++ splitParagraphSpec.position += insertTextSpec.text.length
++ }else {
++ insertTextSpec.position += 1
++ }
++ return null
+ }
+ }
- function moveCursorToLineStart() {
- moveCursorToLineBoundary(-1, false);
- return true
- }
- function moveCursorToLineEnd() {
- moveCursorToLineBoundary(1, false);
- return true
- }
- function extendSelectionToLineStart() {
- moveCursorToLineBoundary(-1, true);
- return true
- }
- function extendSelectionToLineEnd() {
- moveCursorToLineBoundary(1, true);
- return true
- }
- function extendSelectionToParagraphStart() {
- var paragraphNode = odtDocument.getParagraphElement(odtDocument.getCursor(inputMemberId).getNode()), iterator, node, steps;
- runtime.assert(Boolean(paragraphNode), "SessionController: Cursor outside paragraph");
- steps = odtDocument.getDistanceFromCursor(inputMemberId, paragraphNode, 0);
- iterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode());
- iterator.setUnfilteredPosition(paragraphNode, 0);
- while(steps === 0 && iterator.previousPosition()) {
- node = iterator.getCurrentNode();
- if(odfUtils.isParagraph(node)) {
- steps = odtDocument.getDistanceFromCursor(inputMemberId, node, 0)
++ return{opSpecsA:[insertTextSpec], opSpecsB:[splitParagraphSpec]}
++ }
++ function transformUpdateParagraphStyleUpdateParagraphStyle(updateParagraphStyleSpecA, updateParagraphStyleSpecB, hasAPriority) {
++ var majorSpec, minorSpec, updateParagraphStyleSpecAResult = [updateParagraphStyleSpecA], updateParagraphStyleSpecBResult = [updateParagraphStyleSpecB];
++ if(updateParagraphStyleSpecA.styleName === updateParagraphStyleSpecB.styleName) {
++ majorSpec = hasAPriority ? updateParagraphStyleSpecA : updateParagraphStyleSpecB;
++ minorSpec = hasAPriority ? updateParagraphStyleSpecB : updateParagraphStyleSpecA;
++ dropOverruledAndUnneededProperties(minorSpec, majorSpec, "style:paragraph-properties");
++ dropOverruledAndUnneededProperties(minorSpec, majorSpec, "style:text-properties");
++ dropOverruledAndUnneededAttributes(minorSpec.setProperties || null, minorSpec.removedProperties || null, majorSpec.setProperties || null, majorSpec.removedProperties || null);
++ if(!(majorSpec.setProperties && hasProperties(majorSpec.setProperties)) && !(majorSpec.removedProperties && hasRemovedProperties(majorSpec.removedProperties))) {
++ if(hasAPriority) {
++ updateParagraphStyleSpecAResult = []
++ }else {
++ updateParagraphStyleSpecBResult = []
+ }
+ }
- extendCursorByAdjustment(steps);
- return true
- }
- function extendSelectionToParagraphEnd() {
- var paragraphNode = odtDocument.getParagraphElement(odtDocument.getCursor(inputMemberId).getNode()), iterator, node, steps;
- runtime.assert(Boolean(paragraphNode), "SessionController: Cursor outside paragraph");
- iterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode());
- iterator.moveToEndOfNode(paragraphNode);
- steps = odtDocument.getDistanceFromCursor(inputMemberId, iterator.container(), iterator.unfilteredDomOffset());
- while(steps === 0 && iterator.nextPosition()) {
- node = iterator.getCurrentNode();
- if(odfUtils.isParagraph(node)) {
- iterator.moveToEndOfNode(node);
- steps = odtDocument.getDistanceFromCursor(inputMemberId, iterator.container(), iterator.unfilteredDomOffset())
++ if(!(minorSpec.setProperties && hasProperties(minorSpec.setProperties)) && !(minorSpec.removedProperties && hasRemovedProperties(minorSpec.removedProperties))) {
++ if(hasAPriority) {
++ updateParagraphStyleSpecBResult = []
++ }else {
++ updateParagraphStyleSpecAResult = []
+ }
+ }
- extendCursorByAdjustment(steps);
- return true
+ }
- function moveCursorToDocumentBoundary(direction, extend) {
- var iterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode()), steps;
- if(direction > 0) {
- iterator.moveToEnd()
++ return{opSpecsA:updateParagraphStyleSpecAResult, opSpecsB:updateParagraphStyleSpecBResult}
++ }
++ function transformUpdateMetadataUpdateMetadata(updateMetadataSpecA, updateMetadataSpecB, hasAPriority) {
++ var majorSpec, minorSpec, updateMetadataSpecAResult = [updateMetadataSpecA], updateMetadataSpecBResult = [updateMetadataSpecB];
++ majorSpec = hasAPriority ? updateMetadataSpecA : updateMetadataSpecB;
++ minorSpec = hasAPriority ? updateMetadataSpecB : updateMetadataSpecA;
++ dropOverruledAndUnneededAttributes(minorSpec.setProperties || null, minorSpec.removedProperties || null, majorSpec.setProperties || null, majorSpec.removedProperties || null);
++ if(!(majorSpec.setProperties && hasProperties(majorSpec.setProperties)) && !(majorSpec.removedProperties && hasRemovedProperties(majorSpec.removedProperties))) {
++ if(hasAPriority) {
++ updateMetadataSpecAResult = []
++ }else {
++ updateMetadataSpecBResult = []
++ }
++ }
++ if(!(minorSpec.setProperties && hasProperties(minorSpec.setProperties)) && !(minorSpec.removedProperties && hasRemovedProperties(minorSpec.removedProperties))) {
++ if(hasAPriority) {
++ updateMetadataSpecBResult = []
++ }else {
++ updateMetadataSpecAResult = []
+ }
- steps = odtDocument.getDistanceFromCursor(inputMemberId, iterator.container(), iterator.unfilteredDomOffset());
- if(extend) {
- extendCursorByAdjustment(steps)
++ }
++ return{opSpecsA:updateMetadataSpecAResult, opSpecsB:updateMetadataSpecBResult}
++ }
++ function transformSplitParagraphSplitParagraph(splitParagraphSpecA, splitParagraphSpecB, hasAPriority) {
++ if(splitParagraphSpecA.position < splitParagraphSpecB.position) {
++ splitParagraphSpecB.position += 1
++ }else {
++ if(splitParagraphSpecA.position > splitParagraphSpecB.position) {
++ splitParagraphSpecA.position += 1
+ }else {
- moveCursorByAdjustment(steps)
++ if(splitParagraphSpecA.position === splitParagraphSpecB.position) {
++ if(hasAPriority) {
++ splitParagraphSpecB.position += 1
++ }else {
++ splitParagraphSpecA.position += 1
++ }
++ return null
++ }
+ }
+ }
- this.moveCursorToDocumentBoundary = moveCursorToDocumentBoundary;
- function moveCursorToDocumentStart() {
- moveCursorToDocumentBoundary(-1, false);
- return true
++ return{opSpecsA:[splitParagraphSpecA], opSpecsB:[splitParagraphSpecB]}
++ }
++ function transformMoveCursorRemoveCursor(moveCursorSpec, removeCursorSpec) {
++ var isSameCursorRemoved = moveCursorSpec.memberid === removeCursorSpec.memberid;
++ return{opSpecsA:isSameCursorRemoved ? [] : [moveCursorSpec], opSpecsB:[removeCursorSpec]}
++ }
++ function transformMoveCursorRemoveText(moveCursorSpec, removeTextSpec) {
++ var isMoveCursorSpecRangeInverted = invertMoveCursorSpecRangeOnNegativeLength(moveCursorSpec), moveCursorSpecEnd = moveCursorSpec.position + moveCursorSpec.length, removeTextSpecEnd = removeTextSpec.position + removeTextSpec.length;
++ if(removeTextSpecEnd <= moveCursorSpec.position) {
++ moveCursorSpec.position -= removeTextSpec.length
++ }else {
++ if(removeTextSpec.position < moveCursorSpecEnd) {
++ if(moveCursorSpec.position < removeTextSpec.position) {
++ if(removeTextSpecEnd < moveCursorSpecEnd) {
++ moveCursorSpec.length -= removeTextSpec.length
++ }else {
++ moveCursorSpec.length = removeTextSpec.position - moveCursorSpec.position
++ }
++ }else {
++ moveCursorSpec.position = removeTextSpec.position;
++ if(removeTextSpecEnd < moveCursorSpecEnd) {
++ moveCursorSpec.length = moveCursorSpecEnd - removeTextSpecEnd
++ }else {
++ moveCursorSpec.length = 0
++ }
++ }
++ }
+ }
- function moveCursorToDocumentEnd() {
- moveCursorToDocumentBoundary(1, false);
- return true
++ if(isMoveCursorSpecRangeInverted) {
++ invertMoveCursorSpecRange(moveCursorSpec)
+ }
- function extendSelectionToDocumentStart() {
- moveCursorToDocumentBoundary(-1, true);
- return true
++ return{opSpecsA:[moveCursorSpec], opSpecsB:[removeTextSpec]}
++ }
++ function transformMoveCursorSplitParagraph(moveCursorSpec, splitParagraphSpec) {
++ var isMoveCursorSpecRangeInverted = invertMoveCursorSpecRangeOnNegativeLength(moveCursorSpec);
++ if(splitParagraphSpec.position < moveCursorSpec.position) {
++ moveCursorSpec.position += 1
++ }else {
++ if(splitParagraphSpec.position < moveCursorSpec.position + moveCursorSpec.length) {
++ moveCursorSpec.length += 1
++ }
+ }
- function extendSelectionToDocumentEnd() {
- moveCursorToDocumentBoundary(1, true);
- return true
++ if(isMoveCursorSpecRangeInverted) {
++ invertMoveCursorSpecRange(moveCursorSpec)
+ }
- function extendSelectionToEntireDocument() {
- var rootNode = odtDocument.getRootNode(), lastWalkableStep = odtDocument.convertDomPointToCursorStep(rootNode, rootNode.childNodes.length);
- session.enqueue([createOpMoveCursor(0, lastWalkableStep)]);
- return true
++ return{opSpecsA:[moveCursorSpec], opSpecsB:[splitParagraphSpec]}
++ }
++ function transformRemoveCursorRemoveCursor(removeCursorSpecA, removeCursorSpecB) {
++ var isSameMemberid = removeCursorSpecA.memberid === removeCursorSpecB.memberid;
++ return{opSpecsA:isSameMemberid ? [] : [removeCursorSpecA], opSpecsB:isSameMemberid ? [] : [removeCursorSpecB]}
++ }
++ function transformRemoveStyleRemoveStyle(removeStyleSpecA, removeStyleSpecB) {
++ var isSameStyle = removeStyleSpecA.styleName === removeStyleSpecB.styleName && removeStyleSpecA.styleFamily === removeStyleSpecB.styleFamily;
++ return{opSpecsA:isSameStyle ? [] : [removeStyleSpecA], opSpecsB:isSameStyle ? [] : [removeStyleSpecB]}
++ }
++ function transformRemoveStyleSetParagraphStyle(removeStyleSpec, setParagraphStyleSpec) {
++ var helperOpspec, removeStyleSpecResult = [removeStyleSpec], setParagraphStyleSpecResult = [setParagraphStyleSpec];
++ if(removeStyleSpec.styleFamily === "paragraph" && removeStyleSpec.styleName === setParagraphStyleSpec.styleName) {
++ helperOpspec = {optype:"SetParagraphStyle", memberid:removeStyleSpec.memberid, timestamp:removeStyleSpec.timestamp, position:setParagraphStyleSpec.position, styleName:""};
++ removeStyleSpecResult.unshift(helperOpspec);
++ setParagraphStyleSpec.styleName = ""
+ }
- this.extendSelectionToEntireDocument = extendSelectionToEntireDocument;
- function maintainCursorSelection() {
- var cursor = odtDocument.getCursor(inputMemberId), selection = window.getSelection(), imageElement, range;
- if(cursor) {
- imageSelector.clearSelection();
- if(cursor.getSelectionType() === ops.OdtCursor.RegionSelection) {
- imageElement = odfUtils.getImageElements(cursor.getSelectedRange())[0];
- if(imageElement) {
- imageSelector.select((imageElement.parentNode))
- }
- }
- if(eventManager.hasFocus()) {
- range = cursor.getSelectedRange();
- if(selection.extend) {
- if(cursor.hasForwardSelection()) {
- selection.collapse(range.startContainer, range.startOffset);
- selection.extend(range.endContainer, range.endOffset)
++ return{opSpecsA:removeStyleSpecResult, opSpecsB:setParagraphStyleSpecResult}
++ }
++ function transformRemoveStyleUpdateParagraphStyle(removeStyleSpec, updateParagraphStyleSpec) {
++ var setAttributes, helperOpspec, removeStyleSpecResult = [removeStyleSpec], updateParagraphStyleSpecResult = [updateParagraphStyleSpec];
++ if(removeStyleSpec.styleFamily === "paragraph") {
++ setAttributes = getStyleReferencingAttributes(updateParagraphStyleSpec.setProperties, removeStyleSpec.styleName);
++ if(setAttributes.length > 0) {
++ helperOpspec = {optype:"UpdateParagraphStyle", memberid:removeStyleSpec.memberid, timestamp:removeStyleSpec.timestamp, styleName:updateParagraphStyleSpec.styleName, removedProperties:{attributes:setAttributes.join(",")}};
++ removeStyleSpecResult.unshift(helperOpspec)
++ }
++ if(removeStyleSpec.styleName === updateParagraphStyleSpec.styleName) {
++ updateParagraphStyleSpecResult = []
++ }else {
++ dropStyleReferencingAttributes(updateParagraphStyleSpec.setProperties, removeStyleSpec.styleName)
++ }
++ }
++ return{opSpecsA:removeStyleSpecResult, opSpecsB:updateParagraphStyleSpecResult}
++ }
++ function transformRemoveTextRemoveText(removeTextSpecA, removeTextSpecB) {
++ var removeTextSpecAEnd = removeTextSpecA.position + removeTextSpecA.length, removeTextSpecBEnd = removeTextSpecB.position + removeTextSpecB.length, removeTextSpecAResult = [removeTextSpecA], removeTextSpecBResult = [removeTextSpecB];
++ if(removeTextSpecBEnd <= removeTextSpecA.position) {
++ removeTextSpecA.position -= removeTextSpecB.length
++ }else {
++ if(removeTextSpecAEnd <= removeTextSpecB.position) {
++ removeTextSpecB.position -= removeTextSpecA.length
++ }else {
++ if(removeTextSpecB.position < removeTextSpecAEnd) {
++ if(removeTextSpecA.position < removeTextSpecB.position) {
++ if(removeTextSpecBEnd < removeTextSpecAEnd) {
++ removeTextSpecA.length = removeTextSpecA.length - removeTextSpecB.length
+ }else {
- selection.collapse(range.endContainer, range.endOffset);
- selection.extend(range.startContainer, range.startOffset)
++ removeTextSpecA.length = removeTextSpecB.position - removeTextSpecA.position
++ }
++ if(removeTextSpecAEnd < removeTextSpecBEnd) {
++ removeTextSpecB.position = removeTextSpecA.position;
++ removeTextSpecB.length = removeTextSpecBEnd - removeTextSpecAEnd
++ }else {
++ removeTextSpecBResult = []
+ }
+ }else {
- suppressFocusEvent = true;
- selection.removeAllRanges();
- selection.addRange(range.cloneRange());
- odtDocument.getOdfCanvas().getElement().setActive();
- runtime.setTimeout(function() {
- suppressFocusEvent = false
- }, 0)
++ if(removeTextSpecAEnd < removeTextSpecBEnd) {
++ removeTextSpecB.length = removeTextSpecB.length - removeTextSpecA.length
++ }else {
++ if(removeTextSpecB.position < removeTextSpecA.position) {
++ removeTextSpecB.length = removeTextSpecA.position - removeTextSpecB.position
++ }else {
++ removeTextSpecBResult = []
++ }
++ }
++ if(removeTextSpecBEnd < removeTextSpecAEnd) {
++ removeTextSpecA.position = removeTextSpecB.position;
++ removeTextSpecA.length = removeTextSpecAEnd - removeTextSpecBEnd
++ }else {
++ removeTextSpecAResult = []
++ }
+ }
+ }
- }else {
- imageSelector.clearSelection()
+ }
+ }
- function delayedMaintainCursor() {
- if(suppressFocusEvent === false) {
- runtime.setTimeout(maintainCursorSelection, 0)
- }
++ return{opSpecsA:removeTextSpecAResult, opSpecsB:removeTextSpecBResult}
++ }
++ function transformRemoveTextSplitParagraph(removeTextSpec, splitParagraphSpec) {
++ var removeTextSpecEnd = removeTextSpec.position + removeTextSpec.length, helperOpspec, removeTextSpecResult = [removeTextSpec], splitParagraphSpecResult = [splitParagraphSpec];
++ if(splitParagraphSpec.position <= removeTextSpec.position) {
++ removeTextSpec.position += 1
++ }else {
++ if(splitParagraphSpec.position < removeTextSpecEnd) {
++ removeTextSpec.length = splitParagraphSpec.position - removeTextSpec.position;
++ helperOpspec = {optype:"RemoveText", memberid:removeTextSpec.memberid, timestamp:removeTextSpec.timestamp, position:splitParagraphSpec.position + 1, length:removeTextSpecEnd - splitParagraphSpec.position};
++ removeTextSpecResult.unshift(helperOpspec)
++ }
++ }
++ if(removeTextSpec.position + removeTextSpec.length <= splitParagraphSpec.position) {
++ splitParagraphSpec.position -= removeTextSpec.length
++ }else {
++ if(removeTextSpec.position < splitParagraphSpec.position) {
++ splitParagraphSpec.position = removeTextSpec.position
++ }
++ }
++ return{opSpecsA:removeTextSpecResult, opSpecsB:splitParagraphSpecResult}
++ }
++ function passUnchanged(opSpecA, opSpecB) {
++ return{opSpecsA:[opSpecA], opSpecsB:[opSpecB]}
++ }
++ var transformations = {"AddCursor":{"AddCursor":passUnchanged, "AddMember":passUnchanged, "AddStyle":passUnchanged, "ApplyDirectStyling":passUnchanged, "InsertText":passUnchanged, "MoveCursor":passUnchanged, "RemoveCursor":passUnchanged, "RemoveMember":passUnchanged, "RemoveStyle":passUnchanged, "RemoveText":passUnchanged, "SetParagraphStyle":passUnchanged, "SplitParagraph":passUnchanged, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchange [...]
++ "InsertText":passUnchanged, "MoveCursor":passUnchanged, "RemoveCursor":passUnchanged, "RemoveStyle":passUnchanged, "RemoveText":passUnchanged, "SetParagraphStyle":passUnchanged, "SplitParagraph":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "AddStyle":{"AddStyle":passUnchanged, "ApplyDirectStyling":passUnchanged, "InsertText":passUnchanged, "MoveCursor":passUnchanged, "RemoveCursor":passUnchanged, "RemoveMember":passUnchanged, "RemoveStyle":tran [...]
++ "RemoveText":passUnchanged, "SetParagraphStyle":passUnchanged, "SplitParagraph":passUnchanged, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "ApplyDirectStyling":{"ApplyDirectStyling":transformApplyDirectStylingApplyDirectStyling, "InsertText":transformApplyDirectStylingInsertText, "MoveCursor":passUnchanged, "RemoveCursor":passUnchanged, "RemoveStyle":passUnchanged, "RemoveText":transformApplyDirectStylingRemoveText, "SetParagrap [...]
++ "SplitParagraph":transformApplyDirectStylingSplitParagraph, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "InsertText":{"InsertText":transformInsertTextInsertText, "MoveCursor":transformInsertTextMoveCursor, "RemoveCursor":passUnchanged, "RemoveMember":passUnchanged, "RemoveStyle":passUnchanged, "RemoveText":transformInsertTextRemoveText, "SplitParagraph":transformInsertTextSplitParagraph, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdatePa [...]
++ "MoveCursor":{"MoveCursor":passUnchanged, "RemoveCursor":transformMoveCursorRemoveCursor, "RemoveMember":passUnchanged, "RemoveStyle":passUnchanged, "RemoveText":transformMoveCursorRemoveText, "SetParagraphStyle":passUnchanged, "SplitParagraph":transformMoveCursorSplitParagraph, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "RemoveCursor":{"RemoveCursor":transformRemoveCursorRemoveCursor, "RemoveMember":passUnchanged, "RemoveStyle [...]
++ "RemoveText":passUnchanged, "SetParagraphStyle":passUnchanged, "SplitParagraph":passUnchanged, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "RemoveMember":{"RemoveStyle":passUnchanged, "RemoveText":passUnchanged, "SetParagraphStyle":passUnchanged, "SplitParagraph":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "RemoveStyle":{"RemoveStyle":transformRemoveStyleRemoveStyle, "RemoveText":passUnc [...]
++ "SplitParagraph":passUnchanged, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":transformRemoveStyleUpdateParagraphStyle}, "RemoveText":{"RemoveText":transformRemoveTextRemoveText, "SplitParagraph":transformRemoveTextSplitParagraph, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "SetParagraphStyle":{"UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchange [...]
++ "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "UpdateMember":{"UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "UpdateMetadata":{"UpdateMetadata":transformUpdateMetadataUpdateMetadata, "UpdateParagraphStyle":passUnchanged}, "UpdateParagraphStyle":{"UpdateParagraphStyle":transformUpdateParagraphStyleUpdateParagraphStyle}};
++ this.passUnchanged = passUnchanged;
++ this.extendTransformations = function(moreTransformations) {
++ Object.keys(moreTransformations).forEach(function(optypeA) {
++ var moreTransformationsOptypeAMap = moreTransformations[optypeA], optypeAMap, isExtendingOptypeAMap = transformations.hasOwnProperty(optypeA);
++ runtime.log((isExtendingOptypeAMap ? "Extending" : "Adding") + " map for optypeA: " + optypeA);
++ if(!isExtendingOptypeAMap) {
++ transformations[optypeA] = {}
++ }
++ optypeAMap = transformations[optypeA];
++ Object.keys(moreTransformationsOptypeAMap).forEach(function(optypeB) {
++ var isOverwritingOptypeBEntry = optypeAMap.hasOwnProperty(optypeB);
++ runtime.assert(optypeA <= optypeB, "Wrong order:" + optypeA + ", " + optypeB);
++ runtime.log(" " + (isOverwritingOptypeBEntry ? "Overwriting" : "Adding") + " entry for optypeB: " + optypeB);
++ optypeAMap[optypeB] = moreTransformationsOptypeAMap[optypeB]
++ })
++ })
++ };
++ this.transformOpspecVsOpspec = function(opSpecA, opSpecB) {
++ var isOptypeAAlphaNumericSmaller = opSpecA.optype <= opSpecB.optype, helper, transformationFunctionMap, transformationFunction, result;
++ runtime.log("Crosstransforming:");
++ runtime.log(runtime.toJson(opSpecA));
++ runtime.log(runtime.toJson(opSpecB));
++ if(!isOptypeAAlphaNumericSmaller) {
++ helper = opSpecA;
++ opSpecA = opSpecB;
++ opSpecB = helper
++ }
++ transformationFunctionMap = transformations[opSpecA.optype];
++ transformationFunction = transformationFunctionMap && transformationFunctionMap[opSpecB.optype];
++ if(transformationFunction) {
++ result = transformationFunction(opSpecA, opSpecB, !isOptypeAAlphaNumericSmaller);
++ if(!isOptypeAAlphaNumericSmaller && result !== null) {
++ result = {opSpecsA:result.opSpecsB, opSpecsB:result.opSpecsA}
++ }
++ }else {
++ result = null
++ }
++ runtime.log("result:");
++ if(result) {
++ runtime.log(runtime.toJson(result.opSpecsA));
++ runtime.log(runtime.toJson(result.opSpecsB))
++ }else {
++ runtime.log("null")
+ }
- function stringFromKeyPress(event) {
- if(event.which === null || event.which === undefined) {
- return String.fromCharCode(event.keyCode)
- }
- if(event.which !== 0 && event.charCode !== 0) {
- return String.fromCharCode(event.which)
++ return result
++ }
++};
++/*
++
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ This file is part of WebODF.
++
++ WebODF is free software: you can redistribute it and/or modify it
++ under the terms of the GNU Affero General Public License (GNU AGPL)
++ as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version.
++
++ WebODF is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU Affero General Public License for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
++ @licend
++
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++runtime.loadClass("ops.OperationFactory");
++runtime.loadClass("ops.OperationTransformMatrix");
++ops.OperationTransformer = function OperationTransformer() {
++ var operationFactory, operationTransformMatrix = new ops.OperationTransformMatrix;
++ function operations(opspecs) {
++ var ops = [];
++ opspecs.forEach(function(opspec) {
++ ops.push(operationFactory.create(opspec))
++ });
++ return ops
++ }
++ function transformOpVsOp(opSpecA, opSpecB) {
++ return operationTransformMatrix.transformOpspecVsOpspec(opSpecA, opSpecB)
++ }
++ function transformOpListVsOp(opSpecsA, opSpecB) {
++ var transformResult, transformListResult, transformedOpspecsA = [], transformedOpspecsB = [];
++ while(opSpecsA.length > 0 && opSpecB) {
++ transformResult = transformOpVsOp(opSpecsA.shift(), (opSpecB));
++ if(!transformResult) {
++ return null
+ }
- return null
- }
- function handleCut(e) {
- var cursor = odtDocument.getCursor(inputMemberId), selectedRange = cursor.getSelectedRange();
- if(selectedRange.collapsed) {
- return
++ transformedOpspecsA = transformedOpspecsA.concat(transformResult.opSpecsA);
++ if(transformResult.opSpecsB.length === 0) {
++ transformedOpspecsA = transformedOpspecsA.concat(opSpecsA);
++ opSpecB = null;
++ break
+ }
- if(clipboard.setDataFromRange(e, cursor.getSelectedRange())) {
- textManipulator.removeCurrentSelection()
- }else {
- runtime.log("Cut operation failed")
++ while(transformResult.opSpecsB.length > 1) {
++ transformListResult = transformOpListVsOp(opSpecsA, transformResult.opSpecsB.shift());
++ if(!transformListResult) {
++ return null
++ }
++ transformedOpspecsB = transformedOpspecsB.concat(transformListResult.opSpecsB);
++ opSpecsA = transformListResult.opSpecsA
+ }
++ opSpecB = transformResult.opSpecsB.pop()
+ }
- function handleBeforeCut() {
- var cursor = odtDocument.getCursor(inputMemberId), selectedRange = cursor.getSelectedRange();
- return selectedRange.collapsed !== false
++ if(opSpecB) {
++ transformedOpspecsB.push(opSpecB)
+ }
- function handleCopy(e) {
- var cursor = odtDocument.getCursor(inputMemberId), selectedRange = cursor.getSelectedRange();
- if(selectedRange.collapsed) {
- return
- }
- if(!clipboard.setDataFromRange(e, cursor.getSelectedRange())) {
- runtime.log("Cut operation failed")
++ return{opSpecsA:transformedOpspecsA, opSpecsB:transformedOpspecsB}
++ }
++ this.setOperationFactory = function(f) {
++ operationFactory = f
++ };
++ this.getOperationTransformMatrix = function() {
++ return operationTransformMatrix
++ };
++ this.transform = function(opSpecsA, opSpecsB) {
++ var transformResult, transformedOpspecsB = [];
++ while(opSpecsB.length > 0) {
++ transformResult = transformOpListVsOp(opSpecsA, opSpecsB.shift());
++ if(!transformResult) {
++ return null
+ }
++ opSpecsA = transformResult.opSpecsA;
++ transformedOpspecsB = transformedOpspecsB.concat(transformResult.opSpecsB)
+ }
- function handlePaste(e) {
- var plainText;
- if(window.clipboardData && window.clipboardData.getData) {
- plainText = window.clipboardData.getData("Text")
++ return{opsA:operations(opSpecsA), opsB:operations(transformedOpspecsB)}
++ }
++};
++/*
++
++ Copyright (C) 2012 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++ops.TrivialOperationRouter = function TrivialOperationRouter() {
++ var operationFactory, playbackFunction;
++ this.setOperationFactory = function(f) {
++ operationFactory = f
++ };
++ this.setPlaybackFunction = function(playback_func) {
++ playbackFunction = playback_func
++ };
++ this.push = function(operations) {
++ operations.forEach(function(op) {
++ var timedOp, opspec = op.spec();
++ opspec.timestamp = (new Date).getTime();
++ timedOp = operationFactory.create(opspec);
++ playbackFunction(timedOp)
++ })
++ };
++ this.close = function(cb) {
++ cb()
++ };
++ this.subscribe = function(eventId, cb) {
++ };
++ this.unsubscribe = function(eventId, cb) {
++ };
++ this.hasLocalUnsyncedOps = function() {
++ return false
++ };
++ this.hasSessionHostConnection = function() {
++ return true
++ }
++};
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++runtime.loadClass("ops.EditInfo");
++runtime.loadClass("gui.EditInfoHandle");
++gui.EditInfoMarker = function EditInfoMarker(editInfo, initialVisibility) {
++ var self = this, editInfoNode, handle, marker, editinfons = "urn:webodf:names:editinfo", decay1, decay2, decayTimeStep = 1E4;
++ function applyDecay(opacity, delay) {
++ return runtime.setTimeout(function() {
++ marker.style.opacity = opacity
++ }, delay)
++ }
++ function deleteDecay(timer) {
++ runtime.clearTimeout(timer)
++ }
++ function setLastAuthor(memberid) {
++ marker.setAttributeNS(editinfons, "editinfo:memberid", memberid)
++ }
++ this.addEdit = function(memberid, timestamp) {
++ var age = Date.now() - timestamp;
++ editInfo.addEdit(memberid, timestamp);
++ handle.setEdits(editInfo.getSortedEdits());
++ setLastAuthor(memberid);
++ if(decay1) {
++ deleteDecay(decay1)
++ }
++ if(decay2) {
++ deleteDecay(decay2)
++ }
++ if(age < decayTimeStep) {
++ applyDecay(1, 0);
++ decay1 = applyDecay(0.5, decayTimeStep - age);
++ decay2 = applyDecay(0.2, decayTimeStep * 2 - age)
++ }else {
++ if(age >= decayTimeStep && age < decayTimeStep * 2) {
++ applyDecay(0.5, 0);
++ decay2 = applyDecay(0.2, decayTimeStep * 2 - age)
+ }else {
- if(e.clipboardData && e.clipboardData.getData) {
- plainText = e.clipboardData.getData("text/plain")
- }
- }
- if(plainText) {
- textManipulator.removeCurrentSelection();
- session.enqueue(pasteHandler.createPasteOps(plainText));
- cancelEvent(e)
++ applyDecay(0.2, 0)
+ }
+ }
- function handleBeforePaste() {
- return false
++ };
++ this.getEdits = function() {
++ return editInfo.getEdits()
++ };
++ this.clearEdits = function() {
++ editInfo.clearEdits();
++ handle.setEdits([]);
++ if(marker.hasAttributeNS(editinfons, "editinfo:memberid")) {
++ marker.removeAttributeNS(editinfons, "editinfo:memberid")
+ }
- function updateUndoStack(op) {
- if(undoManager) {
- undoManager.onOperationExecuted(op)
++ };
++ this.getEditInfo = function() {
++ return editInfo
++ };
++ this.show = function() {
++ marker.style.display = "block"
++ };
++ this.hide = function() {
++ self.hideHandle();
++ marker.style.display = "none"
++ };
++ this.showHandle = function() {
++ handle.show()
++ };
++ this.hideHandle = function() {
++ handle.hide()
++ };
++ this.destroy = function(callback) {
++ editInfoNode.removeChild(marker);
++ handle.destroy(function(err) {
++ if(err) {
++ callback(err)
++ }else {
++ editInfo.destroy(callback)
+ }
++ })
++ };
++ function init() {
++ var dom = editInfo.getOdtDocument().getDOM(), htmlns = dom.documentElement.namespaceURI;
++ marker = dom.createElementNS(htmlns, "div");
++ marker.setAttribute("class", "editInfoMarker");
++ marker.onmouseover = function() {
++ self.showHandle()
++ };
++ marker.onmouseout = function() {
++ self.hideHandle()
++ };
++ editInfoNode = editInfo.getNode();
++ editInfoNode.appendChild(marker);
++ handle = new gui.EditInfoHandle(editInfoNode);
++ if(!initialVisibility) {
++ self.hide()
+ }
- function forwardUndoStackChange(e) {
- odtDocument.emit(ops.OdtDocument.signalUndoStackChanged, e)
++ }
++ init()
++};
++/*
++
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++gui.PlainTextPasteboard = function PlainTextPasteboard(odtDocument, inputMemberId) {
++ function createOp(op, data) {
++ op.init(data);
++ return op
++ }
++ this.createPasteOps = function(data) {
++ var originalCursorPosition = odtDocument.getCursorPosition(inputMemberId), cursorPosition = originalCursorPosition, operations = [], paragraphs;
++ paragraphs = data.replace(/\r/g, "").split("\n");
++ paragraphs.forEach(function(text) {
++ operations.push(createOp(new ops.OpSplitParagraph, {memberid:inputMemberId, position:cursorPosition}));
++ cursorPosition += 1;
++ operations.push(createOp(new ops.OpInsertText, {memberid:inputMemberId, position:cursorPosition, text:text}));
++ cursorPosition += text.length
++ });
++ operations.push(createOp(new ops.OpRemoveText, {memberid:inputMemberId, position:originalCursorPosition, length:1}));
++ return operations
++ }
++};
++runtime.loadClass("core.DomUtils");
++runtime.loadClass("odf.OdfUtils");
++runtime.loadClass("odf.OdfNodeFilter");
++runtime.loadClass("gui.SelectionMover");
++gui.SelectionView = function SelectionView(cursor) {
++ var odtDocument = cursor.getOdtDocument(), documentRoot, root, doc = odtDocument.getDOM(), overlayTop = doc.createElement("div"), overlayMiddle = doc.createElement("div"), overlayBottom = doc.createElement("div"), odfUtils = new odf.OdfUtils, domUtils = new core.DomUtils, isVisible = true, positionIterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode()), FILTER_ACCEPT = NodeFilter.FILTER_ACCEPT, FILTER_REJECT = NodeFilter.FILTER_REJECT;
++ function addOverlays() {
++ var newDocumentRoot = odtDocument.getRootNode();
++ if(documentRoot !== newDocumentRoot) {
++ documentRoot = newDocumentRoot;
++ root = (documentRoot.parentNode.parentNode.parentNode);
++ root.appendChild(overlayTop);
++ root.appendChild(overlayMiddle);
++ root.appendChild(overlayBottom)
+ }
- function undo() {
- if(undoManager) {
- undoManager.moveBackward(1);
- maintainCursorSelection();
- return true
++ }
++ function setRect(div, rect) {
++ div.style.left = rect.left + "px";
++ div.style.top = rect.top + "px";
++ div.style.width = rect.width + "px";
++ div.style.height = rect.height + "px"
++ }
++ function showOverlays(choice) {
++ var display;
++ isVisible = choice;
++ display = choice === true ? "block" : "none";
++ overlayTop.style.display = overlayMiddle.style.display = overlayBottom.style.display = display
++ }
++ function translateRect(rect) {
++ var rootRect = domUtils.getBoundingClientRect(root), zoomLevel = odtDocument.getOdfCanvas().getZoomLevel(), resultRect = {};
++ resultRect.top = domUtils.adaptRangeDifferenceToZoomLevel(rect.top - rootRect.top, zoomLevel);
++ resultRect.left = domUtils.adaptRangeDifferenceToZoomLevel(rect.left - rootRect.left, zoomLevel);
++ resultRect.bottom = domUtils.adaptRangeDifferenceToZoomLevel(rect.bottom - rootRect.top, zoomLevel);
++ resultRect.right = domUtils.adaptRangeDifferenceToZoomLevel(rect.right - rootRect.left, zoomLevel);
++ resultRect.width = domUtils.adaptRangeDifferenceToZoomLevel(rect.width, zoomLevel);
++ resultRect.height = domUtils.adaptRangeDifferenceToZoomLevel(rect.height, zoomLevel);
++ return resultRect
++ }
++ function isRangeVisible(range) {
++ var bcr = range.getBoundingClientRect();
++ return Boolean(bcr && bcr.height !== 0)
++ }
++ function lastVisibleRect(range, nodes) {
++ var nextNodeIndex = nodes.length - 1, node = nodes[nextNodeIndex], startOffset = range.endContainer === node ? range.endOffset : node.length || node.childNodes.length, endOffset = startOffset;
++ range.setStart(node, startOffset);
++ range.setEnd(node, endOffset);
++ while(!isRangeVisible(range)) {
++ if(node.nodeType === Node.ELEMENT_NODE && startOffset > 0) {
++ startOffset = 0
++ }else {
++ if(node.nodeType === Node.TEXT_NODE && startOffset > 0) {
++ startOffset -= 1
++ }else {
++ if(nodes[nextNodeIndex]) {
++ node = nodes[nextNodeIndex];
++ nextNodeIndex -= 1;
++ startOffset = endOffset = node.length || node.childNodes.length
++ }else {
++ return false
++ }
++ }
+ }
- return false
++ range.setStart(node, startOffset);
++ range.setEnd(node, endOffset)
+ }
- function redo() {
- if(undoManager) {
- undoManager.moveForward(1);
- maintainCursorSelection();
- return true
++ return true
++ }
++ function firstVisibleRect(range, nodes) {
++ var nextNodeIndex = 0, node = nodes[nextNodeIndex], startOffset = range.startContainer === node ? range.startOffset : 0, endOffset = startOffset;
++ range.setStart(node, startOffset);
++ range.setEnd(node, endOffset);
++ while(!isRangeVisible(range)) {
++ if(node.nodeType === Node.ELEMENT_NODE && endOffset < node.childNodes.length) {
++ endOffset = node.childNodes.length
++ }else {
++ if(node.nodeType === Node.TEXT_NODE && endOffset < node.length) {
++ endOffset += 1
++ }else {
++ if(nodes[nextNodeIndex]) {
++ node = nodes[nextNodeIndex];
++ nextNodeIndex += 1;
++ startOffset = endOffset = 0
++ }else {
++ return false
++ }
++ }
+ }
- return false
++ range.setStart(node, startOffset);
++ range.setEnd(node, endOffset)
+ }
- function filterMouseClicks(e) {
- var target = getTarget(e);
- clickStartedWithinContainer = target && domUtils.containsNode(odtDocument.getOdfCanvas().getElement(), target);
- if(clickStartedWithinContainer) {
- isMouseMoved = false;
- mouseDownRootFilter = odtDocument.createRootFilter(target)
- }
++ return true
++ }
++ function getExtremeRanges(range) {
++ var nodes = odfUtils.getTextElements(range, true, false), firstRange = (range.cloneRange()), lastRange = (range.cloneRange()), fillerRange = range.cloneRange();
++ if(!nodes.length) {
++ return null
+ }
- function cursorToSelection(cursor) {
- var range = cursor.getSelectedRange();
- if(cursor.hasForwardSelection()) {
- return{anchorNode:range.startContainer, anchorOffset:range.startOffset, focusNode:range.endContainer, focusOffset:range.endOffset}
- }
- return{anchorNode:range.endContainer, anchorOffset:range.endOffset, focusNode:range.startContainer, focusOffset:range.startOffset}
++ if(!firstVisibleRect(firstRange, nodes)) {
++ return null
+ }
- function mutableSelection(selection) {
- if(selection) {
- return{anchorNode:selection.anchorNode, anchorOffset:selection.anchorOffset, focusNode:selection.focusNode, focusOffset:selection.focusOffset}
- }
++ if(!lastVisibleRect(lastRange, nodes)) {
+ return null
+ }
- function handleMouseClickEvent(event) {
- var target = getTarget(event), eventDetails = {detail:event.detail, clientX:event.clientX, clientY:event.clientY, target:target};
- drawShadowCursorTask.processRequests();
- if(odfUtils.isImage(target) && odfUtils.isCharacterFrame(target.parentNode)) {
- selectImage(target.parentNode)
++ fillerRange.setStart(firstRange.startContainer, firstRange.startOffset);
++ fillerRange.setEnd(lastRange.endContainer, lastRange.endOffset);
++ return{firstRange:firstRange, lastRange:lastRange, fillerRange:fillerRange}
++ }
++ function getBoundingRect(rect1, rect2) {
++ var resultRect = {};
++ resultRect.top = Math.min(rect1.top, rect2.top);
++ resultRect.left = Math.min(rect1.left, rect2.left);
++ resultRect.right = Math.max(rect1.right, rect2.right);
++ resultRect.bottom = Math.max(rect1.bottom, rect2.bottom);
++ resultRect.width = resultRect.right - resultRect.left;
++ resultRect.height = resultRect.bottom - resultRect.top;
++ return resultRect
++ }
++ function checkAndGrowOrCreateRect(originalRect, newRect) {
++ if(newRect && (newRect.width > 0 && newRect.height > 0)) {
++ if(!originalRect) {
++ originalRect = newRect
+ }else {
- if(clickStartedWithinContainer && !imageSelector.isSelectorElement(target)) {
- if(isMouseMoved) {
- selectRange(cursorToSelection(shadowCursor), event)
- }else {
- runtime.setTimeout(function() {
- selectRange(mutableSelection(window.getSelection()), eventDetails)
- }, 0)
- }
- }
++ originalRect = getBoundingRect(originalRect, newRect)
+ }
- clickStartedWithinContainer = false;
- isMouseMoved = false
- }
- function handleContextMenu(e) {
- handleMouseClickEvent(e)
+ }
- function handleMouseUp(event) {
- var target = getTarget(event), annotationNode = null;
- if(target.className === "annotationRemoveButton") {
- annotationNode = domUtils.getElementsByTagNameNS(target.parentNode, odf.Namespaces.officens, "annotation")[0];
- annotationController.removeAnnotation(annotationNode)
- }else {
- handleMouseClickEvent(event)
++ return originalRect
++ }
++ function getFillerRect(fillerRange) {
++ var containerNode = fillerRange.commonAncestorContainer, firstNode = (fillerRange.startContainer), lastNode = (fillerRange.endContainer), firstOffset = fillerRange.startOffset, lastOffset = fillerRange.endOffset, currentNode, lastMeasuredNode, firstSibling, lastSibling, grownRect = null, currentRect, range = doc.createRange(), rootFilter, odfNodeFilter = new odf.OdfNodeFilter, treeWalker;
++ function acceptNode(node) {
++ positionIterator.setUnfilteredPosition(node, 0);
++ if(odfNodeFilter.acceptNode(node) === FILTER_ACCEPT && rootFilter.acceptPosition(positionIterator) === FILTER_ACCEPT) {
++ return FILTER_ACCEPT
+ }
++ return FILTER_REJECT
+ }
- function updateShadowCursor() {
- var selection = window.getSelection(), selectionRange, isForwardSelection;
- if(clickStartedWithinContainer && selection.rangeCount > 0) {
- isMouseMoved = true;
- imageSelector.clearSelection();
- shadowCursorIterator.setUnfilteredPosition((selection.focusNode), selection.focusOffset);
- if(mouseDownRootFilter.acceptPosition(shadowCursorIterator) === FILTER_ACCEPT) {
- selectionRange = selection.getRangeAt(0).cloneRange();
- isForwardSelection = selection.anchorNode === selectionRange.startContainer && selection.anchorOffset === selectionRange.startOffset;
- shadowCursor.setSelectedRange(selectionRange, isForwardSelection);
- odtDocument.emit(ops.OdtDocument.signalCursorMoved, shadowCursor)
- }
++ function getRectFromNodeAfterFiltering(node) {
++ var rect = null;
++ if(acceptNode(node) === FILTER_ACCEPT) {
++ rect = domUtils.getBoundingClientRect(node)
+ }
++ return rect
+ }
- this.startEditing = function() {
- var op;
- odtDocument.getOdfCanvas().getElement().classList.add("virtualSelections");
- eventManager.subscribe("keydown", keyDownHandler.handleEvent);
- eventManager.subscribe("keypress", keyPressHandler.handleEvent);
- eventManager.subscribe("keyup", dummyHandler);
- eventManager.subscribe("beforecut", handleBeforeCut);
- eventManager.subscribe("cut", handleCut);
- eventManager.subscribe("copy", handleCopy);
- eventManager.subscribe("beforepaste", handleBeforePaste);
- eventManager.subscribe("paste", handlePaste);
- eventManager.subscribe("mousedown", filterMouseClicks);
- eventManager.subscribe("mousemove", drawShadowCursorTask.trigger);
- eventManager.subscribe("mouseup", handleMouseUp);
- eventManager.subscribe("contextmenu", handleContextMenu);
- eventManager.subscribe("focus", delayedMaintainCursor);
- odtDocument.subscribe(ops.OdtDocument.signalOperationExecuted, maintainCursorSelection);
- odtDocument.subscribe(ops.OdtDocument.signalOperationExecuted, updateUndoStack);
- op = new ops.OpAddCursor;
- op.init({memberid:inputMemberId});
- session.enqueue([op]);
- if(undoManager) {
- undoManager.saveInitialState()
- }
- };
- this.endEditing = function() {
- var op;
- op = new ops.OpRemoveCursor;
- op.init({memberid:inputMemberId});
- session.enqueue([op]);
- if(undoManager) {
- undoManager.resetInitialState()
- }
- odtDocument.unsubscribe(ops.OdtDocument.signalOperationExecuted, updateUndoStack);
- odtDocument.unsubscribe(ops.OdtDocument.signalOperationExecuted, maintainCursorSelection);
- eventManager.unsubscribe("keydown", keyDownHandler.handleEvent);
- eventManager.unsubscribe("keypress", keyPressHandler.handleEvent);
- eventManager.unsubscribe("keyup", dummyHandler);
- eventManager.unsubscribe("cut", handleCut);
- eventManager.unsubscribe("beforecut", handleBeforeCut);
- eventManager.unsubscribe("copy", handleCopy);
- eventManager.unsubscribe("paste", handlePaste);
- eventManager.unsubscribe("beforepaste", handleBeforePaste);
- eventManager.unsubscribe("mousemove", drawShadowCursorTask.trigger);
- eventManager.unsubscribe("mousedown", filterMouseClicks);
- eventManager.unsubscribe("mouseup", handleMouseUp);
- eventManager.unsubscribe("contextmenu", handleContextMenu);
- eventManager.unsubscribe("focus", delayedMaintainCursor);
- odtDocument.getOdfCanvas().getElement().classList.remove("virtualSelections")
- };
- this.getInputMemberId = function() {
- return inputMemberId
- };
- this.getSession = function() {
- return session
- };
- this.setUndoManager = function(manager) {
- if(undoManager) {
- undoManager.unsubscribe(gui.UndoManager.signalUndoStackChanged, forwardUndoStackChange)
- }
- undoManager = manager;
- if(undoManager) {
- undoManager.setOdtDocument(odtDocument);
- undoManager.setPlaybackFunction(function(op) {
- op.execute(odtDocument)
- });
- undoManager.subscribe(gui.UndoManager.signalUndoStackChanged, forwardUndoStackChange)
- }
- };
- this.getUndoManager = function() {
- return undoManager
- };
- this.getAnnotationController = function() {
- return annotationController
- };
- this.getDirectTextStyler = function() {
- return directTextStyler
- };
- this.getDirectParagraphStyler = function() {
- return directParagraphStyler
- };
- this.getImageManager = function() {
- return imageManager
- };
- this.getTextManipulator = function() {
- return textManipulator
- };
- this.getEventManager = function() {
- return eventManager
- };
- this.getKeyboardHandlers = function() {
- return{keydown:keyDownHandler, keypress:keyPressHandler}
- };
- this.destroy = function(callback) {
- var destroyCallbacks = [drawShadowCursorTask.destroy, directTextStyler.destroy];
- if(directParagraphStyler) {
- destroyCallbacks.push(directParagraphStyler.destroy)
- }
- async.destroyAll(destroyCallbacks, callback)
- };
- function returnTrue(fn) {
- return function() {
- fn();
- return true
- }
++ if(firstNode === containerNode || lastNode === containerNode) {
++ range = fillerRange.cloneRange();
++ grownRect = range.getBoundingClientRect();
++ range.detach();
++ return grownRect
+ }
- function rangeSelectionOnly(fn) {
- return function(e) {
- var selectionType = odtDocument.getCursor(inputMemberId).getSelectionType();
- if(selectionType === ops.OdtCursor.RangeSelection) {
- return fn(e)
- }
- return true
- }
++ firstSibling = firstNode;
++ while(firstSibling.parentNode !== containerNode) {
++ firstSibling = firstSibling.parentNode
+ }
- function init() {
- var isMacOS = window.navigator.appVersion.toLowerCase().indexOf("mac") !== -1, modifier = gui.KeyboardHandler.Modifier, keyCode = gui.KeyboardHandler.KeyCode;
- drawShadowCursorTask = new core.ScheduledTask(updateShadowCursor, 0);
- keyDownHandler.bind(keyCode.Tab, modifier.None, rangeSelectionOnly(function() {
- textManipulator.insertText("\t");
- return true
- }));
- keyDownHandler.bind(keyCode.Left, modifier.None, rangeSelectionOnly(moveCursorToLeft));
- keyDownHandler.bind(keyCode.Right, modifier.None, rangeSelectionOnly(moveCursorToRight));
- keyDownHandler.bind(keyCode.Up, modifier.None, rangeSelectionOnly(moveCursorUp));
- keyDownHandler.bind(keyCode.Down, modifier.None, rangeSelectionOnly(moveCursorDown));
- keyDownHandler.bind(keyCode.Backspace, modifier.None, returnTrue(textManipulator.removeTextByBackspaceKey));
- keyDownHandler.bind(keyCode.Delete, modifier.None, textManipulator.removeTextByDeleteKey);
- keyDownHandler.bind(keyCode.Left, modifier.Shift, rangeSelectionOnly(extendSelectionToLeft));
- keyDownHandler.bind(keyCode.Right, modifier.Shift, rangeSelectionOnly(extendSelectionToRight));
- keyDownHandler.bind(keyCode.Up, modifier.Shift, rangeSelectionOnly(extendSelectionUp));
- keyDownHandler.bind(keyCode.Down, modifier.Shift, rangeSelectionOnly(extendSelectionDown));
- keyDownHandler.bind(keyCode.Home, modifier.None, rangeSelectionOnly(moveCursorToLineStart));
- keyDownHandler.bind(keyCode.End, modifier.None, rangeSelectionOnly(moveCursorToLineEnd));
- keyDownHandler.bind(keyCode.Home, modifier.Ctrl, rangeSelectionOnly(moveCursorToDocumentStart));
- keyDownHandler.bind(keyCode.End, modifier.Ctrl, rangeSelectionOnly(moveCursorToDocumentEnd));
- keyDownHandler.bind(keyCode.Home, modifier.Shift, rangeSelectionOnly(extendSelectionToLineStart));
- keyDownHandler.bind(keyCode.End, modifier.Shift, rangeSelectionOnly(extendSelectionToLineEnd));
- keyDownHandler.bind(keyCode.Up, modifier.CtrlShift, rangeSelectionOnly(extendSelectionToParagraphStart));
- keyDownHandler.bind(keyCode.Down, modifier.CtrlShift, rangeSelectionOnly(extendSelectionToParagraphEnd));
- keyDownHandler.bind(keyCode.Home, modifier.CtrlShift, rangeSelectionOnly(extendSelectionToDocumentStart));
- keyDownHandler.bind(keyCode.End, modifier.CtrlShift, rangeSelectionOnly(extendSelectionToDocumentEnd));
- if(isMacOS) {
- keyDownHandler.bind(keyCode.Clear, modifier.None, textManipulator.removeCurrentSelection);
- keyDownHandler.bind(keyCode.Left, modifier.Meta, rangeSelectionOnly(moveCursorToLineStart));
- keyDownHandler.bind(keyCode.Right, modifier.Meta, rangeSelectionOnly(moveCursorToLineEnd));
- keyDownHandler.bind(keyCode.Home, modifier.Meta, rangeSelectionOnly(moveCursorToDocumentStart));
- keyDownHandler.bind(keyCode.End, modifier.Meta, rangeSelectionOnly(moveCursorToDocumentEnd));
- keyDownHandler.bind(keyCode.Left, modifier.MetaShift, rangeSelectionOnly(extendSelectionToLineStart));
- keyDownHandler.bind(keyCode.Right, modifier.MetaShift, rangeSelectionOnly(extendSelectionToLineEnd));
- keyDownHandler.bind(keyCode.Up, modifier.AltShift, rangeSelectionOnly(extendSelectionToParagraphStart));
- keyDownHandler.bind(keyCode.Down, modifier.AltShift, rangeSelectionOnly(extendSelectionToParagraphEnd));
- keyDownHandler.bind(keyCode.Up, modifier.MetaShift, rangeSelectionOnly(extendSelectionToDocumentStart));
- keyDownHandler.bind(keyCode.Down, modifier.MetaShift, rangeSelectionOnly(extendSelectionToDocumentEnd));
- keyDownHandler.bind(keyCode.A, modifier.Meta, rangeSelectionOnly(extendSelectionToEntireDocument));
- keyDownHandler.bind(keyCode.B, modifier.Meta, rangeSelectionOnly(directTextStyler.toggleBold));
- keyDownHandler.bind(keyCode.I, modifier.Meta, rangeSelectionOnly(directTextStyler.toggleItalic));
- keyDownHandler.bind(keyCode.U, modifier.Meta, rangeSelectionOnly(directTextStyler.toggleUnderline));
- if(directParagraphStyler) {
- keyDownHandler.bind(keyCode.L, modifier.MetaShift, rangeSelectionOnly(directParagraphStyler.alignParagraphLeft));
- keyDownHandler.bind(keyCode.E, modifier.MetaShift, rangeSelectionOnly(directParagraphStyler.alignParagraphCenter));
- keyDownHandler.bind(keyCode.R, modifier.MetaShift, rangeSelectionOnly(directParagraphStyler.alignParagraphRight));
- keyDownHandler.bind(keyCode.J, modifier.MetaShift, rangeSelectionOnly(directParagraphStyler.alignParagraphJustified))
- }
- if(annotationController) {
- keyDownHandler.bind(keyCode.C, modifier.MetaShift, annotationController.addAnnotation)
- }
- keyDownHandler.bind(keyCode.Z, modifier.Meta, undo);
- keyDownHandler.bind(keyCode.Z, modifier.MetaShift, redo)
++ lastSibling = lastNode;
++ while(lastSibling.parentNode !== containerNode) {
++ lastSibling = lastSibling.parentNode
++ }
++ rootFilter = odtDocument.createRootFilter(firstNode);
++ currentNode = firstSibling.nextSibling;
++ while(currentNode && currentNode !== lastSibling) {
++ currentRect = getRectFromNodeAfterFiltering(currentNode);
++ grownRect = checkAndGrowOrCreateRect(grownRect, currentRect);
++ currentNode = currentNode.nextSibling
++ }
++ if(odfUtils.isParagraph(firstSibling)) {
++ grownRect = checkAndGrowOrCreateRect(grownRect, domUtils.getBoundingClientRect(firstSibling))
++ }else {
++ if(firstSibling.nodeType === Node.TEXT_NODE) {
++ currentNode = firstSibling;
++ range.setStart(currentNode, firstOffset);
++ range.setEnd(currentNode, currentNode === lastSibling ? lastOffset : currentNode.length);
++ currentRect = range.getBoundingClientRect();
++ grownRect = checkAndGrowOrCreateRect(grownRect, currentRect)
+ }else {
- keyDownHandler.bind(keyCode.A, modifier.Ctrl, rangeSelectionOnly(extendSelectionToEntireDocument));
- keyDownHandler.bind(keyCode.B, modifier.Ctrl, rangeSelectionOnly(directTextStyler.toggleBold));
- keyDownHandler.bind(keyCode.I, modifier.Ctrl, rangeSelectionOnly(directTextStyler.toggleItalic));
- keyDownHandler.bind(keyCode.U, modifier.Ctrl, rangeSelectionOnly(directTextStyler.toggleUnderline));
- if(directParagraphStyler) {
- keyDownHandler.bind(keyCode.L, modifier.CtrlShift, rangeSelectionOnly(directParagraphStyler.alignParagraphLeft));
- keyDownHandler.bind(keyCode.E, modifier.CtrlShift, rangeSelectionOnly(directParagraphStyler.alignParagraphCenter));
- keyDownHandler.bind(keyCode.R, modifier.CtrlShift, rangeSelectionOnly(directParagraphStyler.alignParagraphRight));
- keyDownHandler.bind(keyCode.J, modifier.CtrlShift, rangeSelectionOnly(directParagraphStyler.alignParagraphJustified))
- }
- if(annotationController) {
- keyDownHandler.bind(keyCode.C, modifier.CtrlAlt, annotationController.addAnnotation)
++ treeWalker = doc.createTreeWalker(firstSibling, NodeFilter.SHOW_TEXT, acceptNode, false);
++ currentNode = treeWalker.currentNode = firstNode;
++ while(currentNode && currentNode !== lastNode) {
++ range.setStart(currentNode, firstOffset);
++ range.setEnd(currentNode, currentNode.length);
++ currentRect = range.getBoundingClientRect();
++ grownRect = checkAndGrowOrCreateRect(grownRect, currentRect);
++ lastMeasuredNode = currentNode;
++ firstOffset = 0;
++ currentNode = treeWalker.nextNode()
+ }
- keyDownHandler.bind(keyCode.Z, modifier.Ctrl, undo);
- keyDownHandler.bind(keyCode.Z, modifier.CtrlShift, redo)
+ }
- keyPressHandler.setDefault(rangeSelectionOnly(function(e) {
- var text = stringFromKeyPress(e);
- if(text && !(e.altKey || (e.ctrlKey || e.metaKey))) {
- textManipulator.insertText(text);
- return true
++ }
++ if(!lastMeasuredNode) {
++ lastMeasuredNode = firstNode
++ }
++ if(odfUtils.isParagraph(lastSibling)) {
++ grownRect = checkAndGrowOrCreateRect(grownRect, domUtils.getBoundingClientRect(lastSibling))
++ }else {
++ if(lastSibling.nodeType === Node.TEXT_NODE) {
++ currentNode = lastSibling;
++ range.setStart(currentNode, currentNode === firstSibling ? firstOffset : 0);
++ range.setEnd(currentNode, lastOffset);
++ currentRect = range.getBoundingClientRect();
++ grownRect = checkAndGrowOrCreateRect(grownRect, currentRect)
++ }else {
++ treeWalker = doc.createTreeWalker(lastSibling, NodeFilter.SHOW_TEXT, acceptNode, false);
++ currentNode = treeWalker.currentNode = lastNode;
++ while(currentNode && currentNode !== lastMeasuredNode) {
++ range.setStart(currentNode, 0);
++ range.setEnd(currentNode, lastOffset);
++ currentRect = range.getBoundingClientRect();
++ grownRect = checkAndGrowOrCreateRect(grownRect, currentRect);
++ currentNode = treeWalker.previousNode();
++ if(currentNode) {
++ lastOffset = currentNode.length
++ }
+ }
- return false
- }));
- keyPressHandler.bind(keyCode.Enter, modifier.None, rangeSelectionOnly(textManipulator.enqueueParagraphSplittingOps))
++ }
+ }
- init()
++ return grownRect
++ }
++ function getCollapsedRectOfTextRange(range, useRightEdge) {
++ var clientRect = range.getBoundingClientRect(), collapsedRect = {};
++ collapsedRect.width = 0;
++ collapsedRect.top = clientRect.top;
++ collapsedRect.bottom = clientRect.bottom;
++ collapsedRect.height = clientRect.height;
++ collapsedRect.left = collapsedRect.right = useRightEdge ? clientRect.right : clientRect.left;
++ return collapsedRect
++ }
++ function repositionOverlays(selectedRange) {
++ var extremes = getExtremeRanges(selectedRange), firstRange, lastRange, fillerRange, firstRect, fillerRect, lastRect;
++ if(selectedRange.collapsed || !extremes) {
++ showOverlays(false)
++ }else {
++ showOverlays(true);
++ firstRange = extremes.firstRange;
++ lastRange = extremes.lastRange;
++ fillerRange = extremes.fillerRange;
++ firstRect = translateRect(getCollapsedRectOfTextRange(firstRange, false));
++ lastRect = translateRect(getCollapsedRectOfTextRange(lastRange, true));
++ fillerRect = getFillerRect(fillerRange);
++ if(!fillerRect) {
++ fillerRect = getBoundingRect(firstRect, lastRect)
++ }else {
++ fillerRect = translateRect(fillerRect)
++ }
++ setRect(overlayTop, {left:firstRect.left, top:firstRect.top, width:Math.max(0, fillerRect.width - (firstRect.left - fillerRect.left)), height:firstRect.height});
++ if(lastRect.top === firstRect.top || lastRect.bottom === firstRect.bottom) {
++ overlayMiddle.style.display = overlayBottom.style.display = "none"
++ }else {
++ setRect(overlayBottom, {left:fillerRect.left, top:lastRect.top, width:Math.max(0, lastRect.right - fillerRect.left), height:lastRect.height});
++ setRect(overlayMiddle, {left:fillerRect.left, top:firstRect.top + firstRect.height, width:Math.max(0, parseFloat(overlayTop.style.left) + parseFloat(overlayTop.style.width) - parseFloat(overlayBottom.style.left)), height:Math.max(0, lastRect.top - firstRect.bottom)})
++ }
++ firstRange.detach();
++ lastRange.detach();
++ fillerRange.detach()
++ }
++ }
++ function rerender() {
++ addOverlays();
++ if(cursor.getSelectionType() === ops.OdtCursor.RangeSelection) {
++ showOverlays(true);
++ repositionOverlays(cursor.getSelectedRange())
++ }else {
++ showOverlays(false)
++ }
++ }
++ this.rerender = rerender;
++ this.show = rerender;
++ this.hide = function() {
++ showOverlays(false)
+ };
- return gui.SessionController
- }();
++ this.visible = function() {
++ return isVisible
++ };
++ function handleCursorMove(movedCursor) {
++ if(movedCursor === cursor) {
++ rerender()
++ }
++ }
++ this.destroy = function(callback) {
++ root.removeChild(overlayTop);
++ root.removeChild(overlayMiddle);
++ root.removeChild(overlayBottom);
++ cursor.getOdtDocument().unsubscribe(ops.OdtDocument.signalCursorMoved, handleCursorMove);
++ callback()
++ };
++ function init() {
++ var editinfons = "urn:webodf:names:editinfo", memberid = cursor.getMemberId();
++ addOverlays();
++ overlayTop.setAttributeNS(editinfons, "editinfo:memberid", memberid);
++ overlayMiddle.setAttributeNS(editinfons, "editinfo:memberid", memberid);
++ overlayBottom.setAttributeNS(editinfons, "editinfo:memberid", memberid);
++ overlayTop.className = overlayMiddle.className = overlayBottom.className = "selectionOverlay";
++ cursor.getOdtDocument().subscribe(ops.OdtDocument.signalCursorMoved, handleCursorMove)
++ }
++ init()
++};
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.OperationRouter = function OperationRouter() {
- };
- ops.OperationRouter.prototype.setOperationFactory = function(f) {
- };
- ops.OperationRouter.prototype.setPlaybackFunction = function(playback_func) {
- };
- ops.OperationRouter.prototype.push = function(operations) {
- };
- ops.OperationRouter.prototype.close = function(callback) {
++runtime.loadClass("gui.SelectionView");
++gui.SelectionViewManager = function SelectionViewManager() {
++ var selectionViews = {};
++ function getSelectionView(memberId) {
++ return selectionViews.hasOwnProperty(memberId) ? selectionViews[memberId] : null
++ }
++ this.getSelectionView = getSelectionView;
++ function getSelectionViews() {
++ return Object.keys(selectionViews).map(function(memberid) {
++ return selectionViews[memberid]
++ })
++ }
++ this.getSelectionViews = getSelectionViews;
++ function removeSelectionView(memberId) {
++ if(selectionViews.hasOwnProperty(memberId)) {
++ selectionViews[memberId].destroy(function() {
++ });
++ delete selectionViews[memberId]
++ }
++ }
++ this.removeSelectionView = removeSelectionView;
++ function hideSelectionView(memberId) {
++ if(selectionViews.hasOwnProperty(memberId)) {
++ selectionViews[memberId].hide()
++ }
++ }
++ this.hideSelectionView = hideSelectionView;
++ function showSelectionView(memberId) {
++ if(selectionViews.hasOwnProperty(memberId)) {
++ selectionViews[memberId].show()
++ }
++ }
++ this.showSelectionView = showSelectionView;
++ this.rerenderSelectionViews = function() {
++ Object.keys(selectionViews).forEach(function(memberId) {
++ if(selectionViews[memberId].visible()) {
++ selectionViews[memberId].rerender()
++ }
++ })
++ };
++ this.registerCursor = function(cursor, virtualSelectionsInitiallyVisible) {
++ var memberId = cursor.getMemberId(), selectionView = new gui.SelectionView(cursor);
++ if(virtualSelectionsInitiallyVisible) {
++ selectionView.show()
++ }else {
++ selectionView.hide()
++ }
++ selectionViews[memberId] = selectionView;
++ return selectionView
++ };
++ this.destroy = function(callback) {
++ var selectionViewArray = getSelectionViews();
++ (function destroySelectionView(i, err) {
++ if(err) {
++ callback(err)
++ }else {
++ if(i < selectionViewArray.length) {
++ selectionViewArray[i].destroy(function(err) {
++ destroySelectionView(i + 1, err)
++ })
++ }else {
++ callback()
++ }
++ }
++ })(0, undefined)
++ }
+};
+/*
+
- Copyright (C) 2012 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.TrivialOperationRouter = function TrivialOperationRouter() {
- var operationFactory, playbackFunction;
- this.setOperationFactory = function(f) {
- operationFactory = f
++runtime.loadClass("core.DomUtils");
++runtime.loadClass("gui.UndoManager");
++runtime.loadClass("gui.UndoStateRules");
++gui.TrivialUndoManager = function TrivialUndoManager(defaultRules) {
++ var self = this, cursorns = "urn:webodf:names:cursor", domUtils = new core.DomUtils, initialDoc, initialState = [], playFunc, odtDocument, currentUndoState = [], undoStates = [], redoStates = [], eventNotifier = new core.EventNotifier([gui.UndoManager.signalUndoStackChanged, gui.UndoManager.signalUndoStateCreated, gui.UndoManager.signalUndoStateModified, gui.TrivialUndoManager.signalDocumentRootReplaced]), undoRules = defaultRules || new gui.UndoStateRules;
++ function emitStackChange() {
++ eventNotifier.emit(gui.UndoManager.signalUndoStackChanged, {undoAvailable:self.hasUndoStates(), redoAvailable:self.hasRedoStates()})
++ }
++ function mostRecentUndoState() {
++ return undoStates[undoStates.length - 1]
++ }
++ function completeCurrentUndoState() {
++ if(currentUndoState !== initialState && currentUndoState !== mostRecentUndoState()) {
++ undoStates.push(currentUndoState)
++ }
++ }
++ function removeNode(node) {
++ var sibling = node.previousSibling || node.nextSibling;
++ node.parentNode.removeChild(node);
++ domUtils.normalizeTextNodes(sibling)
++ }
++ function removeCursors(root) {
++ domUtils.getElementsByTagNameNS(root, cursorns, "cursor").forEach(removeNode);
++ domUtils.getElementsByTagNameNS(root, cursorns, "anchor").forEach(removeNode)
++ }
++ function values(obj) {
++ return Object.keys(obj).map(function(key) {
++ return obj[key]
++ })
++ }
++ function extractCursorStates(undoStates) {
++ var addCursor = {}, moveCursor = {}, requiredAddOps = {}, remainingAddOps, operations = undoStates.pop();
++ odtDocument.getCursors().forEach(function(cursor) {
++ requiredAddOps[cursor.getMemberId()] = true
++ });
++ remainingAddOps = Object.keys(requiredAddOps).length;
++ function processOp(op) {
++ var spec = op.spec();
++ if(!requiredAddOps[spec.memberid]) {
++ return
++ }
++ switch(spec.optype) {
++ case "AddCursor":
++ if(!addCursor[spec.memberid]) {
++ addCursor[spec.memberid] = op;
++ delete requiredAddOps[spec.memberid];
++ remainingAddOps -= 1
++ }
++ break;
++ case "MoveCursor":
++ if(!moveCursor[spec.memberid]) {
++ moveCursor[spec.memberid] = op
++ }
++ break
++ }
++ }
++ while(operations && remainingAddOps > 0) {
++ operations.reverse();
++ operations.forEach(processOp);
++ operations = undoStates.pop()
++ }
++ return values(addCursor).concat(values(moveCursor))
++ }
++ this.subscribe = function(signal, callback) {
++ eventNotifier.subscribe(signal, callback)
+ };
- this.setPlaybackFunction = function(playback_func) {
- playbackFunction = playback_func
++ this.unsubscribe = function(signal, callback) {
++ eventNotifier.unsubscribe(signal, callback)
+ };
- this.push = function(operations) {
- operations.forEach(function(op) {
- var timedOp, opspec = op.spec();
- opspec.timestamp = (new Date).getTime();
- timedOp = operationFactory.create(opspec);
- playbackFunction(timedOp)
- })
++ this.hasUndoStates = function() {
++ return undoStates.length > 0
+ };
- this.close = function(cb) {
- cb()
- }
- };
- gui.EditInfoHandle = function EditInfoHandle(parentElement) {
- var edits = [], handle, document = (parentElement.ownerDocument), htmlns = document.documentElement.namespaceURI, editinfons = "urn:webodf:names:editinfo";
- function renderEdits() {
- var i, infoDiv, colorSpan, authorSpan, timeSpan;
- handle.innerHTML = "";
- for(i = 0;i < edits.length;i += 1) {
- infoDiv = document.createElementNS(htmlns, "div");
- infoDiv.className = "editInfo";
- colorSpan = document.createElementNS(htmlns, "span");
- colorSpan.className = "editInfoColor";
- colorSpan.setAttributeNS(editinfons, "editinfo:memberid", edits[i].memberid);
- authorSpan = document.createElementNS(htmlns, "span");
- authorSpan.className = "editInfoAuthor";
- authorSpan.setAttributeNS(editinfons, "editinfo:memberid", edits[i].memberid);
- timeSpan = document.createElementNS(htmlns, "span");
- timeSpan.className = "editInfoTime";
- timeSpan.setAttributeNS(editinfons, "editinfo:memberid", edits[i].memberid);
- timeSpan.innerHTML = edits[i].time;
- infoDiv.appendChild(colorSpan);
- infoDiv.appendChild(authorSpan);
- infoDiv.appendChild(timeSpan);
- handle.appendChild(infoDiv)
++ this.hasRedoStates = function() {
++ return redoStates.length > 0
++ };
++ this.setOdtDocument = function(newDocument) {
++ odtDocument = newDocument
++ };
++ this.resetInitialState = function() {
++ undoStates.length = 0;
++ redoStates.length = 0;
++ initialState.length = 0;
++ currentUndoState.length = 0;
++ initialDoc = null;
++ emitStackChange()
++ };
++ this.saveInitialState = function() {
++ var odfContainer = odtDocument.getOdfCanvas().odfContainer(), annotationViewManager = odtDocument.getOdfCanvas().getAnnotationViewManager();
++ if(annotationViewManager) {
++ annotationViewManager.forgetAnnotations()
+ }
- }
- this.setEdits = function(editArray) {
- edits = editArray;
- renderEdits()
++ initialDoc = odfContainer.rootElement.cloneNode(true);
++ odtDocument.getOdfCanvas().refreshAnnotations();
++ removeCursors(initialDoc);
++ completeCurrentUndoState();
++ undoStates.unshift(initialState);
++ currentUndoState = initialState = extractCursorStates(undoStates);
++ undoStates.length = 0;
++ redoStates.length = 0;
++ emitStackChange()
+ };
- this.show = function() {
- handle.style.display = "block"
++ this.setPlaybackFunction = function(playback_func) {
++ playFunc = playback_func
+ };
- this.hide = function() {
- handle.style.display = "none"
++ this.onOperationExecuted = function(op) {
++ redoStates.length = 0;
++ if(undoRules.isEditOperation(op) && currentUndoState === initialState || !undoRules.isPartOfOperationSet(op, currentUndoState)) {
++ completeCurrentUndoState();
++ currentUndoState = [op];
++ undoStates.push(currentUndoState);
++ eventNotifier.emit(gui.UndoManager.signalUndoStateCreated, {operations:currentUndoState});
++ emitStackChange()
++ }else {
++ currentUndoState.push(op);
++ eventNotifier.emit(gui.UndoManager.signalUndoStateModified, {operations:currentUndoState})
++ }
+ };
- this.destroy = function(callback) {
- parentElement.removeChild(handle);
- callback()
++ this.moveForward = function(states) {
++ var moved = 0, redoOperations;
++ while(states && redoStates.length) {
++ redoOperations = redoStates.pop();
++ undoStates.push(redoOperations);
++ redoOperations.forEach(playFunc);
++ states -= 1;
++ moved += 1
++ }
++ if(moved) {
++ currentUndoState = mostRecentUndoState();
++ emitStackChange()
++ }
++ return moved
+ };
- function init() {
- handle = document.createElementNS(htmlns, "div");
- handle.setAttribute("class", "editInfoHandle");
- handle.style.display = "none";
- parentElement.appendChild(handle)
++ this.moveBackward = function(states) {
++ var odfCanvas = odtDocument.getOdfCanvas(), odfContainer = odfCanvas.odfContainer(), moved = 0;
++ while(states && undoStates.length) {
++ redoStates.push(undoStates.pop());
++ states -= 1;
++ moved += 1
++ }
++ if(moved) {
++ odfContainer.setRootElement(initialDoc.cloneNode(true));
++ odfCanvas.setOdfContainer(odfContainer, true);
++ eventNotifier.emit(gui.TrivialUndoManager.signalDocumentRootReplaced, {});
++ odtDocument.getCursors().forEach(function(cursor) {
++ odtDocument.removeCursor(cursor.getMemberId())
++ });
++ initialState.forEach(playFunc);
++ undoStates.forEach(function(ops) {
++ ops.forEach(playFunc)
++ });
++ odfCanvas.refreshCSS();
++ currentUndoState = mostRecentUndoState() || initialState;
++ emitStackChange()
++ }
++ return moved
+ }
- init()
+};
++gui.TrivialUndoManager.signalDocumentRootReplaced = "documentRootReplaced";
++(function() {
++ return gui.TrivialUndoManager
++})();
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("ops.EditInfo");
- runtime.loadClass("gui.EditInfoHandle");
- gui.EditInfoMarker = function EditInfoMarker(editInfo, initialVisibility) {
- var self = this, editInfoNode, handle, marker, editinfons = "urn:webodf:names:editinfo", decay1, decay2, decayTimeStep = 1E4;
- function applyDecay(opacity, delay) {
- return runtime.setTimeout(function() {
- marker.style.opacity = opacity
- }, delay)
- }
- function deleteDecay(timer) {
- runtime.clearTimeout(timer)
- }
- function setLastAuthor(memberid) {
- marker.setAttributeNS(editinfons, "editinfo:memberid", memberid)
- }
- this.addEdit = function(memberid, timestamp) {
- var age = Date.now() - timestamp;
- editInfo.addEdit(memberid, timestamp);
- handle.setEdits(editInfo.getSortedEdits());
- setLastAuthor(memberid);
- if(decay1) {
- deleteDecay(decay1)
- }
- if(decay2) {
- deleteDecay(decay2)
- }
- if(age < decayTimeStep) {
- applyDecay(1, 0);
- decay1 = applyDecay(0.5, decayTimeStep - age);
- decay2 = applyDecay(0.2, decayTimeStep * 2 - age)
- }else {
- if(age >= decayTimeStep && age < decayTimeStep * 2) {
- applyDecay(0.5, 0);
- decay2 = applyDecay(0.2, decayTimeStep * 2 - age)
- }else {
- applyDecay(0.2, 0)
- }
- }
- };
- this.getEdits = function() {
- return editInfo.getEdits()
- };
- this.clearEdits = function() {
- editInfo.clearEdits();
- handle.setEdits([]);
- if(marker.hasAttributeNS(editinfons, "editinfo:memberid")) {
- marker.removeAttributeNS(editinfons, "editinfo:memberid")
++runtime.loadClass("ops.TrivialOperationRouter");
++runtime.loadClass("ops.OperationFactory");
++runtime.loadClass("ops.OdtDocument");
++ops.Session = function Session(odfCanvas) {
++ var self = this, operationFactory = new ops.OperationFactory, odtDocument = new ops.OdtDocument(odfCanvas), operationRouter = null;
++ this.setOperationFactory = function(opFactory) {
++ operationFactory = opFactory;
++ if(operationRouter) {
++ operationRouter.setOperationFactory(operationFactory)
+ }
+ };
- this.getEditInfo = function() {
- return editInfo
- };
- this.show = function() {
- marker.style.display = "block"
++ this.setOperationRouter = function(opRouter) {
++ operationRouter = opRouter;
++ opRouter.setPlaybackFunction(function(op) {
++ if(op.execute(odtDocument)) {
++ odtDocument.emit(ops.OdtDocument.signalOperationExecuted, op);
++ return true
++ }
++ return false
++ });
++ opRouter.setOperationFactory(operationFactory)
+ };
- this.hide = function() {
- self.hideHandle();
- marker.style.display = "none"
++ this.getOperationFactory = function() {
++ return operationFactory
+ };
- this.showHandle = function() {
- handle.show()
++ this.getOdtDocument = function() {
++ return odtDocument
+ };
- this.hideHandle = function() {
- handle.hide()
++ this.enqueue = function(ops) {
++ operationRouter.push(ops)
+ };
- this.destroy = function(callback) {
- editInfoNode.removeChild(marker);
- handle.destroy(function(err) {
++ this.close = function(callback) {
++ operationRouter.close(function(err) {
+ if(err) {
+ callback(err)
+ }else {
- editInfo.destroy(callback)
++ odtDocument.close(callback)
+ }
+ })
+ };
++ this.destroy = function(callback) {
++ odtDocument.destroy(callback)
++ };
+ function init() {
- var dom = editInfo.getOdtDocument().getDOM(), htmlns = dom.documentElement.namespaceURI;
- marker = dom.createElementNS(htmlns, "div");
- marker.setAttribute("class", "editInfoMarker");
- marker.onmouseover = function() {
- self.showHandle()
- };
- marker.onmouseout = function() {
- self.hideHandle()
- };
- editInfoNode = editInfo.getNode();
- editInfoNode.appendChild(marker);
- handle = new gui.EditInfoHandle(editInfoNode);
- if(!initialVisibility) {
- self.hide()
- }
++ self.setOperationRouter(new ops.TrivialOperationRouter)
+ }
+ init()
+};
+/*
+
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
++ This file is part of WebODF.
+
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
++ WebODF is free software: you can redistribute it and/or modify it
++ under the terms of the GNU Affero General Public License (GNU AGPL)
++ as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version.
+
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
++ WebODF is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU Affero General Public License for more details.
+
- This license applies to this entire compilation.
++ You should have received a copy of the GNU Affero General Public License
++ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ @licend
++
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("gui.Caret");
- runtime.loadClass("ops.EditInfo");
- runtime.loadClass("gui.EditInfoMarker");
- gui.SessionViewOptions = function() {
- this.editInfoMarkersInitiallyVisible = true;
- this.caretAvatarsInitiallyVisible = true;
- this.caretBlinksOnRangeSelect = true
- };
- gui.SessionView = function() {
- function configOption(userValue, defaultValue) {
- return userValue !== undefined ? Boolean(userValue) : defaultValue
- }
- function SessionView(viewOptions, localMemberId, session, caretManager, selectionViewManager) {
- var avatarInfoStyles, editInfons = "urn:webodf:names:editinfo", editInfoMap = {}, showEditInfoMarkers = configOption(viewOptions.editInfoMarkersInitiallyVisible, true), showCaretAvatars = configOption(viewOptions.caretAvatarsInitiallyVisible, true), blinkOnRangeSelect = configOption(viewOptions.caretBlinksOnRangeSelect, true), rerenderIntervalId, rerenderSelectionViews = false, RERENDER_INTERVAL = 200;
- function createAvatarInfoNodeMatch(nodeName, memberId, pseudoClass) {
- return nodeName + '[editinfo|memberid="' + memberId + '"]' + pseudoClass
- }
- function getAvatarInfoStyle(nodeName, memberId, pseudoClass) {
- var node = avatarInfoStyles.firstChild, nodeMatch = createAvatarInfoNodeMatch(nodeName, memberId, pseudoClass) + "{";
- while(node) {
- if(node.nodeType === Node.TEXT_NODE && node.data.indexOf(nodeMatch) === 0) {
- return node
- }
- node = node.nextSibling
++runtime.loadClass("core.EventNotifier");
++runtime.loadClass("core.PositionFilter");
++runtime.loadClass("ops.Session");
++runtime.loadClass("ops.OpAddAnnotation");
++runtime.loadClass("ops.OpRemoveAnnotation");
++runtime.loadClass("gui.SelectionMover");
++gui.AnnotationController = function AnnotationController(session, inputMemberId) {
++ var odtDocument = session.getOdtDocument(), isAnnotatable = false, eventNotifier = new core.EventNotifier([gui.AnnotationController.annotatableChanged]), officens = odf.Namespaces.officens;
++ function isWithinAnnotation(node, container) {
++ while(node && node !== container) {
++ if(node.namespaceURI === officens && node.localName === "annotation") {
++ return true
+ }
- return null
++ node = node.parentNode
+ }
- function setAvatarInfoStyle(memberId, name, color) {
- function setStyle(nodeName, rule, pseudoClass) {
- var styleRule = createAvatarInfoNodeMatch(nodeName, memberId, pseudoClass) + rule, styleNode = getAvatarInfoStyle(nodeName, memberId, pseudoClass);
- if(styleNode) {
- styleNode.data = styleRule
- }else {
- avatarInfoStyles.appendChild(document.createTextNode(styleRule))
- }
- }
- setStyle("div.editInfoMarker", "{ background-color: " + color + "; }", "");
- setStyle("span.editInfoColor", "{ background-color: " + color + "; }", "");
- setStyle("span.editInfoAuthor", '{ content: "' + name + '"; }', ":before");
- setStyle("dc|creator", "{ background-color: " + color + "; }", "");
- setStyle("div.selectionOverlay", "{ background-color: " + color + ";}", "")
++ return false
++ }
++ function updatedCachedValues() {
++ var cursor = odtDocument.getCursor(inputMemberId), cursorNode = cursor && cursor.getNode(), newIsAnnotatable = false;
++ if(cursorNode) {
++ newIsAnnotatable = !isWithinAnnotation(cursorNode, odtDocument.getRootNode())
+ }
- function highlightEdit(element, memberId, timestamp) {
- var editInfo, editInfoMarker, id = "", editInfoNode = element.getElementsByTagNameNS(editInfons, "editinfo")[0];
- if(editInfoNode) {
- id = editInfoNode.getAttributeNS(editInfons, "id");
- editInfoMarker = editInfoMap[id]
- }else {
- id = Math.random().toString();
- editInfo = new ops.EditInfo(element, session.getOdtDocument());
- editInfoMarker = new gui.EditInfoMarker(editInfo, showEditInfoMarkers);
- editInfoNode = element.getElementsByTagNameNS(editInfons, "editinfo")[0];
- editInfoNode.setAttributeNS(editInfons, "id", id);
- editInfoMap[id] = editInfoMarker
- }
- editInfoMarker.addEdit(memberId, new Date(timestamp))
++ if(newIsAnnotatable !== isAnnotatable) {
++ isAnnotatable = newIsAnnotatable;
++ eventNotifier.emit(gui.AnnotationController.annotatableChanged, isAnnotatable)
+ }
- function setEditInfoMarkerVisibility(visible) {
- var editInfoMarker, keyname;
- for(keyname in editInfoMap) {
- if(editInfoMap.hasOwnProperty(keyname)) {
- editInfoMarker = editInfoMap[keyname];
- if(visible) {
- editInfoMarker.show()
- }else {
- editInfoMarker.hide()
- }
- }
- }
++ }
++ function onCursorAdded(cursor) {
++ if(cursor.getMemberId() === inputMemberId) {
++ updatedCachedValues()
+ }
- function setCaretAvatarVisibility(visible) {
- caretManager.getCarets().forEach(function(caret) {
- if(visible) {
- caret.showHandle()
- }else {
- caret.hideHandle()
- }
- })
++ }
++ function onCursorRemoved(memberId) {
++ if(memberId === inputMemberId) {
++ updatedCachedValues()
+ }
- this.showEditInfoMarkers = function() {
- if(showEditInfoMarkers) {
- return
- }
- showEditInfoMarkers = true;
- setEditInfoMarkerVisibility(showEditInfoMarkers)
- };
- this.hideEditInfoMarkers = function() {
- if(!showEditInfoMarkers) {
- return
- }
- showEditInfoMarkers = false;
- setEditInfoMarkerVisibility(showEditInfoMarkers)
- };
- this.showCaretAvatars = function() {
- if(showCaretAvatars) {
- return
- }
- showCaretAvatars = true;
- setCaretAvatarVisibility(showCaretAvatars)
- };
- this.hideCaretAvatars = function() {
- if(!showCaretAvatars) {
- return
- }
- showCaretAvatars = false;
- setCaretAvatarVisibility(showCaretAvatars)
- };
- this.getSession = function() {
- return session
- };
- this.getCaret = function(memberid) {
- return caretManager.getCaret(memberid)
- };
- function renderMemberData(member) {
- var memberId = member.getMemberId(), properties = member.getProperties();
- setAvatarInfoStyle(memberId, properties.fullName, properties.color);
- if(localMemberId === memberId) {
- setAvatarInfoStyle("", "", properties.color)
- }
++ }
++ function onCursorMoved(cursor) {
++ if(cursor.getMemberId() === inputMemberId) {
++ updatedCachedValues()
+ }
- function onCursorAdded(cursor) {
- var memberId = cursor.getMemberId(), properties = session.getOdtDocument().getMember(memberId).getProperties(), caret;
- caretManager.registerCursor(cursor, showCaretAvatars, blinkOnRangeSelect);
- selectionViewManager.registerCursor(cursor, true);
- caret = caretManager.getCaret(memberId);
- if(caret) {
- caret.setAvatarImageUrl(properties.imageUrl);
- caret.setColor(properties.color)
- }
- runtime.log("+++ View here +++ eagerly created an Caret for '" + memberId + "'! +++")
++ }
++ this.isAnnotatable = function() {
++ return isAnnotatable
++ };
++ this.addAnnotation = function() {
++ var op = new ops.OpAddAnnotation, selection = odtDocument.getCursorSelection(inputMemberId), length = selection.length, position = selection.position;
++ if(!isAnnotatable) {
++ return
+ }
- function onCursorMoved(cursor) {
- var memberId = cursor.getMemberId(), localSelectionView = selectionViewManager.getSelectionView(localMemberId), shadowSelectionView = selectionViewManager.getSelectionView(gui.ShadowCursor.ShadowCursorMemberId), localCaret = caretManager.getCaret(localMemberId);
- if(memberId === localMemberId) {
- shadowSelectionView.hide();
- localSelectionView.show();
- if(localCaret) {
- localCaret.show()
- }
- }else {
- if(memberId === gui.ShadowCursor.ShadowCursorMemberId) {
- shadowSelectionView.show();
- localSelectionView.hide();
- if(localCaret) {
- localCaret.hide()
- }
++ position = length >= 0 ? position : position + length;
++ length = Math.abs(length);
++ op.init({memberid:inputMemberId, position:position, length:length, name:inputMemberId + Date.now()});
++ session.enqueue([op])
++ };
++ this.removeAnnotation = function(annotationNode) {
++ var startStep, endStep, op, moveCursor;
++ startStep = odtDocument.convertDomPointToCursorStep(annotationNode, 0) + 1;
++ endStep = odtDocument.convertDomPointToCursorStep(annotationNode, annotationNode.childNodes.length);
++ op = new ops.OpRemoveAnnotation;
++ op.init({memberid:inputMemberId, position:startStep, length:endStep - startStep});
++ moveCursor = new ops.OpMoveCursor;
++ moveCursor.init({memberid:inputMemberId, position:startStep > 0 ? startStep - 1 : startStep, length:0});
++ session.enqueue([op, moveCursor])
++ };
++ this.subscribe = function(eventid, cb) {
++ eventNotifier.subscribe(eventid, cb)
++ };
++ this.unsubscribe = function(eventid, cb) {
++ eventNotifier.unsubscribe(eventid, cb)
++ };
++ this.destroy = function(callback) {
++ odtDocument.unsubscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
++ odtDocument.unsubscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
++ odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
++ callback()
++ };
++ function init() {
++ odtDocument.subscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
++ odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
++ odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
++ updatedCachedValues()
++ }
++ init()
++};
++gui.AnnotationController.annotatableChanged = "annotatable/changed";
++(function() {
++ return gui.AnnotationController
++})();
++/*
++
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
++
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
++
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
++
++ This license applies to this entire compilation.
++ @licend
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++runtime.loadClass("core.EventNotifier");
++runtime.loadClass("core.Utils");
++runtime.loadClass("odf.OdfUtils");
++runtime.loadClass("ops.OpAddStyle");
++runtime.loadClass("ops.OpSetParagraphStyle");
++runtime.loadClass("gui.StyleHelper");
++gui.DirectParagraphStyler = function DirectParagraphStyler(session, inputMemberId, objectNameGenerator) {
++ var odtDocument = session.getOdtDocument(), utils = new core.Utils, odfUtils = new odf.OdfUtils, styleHelper = new gui.StyleHelper(odtDocument.getFormatting()), eventNotifier = new core.EventNotifier([gui.DirectParagraphStyler.paragraphStylingChanged]), isAlignedLeftValue, isAlignedCenterValue, isAlignedRightValue, isAlignedJustifiedValue;
++ function updatedCachedValues() {
++ var cursor = odtDocument.getCursor(inputMemberId), range = cursor && cursor.getSelectedRange(), diffMap;
++ function noteChange(oldValue, newValue, id) {
++ if(oldValue !== newValue) {
++ if(diffMap === undefined) {
++ diffMap = {}
+ }
++ diffMap[id] = newValue
+ }
++ return newValue
+ }
- function onCursorRemoved(memberid) {
- selectionViewManager.removeSelectionView(memberid)
++ isAlignedLeftValue = noteChange(isAlignedLeftValue, range ? styleHelper.isAlignedLeft(range) : false, "isAlignedLeft");
++ isAlignedCenterValue = noteChange(isAlignedCenterValue, range ? styleHelper.isAlignedCenter(range) : false, "isAlignedCenter");
++ isAlignedRightValue = noteChange(isAlignedRightValue, range ? styleHelper.isAlignedRight(range) : false, "isAlignedRight");
++ isAlignedJustifiedValue = noteChange(isAlignedJustifiedValue, range ? styleHelper.isAlignedJustified(range) : false, "isAlignedJustified");
++ if(diffMap) {
++ eventNotifier.emit(gui.DirectParagraphStyler.paragraphStylingChanged, diffMap)
+ }
- function onParagraphChanged(info) {
- highlightEdit(info.paragraphElement, info.memberId, info.timeStamp)
++ }
++ function onCursorAdded(cursor) {
++ if(cursor.getMemberId() === inputMemberId) {
++ updatedCachedValues()
+ }
- function requestRerenderOfSelectionViews() {
- rerenderSelectionViews = true
++ }
++ function onCursorRemoved(memberId) {
++ if(memberId === inputMemberId) {
++ updatedCachedValues()
+ }
- function startRerenderLoop() {
- rerenderIntervalId = runtime.getWindow().setInterval(function() {
- if(rerenderSelectionViews) {
- selectionViewManager.rerenderSelectionViews();
- rerenderSelectionViews = false
- }
- }, RERENDER_INTERVAL)
++ }
++ function onCursorMoved(cursor) {
++ if(cursor.getMemberId() === inputMemberId) {
++ updatedCachedValues()
+ }
- function stopRerenderLoop() {
- runtime.getWindow().clearInterval(rerenderIntervalId)
++ }
++ function onParagraphStyleModified() {
++ updatedCachedValues()
++ }
++ function onParagraphChanged(args) {
++ var cursor = odtDocument.getCursor(inputMemberId);
++ if(cursor && odtDocument.getParagraphElement(cursor.getNode()) === args.paragraphElement) {
++ updatedCachedValues()
+ }
- this.destroy = function(callback) {
- var odtDocument = session.getOdtDocument(), editInfoArray = Object.keys(editInfoMap).map(function(keyname) {
- return editInfoMap[keyname]
- });
- odtDocument.unsubscribe(ops.OdtDocument.signalMemberAdded, renderMemberData);
- odtDocument.unsubscribe(ops.OdtDocument.signalMemberUpdated, renderMemberData);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
- odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
- odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, requestRerenderOfSelectionViews);
- odtDocument.unsubscribe(ops.OdtDocument.signalTableAdded, requestRerenderOfSelectionViews);
- odtDocument.unsubscribe(ops.OdtDocument.signalParagraphStyleModified, requestRerenderOfSelectionViews);
- stopRerenderLoop();
- avatarInfoStyles.parentNode.removeChild(avatarInfoStyles);
- (function destroyEditInfo(i, err) {
- if(err) {
- callback(err)
- }else {
- if(i < editInfoArray.length) {
- editInfoArray[i].destroy(function(err) {
- destroyEditInfo(i + 1, err)
- })
- }else {
- callback()
- }
- }
- })(0, undefined)
- };
- function init() {
- var odtDocument = session.getOdtDocument(), head = document.getElementsByTagName("head")[0];
- odtDocument.subscribe(ops.OdtDocument.signalMemberAdded, renderMemberData);
- odtDocument.subscribe(ops.OdtDocument.signalMemberUpdated, renderMemberData);
- odtDocument.subscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
- odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
- odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged);
- odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
- startRerenderLoop();
- odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, requestRerenderOfSelectionViews);
- odtDocument.subscribe(ops.OdtDocument.signalTableAdded, requestRerenderOfSelectionViews);
- odtDocument.subscribe(ops.OdtDocument.signalParagraphStyleModified, requestRerenderOfSelectionViews);
- avatarInfoStyles = document.createElementNS(head.namespaceURI, "style");
- avatarInfoStyles.type = "text/css";
- avatarInfoStyles.media = "screen, print, handheld, projection";
- avatarInfoStyles.appendChild(document.createTextNode("@namespace editinfo url(urn:webodf:names:editinfo);"));
- avatarInfoStyles.appendChild(document.createTextNode("@namespace dc url(http://purl.org/dc/elements/1.1/);"));
- head.appendChild(avatarInfoStyles)
++ }
++ this.isAlignedLeft = function() {
++ return isAlignedLeftValue
++ };
++ this.isAlignedCenter = function() {
++ return isAlignedCenterValue
++ };
++ this.isAlignedRight = function() {
++ return isAlignedRightValue
++ };
++ this.isAlignedJustified = function() {
++ return isAlignedJustifiedValue
++ };
++ function roundUp(step) {
++ return step === ops.StepsTranslator.NEXT_STEP
++ }
++ function applyParagraphDirectStyling(applyDirectStyling) {
++ var range = odtDocument.getCursor(inputMemberId).getSelectedRange(), paragraphs = odfUtils.getParagraphElements(range), formatting = odtDocument.getFormatting();
++ paragraphs.forEach(function(paragraph) {
++ var paragraphStartPoint = odtDocument.convertDomPointToCursorStep(paragraph, 0, roundUp), paragraphStyleName = paragraph.getAttributeNS(odf.Namespaces.textns, "style-name"), newParagraphStyleName = objectNameGenerator.generateStyleName(), opAddStyle, opSetParagraphStyle, paragraphProperties;
++ if(paragraphStyleName) {
++ paragraphProperties = formatting.createDerivedStyleObject(paragraphStyleName, "paragraph", {})
++ }
++ paragraphProperties = applyDirectStyling(paragraphProperties || {});
++ opAddStyle = new ops.OpAddStyle;
++ opAddStyle.init({memberid:inputMemberId, styleName:newParagraphStyleName, styleFamily:"paragraph", isAutomaticStyle:true, setProperties:paragraphProperties});
++ opSetParagraphStyle = new ops.OpSetParagraphStyle;
++ opSetParagraphStyle.init({memberid:inputMemberId, styleName:newParagraphStyleName, position:paragraphStartPoint});
++ session.enqueue([opAddStyle, opSetParagraphStyle])
++ })
++ }
++ function applySimpleParagraphDirectStyling(styleOverrides) {
++ applyParagraphDirectStyling(function(paragraphStyle) {
++ return utils.mergeObjects(paragraphStyle, styleOverrides)
++ })
++ }
++ function alignParagraph(alignment) {
++ applySimpleParagraphDirectStyling({"style:paragraph-properties":{"fo:text-align":alignment}})
++ }
++ this.alignParagraphLeft = function() {
++ alignParagraph("left");
++ return true
++ };
++ this.alignParagraphCenter = function() {
++ alignParagraph("center");
++ return true
++ };
++ this.alignParagraphRight = function() {
++ alignParagraph("right");
++ return true
++ };
++ this.alignParagraphJustified = function() {
++ alignParagraph("justify");
++ return true
++ };
++ function modifyParagraphIndent(direction, paragraphStyle) {
++ var tabStopDistance = odtDocument.getFormatting().getDefaultTabStopDistance(), paragraphProperties = paragraphStyle["style:paragraph-properties"], indentValue = paragraphProperties && paragraphProperties["fo:margin-left"], indent = indentValue && odfUtils.parseLength(indentValue), newIndent;
++ if(indent && indent.unit === tabStopDistance.unit) {
++ newIndent = indent.value + direction * tabStopDistance.value + indent.unit
++ }else {
++ newIndent = direction * tabStopDistance.value + tabStopDistance.unit
+ }
- init()
++ return utils.mergeObjects(paragraphStyle, {"style:paragraph-properties":{"fo:margin-left":newIndent}})
+ }
- return SessionView
- }();
++ this.indent = function() {
++ applyParagraphDirectStyling(modifyParagraphIndent.bind(null, 1));
++ return true
++ };
++ this.outdent = function() {
++ applyParagraphDirectStyling(modifyParagraphIndent.bind(null, -1));
++ return true
++ };
++ this.subscribe = function(eventid, cb) {
++ eventNotifier.subscribe(eventid, cb)
++ };
++ this.unsubscribe = function(eventid, cb) {
++ eventNotifier.unsubscribe(eventid, cb)
++ };
++ this.destroy = function(callback) {
++ odtDocument.unsubscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
++ odtDocument.unsubscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
++ odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
++ odtDocument.unsubscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified);
++ odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged);
++ callback()
++ };
++ function init() {
++ odtDocument.subscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
++ odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
++ odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
++ odtDocument.subscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified);
++ odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged);
++ updatedCachedValues()
++ }
++ init()
++};
++gui.DirectParagraphStyler.paragraphStylingChanged = "paragraphStyling/changed";
++(function() {
++ return gui.DirectParagraphStyler
++})();
+/*
+
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("gui.Caret");
- gui.CaretManager = function CaretManager(sessionController) {
- var carets = {}, window = runtime.getWindow(), scrollIntoViewScheduled = false;
- function getCaret(memberId) {
- return carets.hasOwnProperty(memberId) ? carets[memberId] : null
- }
- function getCarets() {
- return Object.keys(carets).map(function(memberid) {
- return carets[memberid]
- })
++runtime.loadClass("core.EventNotifier");
++runtime.loadClass("core.Utils");
++runtime.loadClass("ops.OpApplyDirectStyling");
++runtime.loadClass("gui.StyleHelper");
++gui.DirectTextStyler = function DirectTextStyler(session, inputMemberId) {
++ var self = this, utils = new core.Utils, odtDocument = session.getOdtDocument(), styleHelper = new gui.StyleHelper(odtDocument.getFormatting()), eventNotifier = new core.EventNotifier([gui.DirectTextStyler.textStylingChanged]), directCursorStyleProperties, currentSelectionStyles = [], isBoldValue = false, isItalicValue = false, hasUnderlineValue = false, hasStrikeThroughValue = false, fontSizeValue, fontNameValue;
++ function get(obj, keys) {
++ var i = 0, key = keys[i];
++ while(key && obj) {
++ obj = obj[key];
++ i += 1;
++ key = keys[i]
++ }
++ return keys.length === i ? obj : undefined
+ }
- function getCanvasElement() {
- return sessionController.getSession().getOdtDocument().getOdfCanvas().getElement()
++ function getCommonValue(objArray, keys) {
++ var value = get(objArray[0], keys);
++ return objArray.every(function(obj) {
++ return value === get(obj, keys)
++ }) ? value : undefined
+ }
- function removeCaret(memberId) {
- if(memberId === sessionController.getInputMemberId()) {
- getCanvasElement().removeAttribute("tabindex")
++ function getAppliedStyles() {
++ var cursor = odtDocument.getCursor(inputMemberId), range = cursor && cursor.getSelectedRange(), selectionStyles = range && styleHelper.getAppliedStyles(range) || [];
++ if(selectionStyles[0] && directCursorStyleProperties) {
++ selectionStyles[0] = utils.mergeObjects(selectionStyles[0], (directCursorStyleProperties))
+ }
- delete carets[memberId]
++ return selectionStyles
+ }
- function refreshLocalCaretBlinking(cursor) {
- var caret, memberId = cursor.getMemberId();
- if(memberId === sessionController.getInputMemberId()) {
- caret = getCaret(memberId);
- if(caret) {
- caret.refreshCursorBlinking()
++ function updatedCachedValues() {
++ var fontSize, diffMap;
++ currentSelectionStyles = getAppliedStyles();
++ function noteChange(oldValue, newValue, id) {
++ if(oldValue !== newValue) {
++ if(diffMap === undefined) {
++ diffMap = {}
++ }
++ diffMap[id] = newValue
+ }
++ return newValue
++ }
++ isBoldValue = noteChange(isBoldValue, currentSelectionStyles ? styleHelper.isBold(currentSelectionStyles) : false, "isBold");
++ isItalicValue = noteChange(isItalicValue, currentSelectionStyles ? styleHelper.isItalic(currentSelectionStyles) : false, "isItalic");
++ hasUnderlineValue = noteChange(hasUnderlineValue, currentSelectionStyles ? styleHelper.hasUnderline(currentSelectionStyles) : false, "hasUnderline");
++ hasStrikeThroughValue = noteChange(hasStrikeThroughValue, currentSelectionStyles ? styleHelper.hasStrikeThrough(currentSelectionStyles) : false, "hasStrikeThrough");
++ fontSize = currentSelectionStyles && getCommonValue(currentSelectionStyles, ["style:text-properties", "fo:font-size"]);
++ fontSizeValue = noteChange(fontSizeValue, fontSize && parseFloat(fontSize), "fontSize");
++ fontNameValue = noteChange(fontNameValue, currentSelectionStyles && getCommonValue(currentSelectionStyles, ["style:text-properties", "style:font-name"]), "fontName");
++ if(diffMap) {
++ eventNotifier.emit(gui.DirectTextStyler.textStylingChanged, diffMap)
+ }
+ }
- function executeEnsureCaretVisible() {
- var caret = getCaret(sessionController.getInputMemberId());
- scrollIntoViewScheduled = false;
- if(caret) {
- caret.ensureVisible()
++ function onCursorAdded(cursor) {
++ if(cursor.getMemberId() === inputMemberId) {
++ updatedCachedValues()
+ }
+ }
- function scheduleCaretVisibilityCheck() {
- var caret = getCaret(sessionController.getInputMemberId());
- if(caret) {
- caret.handleUpdate();
- if(!scrollIntoViewScheduled) {
- scrollIntoViewScheduled = true;
- runtime.setTimeout(executeEnsureCaretVisible, 50)
- }
++ function onCursorRemoved(memberId) {
++ if(memberId === inputMemberId) {
++ updatedCachedValues()
+ }
+ }
- function ensureLocalCaretVisible(info) {
- if(info.memberId === sessionController.getInputMemberId()) {
- scheduleCaretVisibilityCheck()
++ function onCursorMoved(cursor) {
++ if(cursor.getMemberId() === inputMemberId) {
++ updatedCachedValues()
+ }
+ }
- function focusLocalCaret() {
- var caret = getCaret(sessionController.getInputMemberId());
- if(caret) {
- caret.setFocus()
++ function onParagraphStyleModified() {
++ updatedCachedValues()
++ }
++ function onParagraphChanged(args) {
++ var cursor = odtDocument.getCursor(inputMemberId);
++ if(cursor && odtDocument.getParagraphElement(cursor.getNode()) === args.paragraphElement) {
++ updatedCachedValues()
+ }
+ }
- function blurLocalCaret() {
- var caret = getCaret(sessionController.getInputMemberId());
- if(caret) {
- caret.removeFocus()
++ function toggle(predicate, toggleMethod) {
++ var cursor = odtDocument.getCursor(inputMemberId), appliedStyles;
++ if(!cursor) {
++ return false
+ }
++ appliedStyles = styleHelper.getAppliedStyles(cursor.getSelectedRange());
++ toggleMethod(!predicate(appliedStyles));
++ return true
+ }
- function showLocalCaret() {
- var caret = getCaret(sessionController.getInputMemberId());
- if(caret) {
- caret.show()
++ function formatTextSelection(textProperties) {
++ var selection = odtDocument.getCursorSelection(inputMemberId), op, properties = {"style:text-properties":textProperties};
++ if(selection.length !== 0) {
++ op = new ops.OpApplyDirectStyling;
++ op.init({memberid:inputMemberId, position:selection.position, length:selection.length, setProperties:properties});
++ session.enqueue([op])
++ }else {
++ directCursorStyleProperties = utils.mergeObjects(directCursorStyleProperties || {}, properties);
++ updatedCachedValues()
++ }
++ }
++ this.formatTextSelection = formatTextSelection;
++ function applyTextPropertyToSelection(propertyName, propertyValue) {
++ var textProperties = {};
++ textProperties[propertyName] = propertyValue;
++ formatTextSelection(textProperties)
++ }
++ this.createCursorStyleOp = function(position, length) {
++ var styleOp = null;
++ if(directCursorStyleProperties) {
++ styleOp = new ops.OpApplyDirectStyling;
++ styleOp.init({memberid:inputMemberId, position:position, length:length, setProperties:directCursorStyleProperties});
++ directCursorStyleProperties = null;
++ updatedCachedValues()
++ }
++ return styleOp
++ };
++ function clearCursorStyle(op) {
++ var spec = op.spec();
++ if(directCursorStyleProperties && spec.memberid === inputMemberId) {
++ if(spec.optype !== "SplitParagraph") {
++ directCursorStyleProperties = null;
++ updatedCachedValues()
++ }
++ }
++ }
++ function setBold(checked) {
++ var value = checked ? "bold" : "normal";
++ applyTextPropertyToSelection("fo:font-weight", value)
++ }
++ this.setBold = setBold;
++ function setItalic(checked) {
++ var value = checked ? "italic" : "normal";
++ applyTextPropertyToSelection("fo:font-style", value)
++ }
++ this.setItalic = setItalic;
++ function setHasUnderline(checked) {
++ var value = checked ? "solid" : "none";
++ applyTextPropertyToSelection("style:text-underline-style", value)
++ }
++ this.setHasUnderline = setHasUnderline;
++ function setHasStrikethrough(checked) {
++ var value = checked ? "solid" : "none";
++ applyTextPropertyToSelection("style:text-line-through-style", value)
++ }
++ this.setHasStrikethrough = setHasStrikethrough;
++ function setFontSize(value) {
++ applyTextPropertyToSelection("fo:font-size", value + "pt")
++ }
++ this.setFontSize = setFontSize;
++ function setFontName(value) {
++ applyTextPropertyToSelection("style:font-name", value)
++ }
++ this.setFontName = setFontName;
++ this.getAppliedStyles = function() {
++ return currentSelectionStyles
++ };
++ this.toggleBold = toggle.bind(self, styleHelper.isBold, setBold);
++ this.toggleItalic = toggle.bind(self, styleHelper.isItalic, setItalic);
++ this.toggleUnderline = toggle.bind(self, styleHelper.hasUnderline, setHasUnderline);
++ this.toggleStrikethrough = toggle.bind(self, styleHelper.hasStrikeThrough, setHasStrikethrough);
++ this.isBold = function() {
++ return isBoldValue
++ };
++ this.isItalic = function() {
++ return isItalicValue
++ };
++ this.hasUnderline = function() {
++ return hasUnderlineValue
++ };
++ this.hasStrikeThrough = function() {
++ return hasStrikeThroughValue
++ };
++ this.fontSize = function() {
++ return fontSizeValue
++ };
++ this.fontName = function() {
++ return fontNameValue
++ };
++ this.subscribe = function(eventid, cb) {
++ eventNotifier.subscribe(eventid, cb)
++ };
++ this.unsubscribe = function(eventid, cb) {
++ eventNotifier.unsubscribe(eventid, cb)
++ };
++ this.destroy = function(callback) {
++ odtDocument.unsubscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
++ odtDocument.unsubscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
++ odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
++ odtDocument.unsubscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified);
++ odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged);
++ odtDocument.unsubscribe(ops.OdtDocument.signalOperationExecuted, clearCursorStyle);
++ callback()
++ };
++ function init() {
++ odtDocument.subscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
++ odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
++ odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
++ odtDocument.subscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified);
++ odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged);
++ odtDocument.subscribe(ops.OdtDocument.signalOperationExecuted, clearCursorStyle);
++ updatedCachedValues()
++ }
++ init()
++};
++gui.DirectTextStyler.textStylingChanged = "textStyling/changed";
++(function() {
++ return gui.DirectTextStyler
++})();
++runtime.loadClass("odf.Namespaces");
++runtime.loadClass("odf.ObjectNameGenerator");
++gui.ImageManager = function ImageManager(session, inputMemberId, objectNameGenerator) {
++ var cmPerPixel = 0.0264583333333334, fileExtensionByMimetype = {"image/gif":".gif", "image/jpeg":".jpg", "image/png":".png"}, textns = odf.Namespaces.textns, odtDocument = session.getOdtDocument(), formatting = odtDocument.getFormatting(), paragraphStyleToPageContentSizeMap = {};
++ function createAddGraphicsStyleOp(name) {
++ var op = new ops.OpAddStyle;
++ op.init({memberid:inputMemberId, styleName:name, styleFamily:"graphic", isAutomaticStyle:false, setProperties:{"style:graphic-properties":{"text:anchor-type":"paragraph", "svg:x":"0cm", "svg:y":"0cm", "style:wrap":"dynamic", "style:number-wrapped-paragraphs":"no-limit", "style:wrap-contour":"false", "style:vertical-pos":"top", "style:vertical-rel":"paragraph", "style:horizontal-pos":"center", "style:horizontal-rel":"paragraph"}}});
++ return op
++ }
++ function createAddFrameStyleOp(styleName, parentStyleName) {
++ var op = new ops.OpAddStyle;
++ op.init({memberid:inputMemberId, styleName:styleName, styleFamily:"graphic", isAutomaticStyle:true, setProperties:{"style:parent-style-name":parentStyleName, "style:graphic-properties":{"style:vertical-pos":"top", "style:vertical-rel":"baseline", "style:horizontal-pos":"center", "style:horizontal-rel":"paragraph", "fo:background-color":"transparent", "style:background-transparency":"100%", "style:shadow":"none", "style:mirror":"none", "fo:clip":"rect(0cm, 0cm, 0cm, 0cm)", "draw:lumi [...]
++ "draw:contrast":"0%", "draw:red":"0%", "draw:green":"0%", "draw:blue":"0%", "draw:gamma":"100%", "draw:color-inversion":"false", "draw:image-opacity":"100%", "draw:color-mode":"standard"}}});
++ return op
++ }
++ function getFileExtension(mimetype) {
++ mimetype = mimetype.toLowerCase();
++ return fileExtensionByMimetype.hasOwnProperty(mimetype) ? fileExtensionByMimetype[mimetype] : null
++ }
++ function insertImageInternal(mimetype, content, widthInCm, heightInCm) {
++ var graphicsStyleName = "Graphics", stylesElement = odtDocument.getOdfCanvas().odfContainer().rootElement.styles, fileExtension = getFileExtension(mimetype), fileName, graphicsStyleElement, frameStyleName, op, operations = [];
++ runtime.assert(fileExtension !== null, "Image type is not supported: " + mimetype);
++ fileName = "Pictures/" + objectNameGenerator.generateImageName() + fileExtension;
++ op = new ops.OpSetBlob;
++ op.init({memberid:inputMemberId, filename:fileName, mimetype:mimetype, content:content});
++ operations.push(op);
++ graphicsStyleElement = formatting.getStyleElement(graphicsStyleName, "graphic", [stylesElement]);
++ if(!graphicsStyleElement) {
++ op = createAddGraphicsStyleOp(graphicsStyleName);
++ operations.push(op)
++ }
++ frameStyleName = objectNameGenerator.generateStyleName();
++ op = createAddFrameStyleOp(frameStyleName, graphicsStyleName);
++ operations.push(op);
++ op = new ops.OpInsertImage;
++ op.init({memberid:inputMemberId, position:odtDocument.getCursorPosition(inputMemberId), filename:fileName, frameWidth:widthInCm + "cm", frameHeight:heightInCm + "cm", frameStyleName:frameStyleName, frameName:objectNameGenerator.generateFrameName()});
++ operations.push(op);
++ session.enqueue(operations)
++ }
++ function trimmedSize(originalSize, pageContentSize) {
++ var widthRatio = 1, heightRatio = 1, ratio;
++ if(originalSize.width > pageContentSize.width) {
++ widthRatio = pageContentSize.width / originalSize.width
+ }
- }
- function hideLocalCaret() {
- var caret = getCaret(sessionController.getInputMemberId());
- if(caret) {
- caret.hide()
++ if(originalSize.height > pageContentSize.height) {
++ heightRatio = pageContentSize.height / originalSize.height
+ }
++ ratio = Math.min(widthRatio, heightRatio);
++ return{width:originalSize.width * ratio, height:originalSize.height * ratio}
+ }
- this.registerCursor = function(cursor, caretAvatarInitiallyVisible, blinkOnRangeSelect) {
- var memberid = cursor.getMemberId(), caret = new gui.Caret(cursor, caretAvatarInitiallyVisible, blinkOnRangeSelect);
- carets[memberid] = caret;
- if(memberid === sessionController.getInputMemberId()) {
- runtime.log("Starting to track input on new cursor of " + memberid);
- cursor.handleUpdate = scheduleCaretVisibilityCheck;
- getCanvasElement().setAttribute("tabindex", -1);
- sessionController.getEventManager().focus()
- }else {
- cursor.handleUpdate = caret.handleUpdate
++ this.insertImage = function(mimetype, content, widthInPx, heightInPx) {
++ var paragraphElement, styleName, pageContentSize, originalSize, newSize;
++ runtime.assert(widthInPx > 0 && heightInPx > 0, "Both width and height of the image should be greater than 0px.");
++ paragraphElement = odtDocument.getParagraphElement(odtDocument.getCursor(inputMemberId).getNode());
++ styleName = paragraphElement.getAttributeNS(textns, "style-name");
++ if(!paragraphStyleToPageContentSizeMap.hasOwnProperty(styleName)) {
++ paragraphStyleToPageContentSizeMap[styleName] = formatting.getContentSize(styleName, "paragraph")
+ }
- return caret
- };
- this.getCaret = getCaret;
- this.getCarets = getCarets;
- this.destroy = function(callback) {
- var odtDocument = sessionController.getSession().getOdtDocument(), eventManager = sessionController.getEventManager(), caretArray = getCarets();
- odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, ensureLocalCaretVisible);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, refreshLocalCaretBlinking);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorRemoved, removeCaret);
- eventManager.unsubscribe("focus", focusLocalCaret);
- eventManager.unsubscribe("blur", blurLocalCaret);
- window.removeEventListener("focus", showLocalCaret, false);
- window.removeEventListener("blur", hideLocalCaret, false);
- (function destroyCaret(i, err) {
- if(err) {
- callback(err)
- }else {
- if(i < caretArray.length) {
- caretArray[i].destroy(function(err) {
- destroyCaret(i + 1, err)
- })
- }else {
- callback()
- }
- }
- })(0, undefined);
- carets = {}
- };
- function init() {
- var odtDocument = sessionController.getSession().getOdtDocument(), eventManager = sessionController.getEventManager();
- odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, ensureLocalCaretVisible);
- odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, refreshLocalCaretBlinking);
- odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, removeCaret);
- eventManager.subscribe("focus", focusLocalCaret);
- eventManager.subscribe("blur", blurLocalCaret);
- window.addEventListener("focus", showLocalCaret, false);
- window.addEventListener("blur", hideLocalCaret, false)
++ pageContentSize = paragraphStyleToPageContentSizeMap[styleName];
++ originalSize = {width:widthInPx * cmPerPixel, height:heightInPx * cmPerPixel};
++ newSize = trimmedSize(originalSize, pageContentSize);
++ insertImageInternal(mimetype, content, newSize.width, newSize.height)
+ }
- init()
- };
- /*
-
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- gui.UndoManager = function UndoManager() {
- };
- gui.UndoManager.prototype.subscribe = function(signal, callback) {
- };
- gui.UndoManager.prototype.unsubscribe = function(signal, callback) {
- };
- gui.UndoManager.prototype.setOdtDocument = function(newDocument) {
- };
- gui.UndoManager.prototype.saveInitialState = function() {
- };
- gui.UndoManager.prototype.resetInitialState = function() {
- };
- gui.UndoManager.prototype.setPlaybackFunction = function(playback_func) {
- };
- gui.UndoManager.prototype.hasUndoStates = function() {
- };
- gui.UndoManager.prototype.hasRedoStates = function() {
- };
- gui.UndoManager.prototype.moveForward = function(states) {
- };
- gui.UndoManager.prototype.moveBackward = function(states) {
+};
- gui.UndoManager.prototype.onOperationExecuted = function(op) {
- };
- gui.UndoManager.signalUndoStackChanged = "undoStackChanged";
- gui.UndoManager.signalUndoStateCreated = "undoStateCreated";
- gui.UndoManager.signalUndoStateModified = "undoStateModified";
- (function() {
- return gui.UndoManager
- })();
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- gui.UndoStateRules = function UndoStateRules() {
- function getOpType(op) {
- return op.spec().optype
++runtime.loadClass("core.PositionFilter");
++gui.TextManipulator = function TextManipulator(session, inputMemberId, directStyleOp) {
++ var odtDocument = session.getOdtDocument(), FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT;
++ function createOpRemoveSelection(selection) {
++ var op = new ops.OpRemoveText;
++ op.init({memberid:inputMemberId, position:selection.position, length:selection.length});
++ return op
+ }
- this.getOpType = getOpType;
- function getOpPosition(op) {
- return op.spec().position
++ function toForwardSelection(selection) {
++ if(selection.length < 0) {
++ selection.position += selection.length;
++ selection.length = -selection.length
++ }
++ return selection
+ }
- function isEditOperation(op) {
- return op.isEdit
++ this.enqueueParagraphSplittingOps = function() {
++ var selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op, operations = [];
++ if(selection.length > 0) {
++ op = createOpRemoveSelection(selection);
++ operations.push(op)
++ }
++ op = new ops.OpSplitParagraph;
++ op.init({memberid:inputMemberId, position:selection.position});
++ operations.push(op);
++ session.enqueue(operations);
++ return true
++ };
++ function hasPositionInDirection(cursorNode, forward) {
++ var rootConstrainedFilter = new core.PositionFilterChain, iterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootElement(cursorNode)), nextPosition = (forward ? iterator.nextPosition : iterator.previousPosition);
++ rootConstrainedFilter.addFilter("BaseFilter", odtDocument.getPositionFilter());
++ rootConstrainedFilter.addFilter("RootFilter", odtDocument.createRootFilter(inputMemberId));
++ iterator.setUnfilteredPosition(cursorNode, 0);
++ while(nextPosition()) {
++ if(rootConstrainedFilter.acceptPosition(iterator) === FILTER_ACCEPT) {
++ return true
++ }
++ }
++ return false
+ }
- this.isEditOperation = isEditOperation;
- function canAggregateOperation(optype) {
- switch(optype) {
- case "RemoveText":
- ;
- case "InsertText":
- return true;
- default:
- return false
++ this.removeTextByBackspaceKey = function() {
++ var cursor = odtDocument.getCursor(inputMemberId), selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op = null;
++ if(selection.length === 0) {
++ if(hasPositionInDirection(cursor.getNode(), false)) {
++ op = new ops.OpRemoveText;
++ op.init({memberid:inputMemberId, position:selection.position - 1, length:1});
++ session.enqueue([op])
++ }
++ }else {
++ op = createOpRemoveSelection(selection);
++ session.enqueue([op])
++ }
++ return op !== null
++ };
++ this.removeTextByDeleteKey = function() {
++ var cursor = odtDocument.getCursor(inputMemberId), selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op = null;
++ if(selection.length === 0) {
++ if(hasPositionInDirection(cursor.getNode(), true)) {
++ op = new ops.OpRemoveText;
++ op.init({memberid:inputMemberId, position:selection.position, length:1});
++ session.enqueue([op])
++ }
++ }else {
++ op = createOpRemoveSelection(selection);
++ session.enqueue([op])
++ }
++ return op !== null
++ };
++ this.removeCurrentSelection = function() {
++ var selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op;
++ if(selection.length !== 0) {
++ op = createOpRemoveSelection(selection);
++ session.enqueue([op])
++ }
++ return true
++ };
++ function insertText(text) {
++ var selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op, stylingOp, operations = [];
++ if(selection.length > 0) {
++ op = createOpRemoveSelection(selection);
++ operations.push(op)
++ }
++ op = new ops.OpInsertText;
++ op.init({memberid:inputMemberId, position:selection.position, text:text});
++ operations.push(op);
++ if(directStyleOp) {
++ stylingOp = directStyleOp(selection.position, text.length);
++ if(stylingOp) {
++ operations.push(stylingOp)
++ }
++ }
++ session.enqueue(operations)
++ }
++ this.insertText = insertText
++};
++(function() {
++ return gui.TextManipulator
++})();
++runtime.loadClass("core.DomUtils");
++runtime.loadClass("core.Async");
++runtime.loadClass("core.ScheduledTask");
++runtime.loadClass("odf.OdfUtils");
++runtime.loadClass("odf.ObjectNameGenerator");
++runtime.loadClass("ops.OdtCursor");
++runtime.loadClass("ops.OpAddCursor");
++runtime.loadClass("ops.OpRemoveCursor");
++runtime.loadClass("gui.Clipboard");
++runtime.loadClass("gui.DirectTextStyler");
++runtime.loadClass("gui.DirectParagraphStyler");
++runtime.loadClass("gui.KeyboardHandler");
++runtime.loadClass("gui.ImageManager");
++runtime.loadClass("gui.ImageSelector");
++runtime.loadClass("gui.TextManipulator");
++runtime.loadClass("gui.AnnotationController");
++runtime.loadClass("gui.EventManager");
++runtime.loadClass("gui.PlainTextPasteboard");
++gui.SessionController = function() {
++ var FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT;
++ gui.SessionController = function SessionController(session, inputMemberId, shadowCursor, args) {
++ var window = (runtime.getWindow()), odtDocument = session.getOdtDocument(), async = new core.Async, domUtils = new core.DomUtils, odfUtils = new odf.OdfUtils, clipboard = new gui.Clipboard, keyDownHandler = new gui.KeyboardHandler, keyPressHandler = new gui.KeyboardHandler, keyboardMovementsFilter = new core.PositionFilterChain, baseFilter = odtDocument.getPositionFilter(), clickStartedWithinContainer = false, objectNameGenerator = new odf.ObjectNameGenerator(odtDocument.getOdfCanva [...]
++ inputMemberId), isMouseMoved = false, mouseDownRootFilter = null, undoManager = null, eventManager = new gui.EventManager(odtDocument), annotationController = new gui.AnnotationController(session, inputMemberId), directTextStyler = new gui.DirectTextStyler(session, inputMemberId), directParagraphStyler = args && args.directParagraphStylingEnabled ? new gui.DirectParagraphStyler(session, inputMemberId, objectNameGenerator) : null, createCursorStyleOp = (directTextStyler.createCursorS [...]
++ new gui.TextManipulator(session, inputMemberId, createCursorStyleOp), imageManager = new gui.ImageManager(session, inputMemberId, objectNameGenerator), imageSelector = new gui.ImageSelector(odtDocument.getOdfCanvas()), shadowCursorIterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode()), drawShadowCursorTask, suppressFocusEvent = false, redrawRegionSelectionTask, pasteHandler = new gui.PlainTextPasteboard(odtDocument, inputMemberId), clickCount = 0;
++ runtime.assert(window !== null, "Expected to be run in an environment which has a global window, like a browser.");
++ keyboardMovementsFilter.addFilter("BaseFilter", baseFilter);
++ keyboardMovementsFilter.addFilter("RootFilter", odtDocument.createRootFilter(inputMemberId));
++ function getTarget(e) {
++ return e.target || e.srcElement
+ }
- }
- function isSameDirectionOfTravel(recentEditOps, thisOp) {
- var existing1 = getOpPosition(recentEditOps[recentEditOps.length - 2]), existing2 = getOpPosition(recentEditOps[recentEditOps.length - 1]), thisPos = getOpPosition(thisOp), direction = existing2 - existing1;
- return existing2 === thisPos - direction
- }
- function isContinuousOperation(recentEditOps, thisOp) {
- var optype = getOpType(thisOp);
- if(canAggregateOperation(optype) && optype === getOpType(recentEditOps[0])) {
- if(recentEditOps.length === 1) {
- return true
++ function cancelEvent(event) {
++ if(event.preventDefault) {
++ event.preventDefault()
++ }else {
++ event.returnValue = false
+ }
- if(isSameDirectionOfTravel(recentEditOps, thisOp)) {
- return true
++ }
++ function dummyHandler(e) {
++ cancelEvent(e)
++ }
++ function createOpMoveCursor(position, length, selectionType) {
++ var op = new ops.OpMoveCursor;
++ op.init({memberid:inputMemberId, position:position, length:length || 0, selectionType:selectionType});
++ return op
++ }
++ function caretPositionFromPoint(x, y) {
++ var doc = odtDocument.getDOM(), c, result = null;
++ if(doc.caretRangeFromPoint) {
++ c = doc.caretRangeFromPoint(x, y);
++ result = {container:c.startContainer, offset:c.startOffset}
++ }else {
++ if(doc.caretPositionFromPoint) {
++ c = doc.caretPositionFromPoint(x, y);
++ if(c && c.offsetNode) {
++ result = {container:c.offsetNode, offset:c.offset}
++ }
++ }
+ }
++ return result
+ }
- return false
- }
- function isPartOfOperationSet(operation, lastOperations) {
- if(isEditOperation(operation)) {
- if(lastOperations.length === 0) {
- return true
++ function expandToWordBoundaries(range) {
++ var alphaNumeric = /[A-Za-z0-9]/, iterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode()), currentNode, c;
++ iterator.setUnfilteredPosition((range.startContainer), range.startOffset);
++ while(iterator.previousPosition()) {
++ currentNode = iterator.getCurrentNode();
++ if(currentNode.nodeType === Node.TEXT_NODE) {
++ c = currentNode.data[iterator.unfilteredDomOffset()];
++ if(!alphaNumeric.test(c)) {
++ break
++ }
++ }else {
++ if(!odfUtils.isTextSpan(currentNode)) {
++ break
++ }
++ }
++ range.setStart(iterator.container(), iterator.unfilteredDomOffset())
+ }
- return isEditOperation(lastOperations[lastOperations.length - 1]) && isContinuousOperation(lastOperations.filter(isEditOperation), operation)
++ iterator.setUnfilteredPosition((range.endContainer), range.endOffset);
++ do {
++ currentNode = iterator.getCurrentNode();
++ if(currentNode.nodeType === Node.TEXT_NODE) {
++ c = currentNode.data[iterator.unfilteredDomOffset()];
++ if(!alphaNumeric.test(c)) {
++ break
++ }
++ }else {
++ if(!odfUtils.isTextSpan(currentNode)) {
++ break
++ }
++ }
++ }while(iterator.nextPosition());
++ range.setEnd(iterator.container(), iterator.unfilteredDomOffset())
+ }
- return true
- }
- this.isPartOfOperationSet = isPartOfOperationSet
- };
- /*
-
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- runtime.loadClass("core.DomUtils");
- runtime.loadClass("gui.UndoManager");
- runtime.loadClass("gui.UndoStateRules");
- gui.TrivialUndoManager = function TrivialUndoManager(defaultRules) {
- var self = this, cursorns = "urn:webodf:names:cursor", domUtils = new core.DomUtils, initialDoc, initialState = [], playFunc, odtDocument, currentUndoState = [], undoStates = [], redoStates = [], eventNotifier = new core.EventNotifier([gui.UndoManager.signalUndoStackChanged, gui.UndoManager.signalUndoStateCreated, gui.UndoManager.signalUndoStateModified, gui.TrivialUndoManager.signalDocumentRootReplaced]), undoRules = defaultRules || new gui.UndoStateRules;
- function emitStackChange() {
- eventNotifier.emit(gui.UndoManager.signalUndoStackChanged, {undoAvailable:self.hasUndoStates(), redoAvailable:self.hasRedoStates()})
- }
- function mostRecentUndoState() {
- return undoStates[undoStates.length - 1]
- }
- function completeCurrentUndoState() {
- if(currentUndoState !== initialState && currentUndoState !== mostRecentUndoState()) {
- undoStates.push(currentUndoState)
++ function expandToParagraphBoundaries(range) {
++ var startParagraph = odtDocument.getParagraphElement(range.startContainer), endParagraph = odtDocument.getParagraphElement(range.endContainer);
++ if(startParagraph) {
++ range.setStart(startParagraph, 0)
++ }
++ if(endParagraph) {
++ if(odfUtils.isParagraph(range.endContainer) && range.endOffset === 0) {
++ range.setEndBefore(endParagraph)
++ }else {
++ range.setEnd(endParagraph, endParagraph.childNodes.length)
++ }
++ }
+ }
- }
- function removeNode(node) {
- var sibling = node.previousSibling || node.nextSibling;
- node.parentNode.removeChild(node);
- domUtils.normalizeTextNodes(sibling)
- }
- function removeCursors(root) {
- domUtils.getElementsByTagNameNS(root, cursorns, "cursor").forEach(removeNode);
- domUtils.getElementsByTagNameNS(root, cursorns, "anchor").forEach(removeNode)
- }
- function values(obj) {
- return Object.keys(obj).map(function(key) {
- return obj[key]
- })
- }
- function extractCursorStates(undoStates) {
- var addCursor = {}, moveCursor = {}, requiredAddOps = {}, remainingAddOps, operations = undoStates.pop();
- odtDocument.getCursors().forEach(function(cursor) {
- requiredAddOps[cursor.getMemberId()] = true
- });
- remainingAddOps = Object.keys(requiredAddOps).length;
- function processOp(op) {
- var spec = op.spec();
- if(!requiredAddOps[spec.memberid]) {
++ function selectImage(frameNode) {
++ var stepsToAnchor = odtDocument.getDistanceFromCursor(inputMemberId, frameNode, 0), stepsToFocus = stepsToAnchor !== null ? stepsToAnchor + 1 : null, oldPosition, op;
++ if(stepsToFocus || stepsToAnchor) {
++ oldPosition = odtDocument.getCursorPosition(inputMemberId);
++ op = createOpMoveCursor(oldPosition + stepsToAnchor, stepsToFocus - stepsToAnchor, ops.OdtCursor.RegionSelection);
++ session.enqueue([op])
++ }
++ eventManager.focus()
++ }
++ function selectionToRange(selection) {
++ var hasForwardSelection = domUtils.comparePoints((selection.anchorNode), selection.anchorOffset, (selection.focusNode), selection.focusOffset) >= 0, range = selection.focusNode.ownerDocument.createRange();
++ if(hasForwardSelection) {
++ range.setStart(selection.anchorNode, selection.anchorOffset);
++ range.setEnd(selection.focusNode, selection.focusOffset)
++ }else {
++ range.setStart(selection.focusNode, selection.focusOffset);
++ range.setEnd(selection.anchorNode, selection.anchorOffset)
++ }
++ return{range:range, hasForwardSelection:hasForwardSelection}
++ }
++ function rangeToSelection(range, hasForwardSelection) {
++ if(hasForwardSelection) {
++ return{anchorNode:(range.startContainer), anchorOffset:range.startOffset, focusNode:(range.endContainer), focusOffset:range.endOffset}
++ }
++ return{anchorNode:(range.endContainer), anchorOffset:range.endOffset, focusNode:(range.startContainer), focusOffset:range.startOffset}
++ }
++ function constrain(lookup) {
++ return function(originalNode) {
++ var originalContainer = lookup(originalNode);
++ return function(step, node) {
++ return lookup(node) === originalContainer
++ }
++ }
++ }
++ function selectRange(range, hasForwardSelection, clickCount) {
++ var canvasElement = odtDocument.getOdfCanvas().getElement(), validSelection, startInsideCanvas, endInsideCanvas, existingSelection, newSelection, op;
++ startInsideCanvas = domUtils.containsNode(canvasElement, range.startContainer);
++ endInsideCanvas = domUtils.containsNode(canvasElement, range.endContainer);
++ if(!startInsideCanvas && !endInsideCanvas) {
+ return
+ }
- switch(spec.optype) {
- case "AddCursor":
- if(!addCursor[spec.memberid]) {
- addCursor[spec.memberid] = op;
- delete requiredAddOps[spec.memberid];
- remainingAddOps -= 1
- }
- break;
- case "MoveCursor":
- if(!moveCursor[spec.memberid]) {
- moveCursor[spec.memberid] = op
++ if(startInsideCanvas && endInsideCanvas) {
++ if(clickCount === 2) {
++ expandToWordBoundaries(range)
++ }else {
++ if(clickCount >= 3) {
++ expandToParagraphBoundaries(range)
+ }
- break
++ }
++ }
++ validSelection = rangeToSelection(range, hasForwardSelection);
++ newSelection = odtDocument.convertDomToCursorRange(validSelection, constrain(odfUtils.getParagraphElement));
++ existingSelection = odtDocument.getCursorSelection(inputMemberId);
++ if(newSelection.position !== existingSelection.position || newSelection.length !== existingSelection.length) {
++ op = createOpMoveCursor(newSelection.position, newSelection.length, ops.OdtCursor.RangeSelection);
++ session.enqueue([op])
++ }
++ eventManager.focus()
++ }
++ this.selectRange = selectRange;
++ function extendCursorByAdjustment(lengthAdjust) {
++ var selection = odtDocument.getCursorSelection(inputMemberId), stepCounter = odtDocument.getCursor(inputMemberId).getStepCounter(), newLength;
++ if(lengthAdjust !== 0) {
++ lengthAdjust = lengthAdjust > 0 ? stepCounter.convertForwardStepsBetweenFilters(lengthAdjust, keyboardMovementsFilter, baseFilter) : -stepCounter.convertBackwardStepsBetweenFilters(-lengthAdjust, keyboardMovementsFilter, baseFilter);
++ newLength = selection.length + lengthAdjust;
++ session.enqueue([createOpMoveCursor(selection.position, newLength)])
++ }
++ }
++ function moveCursorByAdjustment(positionAdjust) {
++ var position = odtDocument.getCursorPosition(inputMemberId), stepCounter = odtDocument.getCursor(inputMemberId).getStepCounter();
++ if(positionAdjust !== 0) {
++ positionAdjust = positionAdjust > 0 ? stepCounter.convertForwardStepsBetweenFilters(positionAdjust, keyboardMovementsFilter, baseFilter) : -stepCounter.convertBackwardStepsBetweenFilters(-positionAdjust, keyboardMovementsFilter, baseFilter);
++ position = position + positionAdjust;
++ session.enqueue([createOpMoveCursor(position, 0)])
++ }
++ }
++ function moveCursorToLeft() {
++ moveCursorByAdjustment(-1);
++ return true
++ }
++ this.moveCursorToLeft = moveCursorToLeft;
++ function moveCursorToRight() {
++ moveCursorByAdjustment(1);
++ return true
++ }
++ function extendSelectionToLeft() {
++ extendCursorByAdjustment(-1);
++ return true
++ }
++ function extendSelectionToRight() {
++ extendCursorByAdjustment(1);
++ return true
++ }
++ function moveCursorByLine(direction, extend) {
++ var paragraphNode = odtDocument.getParagraphElement(odtDocument.getCursor(inputMemberId).getNode()), steps;
++ runtime.assert(Boolean(paragraphNode), "SessionController: Cursor outside paragraph");
++ steps = odtDocument.getCursor(inputMemberId).getStepCounter().countLinesSteps(direction, keyboardMovementsFilter);
++ if(extend) {
++ extendCursorByAdjustment(steps)
++ }else {
++ moveCursorByAdjustment(steps)
+ }
+ }
- while(operations && remainingAddOps > 0) {
- operations.reverse();
- operations.forEach(processOp);
- operations = undoStates.pop()
++ function moveCursorUp() {
++ moveCursorByLine(-1, false);
++ return true
++ }
++ function moveCursorDown() {
++ moveCursorByLine(1, false);
++ return true
++ }
++ function extendSelectionUp() {
++ moveCursorByLine(-1, true);
++ return true
+ }
- return values(addCursor).concat(values(moveCursor))
- }
- this.subscribe = function(signal, callback) {
- eventNotifier.subscribe(signal, callback)
- };
- this.unsubscribe = function(signal, callback) {
- eventNotifier.unsubscribe(signal, callback)
- };
- this.hasUndoStates = function() {
- return undoStates.length > 0
- };
- this.hasRedoStates = function() {
- return redoStates.length > 0
- };
- this.setOdtDocument = function(newDocument) {
- odtDocument = newDocument
- };
- this.resetInitialState = function() {
- undoStates.length = 0;
- redoStates.length = 0;
- initialState.length = 0;
- currentUndoState.length = 0;
- initialDoc = null;
- emitStackChange()
- };
- this.saveInitialState = function() {
- var odfContainer = odtDocument.getOdfCanvas().odfContainer(), annotationViewManager = odtDocument.getOdfCanvas().getAnnotationViewManager();
- if(annotationViewManager) {
- annotationViewManager.forgetAnnotations()
++ function extendSelectionDown() {
++ moveCursorByLine(1, true);
++ return true
+ }
- initialDoc = odfContainer.rootElement.cloneNode(true);
- odtDocument.getOdfCanvas().refreshAnnotations();
- removeCursors(initialDoc);
- completeCurrentUndoState();
- undoStates.unshift(initialState);
- currentUndoState = initialState = extractCursorStates(undoStates);
- undoStates.length = 0;
- redoStates.length = 0;
- emitStackChange()
- };
- this.setPlaybackFunction = function(playback_func) {
- playFunc = playback_func
- };
- this.onOperationExecuted = function(op) {
- redoStates.length = 0;
- if(undoRules.isEditOperation(op) && currentUndoState === initialState || !undoRules.isPartOfOperationSet(op, currentUndoState)) {
- completeCurrentUndoState();
- currentUndoState = [op];
- undoStates.push(currentUndoState);
- eventNotifier.emit(gui.UndoManager.signalUndoStateCreated, {operations:currentUndoState});
- emitStackChange()
- }else {
- currentUndoState.push(op);
- eventNotifier.emit(gui.UndoManager.signalUndoStateModified, {operations:currentUndoState})
++ function moveCursorToLineBoundary(direction, extend) {
++ var steps = odtDocument.getCursor(inputMemberId).getStepCounter().countStepsToLineBoundary(direction, keyboardMovementsFilter);
++ if(extend) {
++ extendCursorByAdjustment(steps)
++ }else {
++ moveCursorByAdjustment(steps)
++ }
+ }
- };
- this.moveForward = function(states) {
- var moved = 0, redoOperations;
- while(states && redoStates.length) {
- redoOperations = redoStates.pop();
- undoStates.push(redoOperations);
- redoOperations.forEach(playFunc);
- states -= 1;
- moved += 1
++ function moveCursorToLineStart() {
++ moveCursorToLineBoundary(-1, false);
++ return true
+ }
- if(moved) {
- currentUndoState = mostRecentUndoState();
- emitStackChange()
++ function moveCursorToLineEnd() {
++ moveCursorToLineBoundary(1, false);
++ return true
+ }
- return moved
- };
- this.moveBackward = function(states) {
- var odfCanvas = odtDocument.getOdfCanvas(), odfContainer = odfCanvas.odfContainer(), moved = 0;
- while(states && undoStates.length) {
- redoStates.push(undoStates.pop());
- states -= 1;
- moved += 1
++ function extendSelectionToLineStart() {
++ moveCursorToLineBoundary(-1, true);
++ return true
+ }
- if(moved) {
- odfContainer.setRootElement(initialDoc.cloneNode(true));
- odfCanvas.setOdfContainer(odfContainer, true);
- eventNotifier.emit(gui.TrivialUndoManager.signalDocumentRootReplaced, {});
- odtDocument.getCursors().forEach(function(cursor) {
- odtDocument.removeCursor(cursor.getMemberId())
- });
- initialState.forEach(playFunc);
- undoStates.forEach(function(ops) {
- ops.forEach(playFunc)
- });
- odfCanvas.refreshCSS();
- currentUndoState = mostRecentUndoState() || initialState;
- emitStackChange()
++ function extendSelectionToLineEnd() {
++ moveCursorToLineBoundary(1, true);
++ return true
+ }
- return moved
- }
- };
- gui.TrivialUndoManager.signalDocumentRootReplaced = "documentRootReplaced";
- (function() {
- return gui.TrivialUndoManager
- })();
- runtime.loadClass("core.DomUtils");
- runtime.loadClass("odf.OdfUtils");
- runtime.loadClass("odf.OdfNodeFilter");
- runtime.loadClass("gui.SelectionMover");
- gui.SelectionView = function SelectionView(cursor) {
- var odtDocument = cursor.getOdtDocument(), documentRoot, root, doc = odtDocument.getDOM(), overlayTop = doc.createElement("div"), overlayMiddle = doc.createElement("div"), overlayBottom = doc.createElement("div"), odfUtils = new odf.OdfUtils, domUtils = new core.DomUtils, isVisible = true, positionIterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode()), FILTER_ACCEPT = NodeFilter.FILTER_ACCEPT, FILTER_REJECT = NodeFilter.FILTER_REJECT;
- function addOverlays() {
- var newDocumentRoot = odtDocument.getRootNode();
- if(documentRoot !== newDocumentRoot) {
- documentRoot = newDocumentRoot;
- root = documentRoot.parentNode.parentNode.parentNode;
- root.appendChild(overlayTop);
- root.appendChild(overlayMiddle);
- root.appendChild(overlayBottom)
++ function extendSelectionToParagraphStart() {
++ var paragraphNode = (odtDocument.getParagraphElement(odtDocument.getCursor(inputMemberId).getNode())), iterator, node, steps;
++ runtime.assert(Boolean(paragraphNode), "SessionController: Cursor outside paragraph");
++ steps = odtDocument.getDistanceFromCursor(inputMemberId, paragraphNode, 0);
++ iterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode());
++ iterator.setUnfilteredPosition(paragraphNode, 0);
++ while(steps === 0 && iterator.previousPosition()) {
++ node = iterator.getCurrentNode();
++ if(odfUtils.isParagraph(node)) {
++ steps = odtDocument.getDistanceFromCursor(inputMemberId, node, 0)
++ }
++ }
++ extendCursorByAdjustment(steps);
++ return true
+ }
- }
- function setRect(div, rect) {
- div.style.left = rect.left + "px";
- div.style.top = rect.top + "px";
- div.style.width = rect.width + "px";
- div.style.height = rect.height + "px"
- }
- function showOverlays(choice) {
- var display;
- isVisible = choice;
- display = choice === true ? "block" : "none";
- overlayTop.style.display = overlayMiddle.style.display = overlayBottom.style.display = display
- }
- function translateRect(rect) {
- var rootRect = domUtils.getBoundingClientRect(root), zoomLevel = odtDocument.getOdfCanvas().getZoomLevel(), resultRect = {};
- resultRect.top = domUtils.adaptRangeDifferenceToZoomLevel(rect.top - rootRect.top, zoomLevel);
- resultRect.left = domUtils.adaptRangeDifferenceToZoomLevel(rect.left - rootRect.left, zoomLevel);
- resultRect.bottom = domUtils.adaptRangeDifferenceToZoomLevel(rect.bottom - rootRect.top, zoomLevel);
- resultRect.right = domUtils.adaptRangeDifferenceToZoomLevel(rect.right - rootRect.left, zoomLevel);
- resultRect.width = domUtils.adaptRangeDifferenceToZoomLevel(rect.width, zoomLevel);
- resultRect.height = domUtils.adaptRangeDifferenceToZoomLevel(rect.height, zoomLevel);
- return resultRect
- }
- function isRangeVisible(range) {
- var bcr = range.getBoundingClientRect();
- return Boolean(bcr && bcr.height !== 0)
- }
- function lastVisibleRect(range, nodes) {
- var nextNodeIndex = nodes.length - 1, node = nodes[nextNodeIndex], startOffset = range.endContainer === node ? range.endOffset : node.length || node.childNodes.length, endOffset = startOffset;
- range.setStart(node, startOffset);
- range.setEnd(node, endOffset);
- while(!isRangeVisible(range)) {
- if(node.nodeType === Node.ELEMENT_NODE && startOffset > 0) {
- startOffset = 0
++ function extendSelectionToParagraphEnd() {
++ var paragraphNode = (odtDocument.getParagraphElement(odtDocument.getCursor(inputMemberId).getNode())), iterator, node, steps;
++ runtime.assert(Boolean(paragraphNode), "SessionController: Cursor outside paragraph");
++ iterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode());
++ iterator.moveToEndOfNode(paragraphNode);
++ steps = odtDocument.getDistanceFromCursor(inputMemberId, iterator.container(), iterator.unfilteredDomOffset());
++ while(steps === 0 && iterator.nextPosition()) {
++ node = iterator.getCurrentNode();
++ if(odfUtils.isParagraph(node)) {
++ iterator.moveToEndOfNode(node);
++ steps = odtDocument.getDistanceFromCursor(inputMemberId, iterator.container(), iterator.unfilteredDomOffset())
++ }
++ }
++ extendCursorByAdjustment(steps);
++ return true
++ }
++ function moveCursorToDocumentBoundary(direction, extend) {
++ var iterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode()), steps;
++ if(direction > 0) {
++ iterator.moveToEnd()
++ }
++ steps = odtDocument.getDistanceFromCursor(inputMemberId, iterator.container(), iterator.unfilteredDomOffset());
++ if(extend) {
++ extendCursorByAdjustment(steps)
+ }else {
- if(node.nodeType === Node.TEXT_NODE && startOffset > 0) {
- startOffset -= 1
- }else {
- if(nodes[nextNodeIndex]) {
- node = nodes[nextNodeIndex];
- nextNodeIndex -= 1;
- startOffset = endOffset = node.length || node.childNodes.length
++ moveCursorByAdjustment(steps)
++ }
++ }
++ this.moveCursorToDocumentBoundary = moveCursorToDocumentBoundary;
++ function moveCursorToDocumentStart() {
++ moveCursorToDocumentBoundary(-1, false);
++ return true
++ }
++ function moveCursorToDocumentEnd() {
++ moveCursorToDocumentBoundary(1, false);
++ return true
++ }
++ function extendSelectionToDocumentStart() {
++ moveCursorToDocumentBoundary(-1, true);
++ return true
++ }
++ function extendSelectionToDocumentEnd() {
++ moveCursorToDocumentBoundary(1, true);
++ return true
++ }
++ function extendSelectionToEntireDocument() {
++ var rootNode = odtDocument.getRootNode(), lastWalkableStep = odtDocument.convertDomPointToCursorStep(rootNode, rootNode.childNodes.length);
++ session.enqueue([createOpMoveCursor(0, lastWalkableStep)]);
++ return true
++ }
++ this.extendSelectionToEntireDocument = extendSelectionToEntireDocument;
++ function maintainCursorSelection() {
++ var cursor = odtDocument.getCursor(inputMemberId), selection = window.getSelection(), imageElement, range;
++ if(cursor) {
++ imageSelector.clearSelection();
++ if(cursor.getSelectionType() === ops.OdtCursor.RegionSelection) {
++ range = cursor.getSelectedRange();
++ imageElement = odfUtils.getImageElements(range)[0];
++ if(imageElement) {
++ imageSelector.select((imageElement.parentNode))
++ }
++ }
++ if(eventManager.hasFocus()) {
++ range = cursor.getSelectedRange();
++ if(selection.extend) {
++ if(cursor.hasForwardSelection()) {
++ selection.collapse(range.startContainer, range.startOffset);
++ selection.extend(range.endContainer, range.endOffset)
++ }else {
++ selection.collapse(range.endContainer, range.endOffset);
++ selection.extend(range.startContainer, range.startOffset)
++ }
+ }else {
- return false
++ suppressFocusEvent = true;
++ selection.removeAllRanges();
++ selection.addRange(range.cloneRange());
++ (odtDocument.getOdfCanvas().getElement()).setActive();
++ runtime.setTimeout(function() {
++ suppressFocusEvent = false
++ }, 0)
+ }
+ }
- }
- range.setStart(node, startOffset);
- range.setEnd(node, endOffset)
- }
- return true
- }
- function firstVisibleRect(range, nodes) {
- var nextNodeIndex = 0, node = nodes[nextNodeIndex], startOffset = range.startContainer === node ? range.startOffset : 0, endOffset = startOffset;
- range.setStart(node, startOffset);
- range.setEnd(node, endOffset);
- while(!isRangeVisible(range)) {
- if(node.nodeType === Node.ELEMENT_NODE && endOffset < node.childNodes.length) {
- endOffset = node.childNodes.length
+ }else {
- if(node.nodeType === Node.TEXT_NODE && endOffset < node.length) {
- endOffset += 1
- }else {
- if(nodes[nextNodeIndex]) {
- node = nodes[nextNodeIndex];
- nextNodeIndex += 1;
- startOffset = endOffset = 0
- }else {
- return false
- }
- }
++ imageSelector.clearSelection()
+ }
- range.setStart(node, startOffset);
- range.setEnd(node, endOffset)
- }
- return true
- }
- function getExtremeRanges(range) {
- var nodes = odfUtils.getTextElements(range, true, false), firstRange = (range.cloneRange()), lastRange = (range.cloneRange()), fillerRange = range.cloneRange();
- if(!nodes.length) {
- return null
+ }
- if(!firstVisibleRect(firstRange, nodes)) {
- return null
++ function delayedMaintainCursor() {
++ if(suppressFocusEvent === false) {
++ runtime.setTimeout(maintainCursorSelection, 0)
++ }
+ }
- if(!lastVisibleRect(lastRange, nodes)) {
++ function stringFromKeyPress(event) {
++ if(event.which === null || event.which === undefined) {
++ return String.fromCharCode(event.keyCode)
++ }
++ if(event.which !== 0 && event.charCode !== 0) {
++ return String.fromCharCode(event.which)
++ }
+ return null
+ }
- fillerRange.setStart(firstRange.startContainer, firstRange.startOffset);
- fillerRange.setEnd(lastRange.endContainer, lastRange.endOffset);
- return{firstRange:firstRange, lastRange:lastRange, fillerRange:fillerRange}
- }
- function getBoundingRect(rect1, rect2) {
- var resultRect = {};
- resultRect.top = Math.min(rect1.top, rect2.top);
- resultRect.left = Math.min(rect1.left, rect2.left);
- resultRect.right = Math.max(rect1.right, rect2.right);
- resultRect.bottom = Math.max(rect1.bottom, rect2.bottom);
- resultRect.width = resultRect.right - resultRect.left;
- resultRect.height = resultRect.bottom - resultRect.top;
- return resultRect
- }
- function checkAndGrowOrCreateRect(originalRect, newRect) {
- if(newRect && (newRect.width > 0 && newRect.height > 0)) {
- if(!originalRect) {
- originalRect = newRect
++ function handleCut(e) {
++ var cursor = odtDocument.getCursor(inputMemberId), selectedRange = cursor.getSelectedRange();
++ if(selectedRange.collapsed) {
++ return
++ }
++ if(clipboard.setDataFromRange(e, selectedRange)) {
++ textManipulator.removeCurrentSelection()
+ }else {
- originalRect = getBoundingRect(originalRect, newRect)
++ runtime.log("Cut operation failed")
+ }
+ }
- return originalRect
- }
- function getFillerRect(fillerRange) {
- var containerNode = fillerRange.commonAncestorContainer, firstNode = fillerRange.startContainer, lastNode = fillerRange.endContainer, firstOffset = fillerRange.startOffset, lastOffset = fillerRange.endOffset, currentNode, lastMeasuredNode, firstSibling, lastSibling, grownRect = null, currentRect, range = doc.createRange(), rootFilter, odfNodeFilter = new odf.OdfNodeFilter, treeWalker;
- function acceptNode(node) {
- positionIterator.setUnfilteredPosition(node, 0);
- if(odfNodeFilter.acceptNode(node) === FILTER_ACCEPT && rootFilter.acceptPosition(positionIterator) === FILTER_ACCEPT) {
- return FILTER_ACCEPT
- }
- return FILTER_REJECT
++ function handleBeforeCut() {
++ var cursor = odtDocument.getCursor(inputMemberId), selectedRange = cursor.getSelectedRange();
++ return selectedRange.collapsed !== false
+ }
- function getRectFromNodeAfterFiltering(node) {
- var rect = null;
- if(acceptNode(node) === FILTER_ACCEPT) {
- rect = domUtils.getBoundingClientRect(node)
++ function handleCopy(e) {
++ var cursor = odtDocument.getCursor(inputMemberId), selectedRange = cursor.getSelectedRange();
++ if(selectedRange.collapsed) {
++ return
++ }
++ if(!clipboard.setDataFromRange(e, selectedRange)) {
++ runtime.log("Cut operation failed")
+ }
- return rect
- }
- if(firstNode === containerNode || lastNode === containerNode) {
- range = fillerRange.cloneRange();
- grownRect = range.getBoundingClientRect();
- range.detach();
- return grownRect
- }
- firstSibling = firstNode;
- while(firstSibling.parentNode !== containerNode) {
- firstSibling = firstSibling.parentNode
- }
- lastSibling = lastNode;
- while(lastSibling.parentNode !== containerNode) {
- lastSibling = lastSibling.parentNode
- }
- rootFilter = odtDocument.createRootFilter(firstNode);
- currentNode = firstSibling.nextSibling;
- while(currentNode && currentNode !== lastSibling) {
- currentRect = getRectFromNodeAfterFiltering(currentNode);
- grownRect = checkAndGrowOrCreateRect(grownRect, currentRect);
- currentNode = currentNode.nextSibling
+ }
- if(odfUtils.isParagraph(firstSibling)) {
- grownRect = checkAndGrowOrCreateRect(grownRect, domUtils.getBoundingClientRect(firstSibling))
- }else {
- if(firstSibling.nodeType === Node.TEXT_NODE) {
- currentNode = firstSibling;
- range.setStart(currentNode, firstOffset);
- range.setEnd(currentNode, currentNode === lastSibling ? lastOffset : currentNode.length);
- currentRect = range.getBoundingClientRect();
- grownRect = checkAndGrowOrCreateRect(grownRect, currentRect)
++ function handlePaste(e) {
++ var plainText;
++ if(window.clipboardData && window.clipboardData.getData) {
++ plainText = window.clipboardData.getData("Text")
+ }else {
- treeWalker = doc.createTreeWalker(firstSibling, NodeFilter.SHOW_TEXT, acceptNode, false);
- currentNode = treeWalker.currentNode = firstNode;
- while(currentNode && currentNode !== lastNode) {
- range.setStart(currentNode, firstOffset);
- range.setEnd(currentNode, currentNode.length);
- currentRect = range.getBoundingClientRect();
- grownRect = checkAndGrowOrCreateRect(grownRect, currentRect);
- lastMeasuredNode = currentNode;
- firstOffset = 0;
- currentNode = treeWalker.nextNode()
++ if(e.clipboardData && e.clipboardData.getData) {
++ plainText = e.clipboardData.getData("text/plain")
+ }
+ }
++ if(plainText) {
++ textManipulator.removeCurrentSelection();
++ session.enqueue(pasteHandler.createPasteOps(plainText));
++ cancelEvent(e)
++ }
+ }
- if(!lastMeasuredNode) {
- lastMeasuredNode = firstNode
++ function handleBeforePaste() {
++ return false
+ }
- if(odfUtils.isParagraph(lastSibling)) {
- grownRect = checkAndGrowOrCreateRect(grownRect, domUtils.getBoundingClientRect(lastSibling))
- }else {
- if(lastSibling.nodeType === Node.TEXT_NODE) {
- currentNode = lastSibling;
- range.setStart(currentNode, currentNode === firstSibling ? firstOffset : 0);
- range.setEnd(currentNode, lastOffset);
- currentRect = range.getBoundingClientRect();
- grownRect = checkAndGrowOrCreateRect(grownRect, currentRect)
- }else {
- treeWalker = doc.createTreeWalker(lastSibling, NodeFilter.SHOW_TEXT, acceptNode, false);
- currentNode = treeWalker.currentNode = lastNode;
- while(currentNode && currentNode !== lastMeasuredNode) {
- range.setStart(currentNode, 0);
- range.setEnd(currentNode, lastOffset);
- currentRect = range.getBoundingClientRect();
- grownRect = checkAndGrowOrCreateRect(grownRect, currentRect);
- currentNode = treeWalker.previousNode();
- if(currentNode) {
- lastOffset = currentNode.length
- }
- }
++ function updateUndoStack(op) {
++ if(undoManager) {
++ undoManager.onOperationExecuted(op)
+ }
+ }
- return grownRect
- }
- function getCollapsedRectOfTextRange(range, useRightEdge) {
- var clientRect = range.getBoundingClientRect(), collapsedRect = {};
- collapsedRect.width = 0;
- collapsedRect.top = clientRect.top;
- collapsedRect.bottom = clientRect.bottom;
- collapsedRect.height = clientRect.height;
- collapsedRect.left = collapsedRect.right = useRightEdge ? clientRect.right : clientRect.left;
- return collapsedRect
- }
- function repositionOverlays(selectedRange) {
- var extremes = getExtremeRanges(selectedRange), firstRange, lastRange, fillerRange, firstRect, fillerRect, lastRect;
- if(selectedRange.collapsed || !extremes) {
- showOverlays(false)
- }else {
- showOverlays(true);
- firstRange = extremes.firstRange;
- lastRange = extremes.lastRange;
- fillerRange = extremes.fillerRange;
- firstRect = translateRect(getCollapsedRectOfTextRange(firstRange, false));
- lastRect = translateRect(getCollapsedRectOfTextRange(lastRange, true));
- fillerRect = getFillerRect(fillerRange);
- if(!fillerRect) {
- fillerRect = getBoundingRect(firstRect, lastRect)
- }else {
- fillerRect = translateRect(fillerRect)
++ function forwardUndoStackChange(e) {
++ odtDocument.emit(ops.OdtDocument.signalUndoStackChanged, e)
++ }
++ function undo() {
++ if(undoManager) {
++ undoManager.moveBackward(1);
++ redrawRegionSelectionTask.trigger();
++ return true
+ }
- setRect(overlayTop, {left:firstRect.left, top:firstRect.top, width:Math.max(0, fillerRect.width - (firstRect.left - fillerRect.left)), height:firstRect.height});
- if(lastRect.top === firstRect.top || lastRect.bottom === firstRect.bottom) {
- overlayMiddle.style.display = overlayBottom.style.display = "none"
- }else {
- setRect(overlayBottom, {left:fillerRect.left, top:lastRect.top, width:Math.max(0, lastRect.right - fillerRect.left), height:lastRect.height});
- setRect(overlayMiddle, {left:fillerRect.left, top:firstRect.top + firstRect.height, width:Math.max(0, parseFloat(overlayTop.style.left) + parseFloat(overlayTop.style.width) - parseFloat(overlayBottom.style.left)), height:Math.max(0, lastRect.top - firstRect.bottom)})
++ return false
++ }
++ function redo() {
++ if(undoManager) {
++ undoManager.moveForward(1);
++ redrawRegionSelectionTask.trigger();
++ return true
+ }
- firstRange.detach();
- lastRange.detach();
- fillerRange.detach()
++ return false
+ }
- }
- function rerender() {
- addOverlays();
- if(cursor.getSelectionType() === ops.OdtCursor.RangeSelection) {
- showOverlays(true);
- repositionOverlays(cursor.getSelectedRange())
- }else {
- showOverlays(false)
++ function updateShadowCursor() {
++ var selection = window.getSelection(), selectionRange = selection.rangeCount > 0 && selectionToRange(selection);
++ if(clickStartedWithinContainer && selectionRange) {
++ isMouseMoved = true;
++ imageSelector.clearSelection();
++ shadowCursorIterator.setUnfilteredPosition((selection.focusNode), selection.focusOffset);
++ if(mouseDownRootFilter.acceptPosition(shadowCursorIterator) === FILTER_ACCEPT) {
++ if(clickCount === 2) {
++ expandToWordBoundaries(selectionRange.range)
++ }else {
++ if(clickCount >= 3) {
++ expandToParagraphBoundaries(selectionRange.range)
++ }
++ }
++ shadowCursor.setSelectedRange(selectionRange.range, selectionRange.hasForwardSelection);
++ odtDocument.emit(ops.OdtDocument.signalCursorMoved, shadowCursor)
++ }
++ }
+ }
- }
- this.rerender = rerender;
- this.show = rerender;
- this.hide = function() {
- showOverlays(false)
- };
- this.visible = function() {
- return isVisible
- };
- function handleCursorMove(movedCursor) {
- if(movedCursor === cursor) {
- rerender()
++ function handleMouseDown(e) {
++ var target = getTarget(e), cursor = odtDocument.getCursor(inputMemberId);
++ clickStartedWithinContainer = target && domUtils.containsNode(odtDocument.getOdfCanvas().getElement(), target);
++ if(clickStartedWithinContainer) {
++ isMouseMoved = false;
++ mouseDownRootFilter = odtDocument.createRootFilter(target);
++ clickCount = e.detail;
++ if(cursor && e.shiftKey) {
++ window.getSelection().collapse(cursor.getAnchorNode(), 0)
++ }
++ if(clickCount > 1) {
++ updateShadowCursor()
++ }
++ }
+ }
- }
- this.destroy = function(callback) {
- root.removeChild(overlayTop);
- root.removeChild(overlayMiddle);
- root.removeChild(overlayBottom);
- cursor.getOdtDocument().unsubscribe(ops.OdtDocument.signalCursorMoved, handleCursorMove);
- callback()
- };
- function init() {
- var editinfons = "urn:webodf:names:editinfo", memberid = cursor.getMemberId();
- addOverlays();
- overlayTop.setAttributeNS(editinfons, "editinfo:memberid", memberid);
- overlayMiddle.setAttributeNS(editinfons, "editinfo:memberid", memberid);
- overlayBottom.setAttributeNS(editinfons, "editinfo:memberid", memberid);
- overlayTop.className = overlayMiddle.className = overlayBottom.className = "selectionOverlay";
- cursor.getOdtDocument().subscribe(ops.OdtDocument.signalCursorMoved, handleCursorMove)
- }
- init()
- };
- /*
-
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- runtime.loadClass("gui.SelectionView");
- gui.SelectionViewManager = function SelectionViewManager() {
- var selectionViews = {};
- function getSelectionView(memberId) {
- return selectionViews.hasOwnProperty(memberId) ? selectionViews[memberId] : null
- }
- this.getSelectionView = getSelectionView;
- function getSelectionViews() {
- return Object.keys(selectionViews).map(function(memberid) {
- return selectionViews[memberid]
- })
- }
- this.getSelectionViews = getSelectionViews;
- function removeSelectionView(memberId) {
- if(selectionViews.hasOwnProperty(memberId)) {
- selectionViews[memberId].destroy(function() {
- });
- delete selectionViews[memberId]
++ function mutableSelection(selection) {
++ if(selection) {
++ return{anchorNode:selection.anchorNode, anchorOffset:selection.anchorOffset, focusNode:selection.focusNode, focusOffset:selection.focusOffset}
++ }
++ return null
+ }
- }
- this.removeSelectionView = removeSelectionView;
- function hideSelectionView(memberId) {
- if(selectionViews.hasOwnProperty(memberId)) {
- selectionViews[memberId].hide()
++ function handleMouseClickEvent(event) {
++ var target = getTarget(event), eventDetails = {detail:event.detail, clientX:event.clientX, clientY:event.clientY, target:target};
++ drawShadowCursorTask.processRequests();
++ if(odfUtils.isImage(target) && odfUtils.isCharacterFrame(target.parentNode)) {
++ selectImage(target.parentNode)
++ }else {
++ if(clickStartedWithinContainer && !imageSelector.isSelectorElement(target)) {
++ if(isMouseMoved) {
++ selectRange(shadowCursor.getSelectedRange(), shadowCursor.hasForwardSelection(), event.detail)
++ }else {
++ runtime.setTimeout(function() {
++ var selection = mutableSelection(window.getSelection()), selectionRange, caretPos;
++ if(!selection.anchorNode && !selection.focusNode) {
++ caretPos = caretPositionFromPoint(eventDetails.clientX, eventDetails.clientY);
++ if(!caretPos) {
++ return
++ }
++ selection.anchorNode = (caretPos.container);
++ selection.anchorOffset = caretPos.offset;
++ selection.focusNode = selection.anchorNode;
++ selection.focusOffset = selection.anchorOffset
++ }
++ selectionRange = selectionToRange(selection);
++ selectRange(selectionRange.range, selectionRange.hasForwardSelection, eventDetails.detail)
++ }, 0)
++ }
++ }
++ }
++ clickCount = 0;
++ clickStartedWithinContainer = false;
++ isMouseMoved = false
+ }
- }
- this.hideSelectionView = hideSelectionView;
- function showSelectionView(memberId) {
- if(selectionViews.hasOwnProperty(memberId)) {
- selectionViews[memberId].show()
++ function handleContextMenu(e) {
++ handleMouseClickEvent(e)
+ }
- }
- this.showSelectionView = showSelectionView;
- this.rerenderSelectionViews = function() {
- Object.keys(selectionViews).forEach(function(memberId) {
- if(selectionViews[memberId].visible()) {
- selectionViews[memberId].rerender()
++ function handleMouseUp(event) {
++ var target = getTarget(event), annotationNode = null;
++ if(target.className === "annotationRemoveButton") {
++ annotationNode = domUtils.getElementsByTagNameNS(target.parentNode, odf.Namespaces.officens, "annotation")[0];
++ annotationController.removeAnnotation(annotationNode)
++ }else {
++ handleMouseClickEvent(event)
++ }
++ }
++ this.startEditing = function() {
++ var op;
++ odtDocument.getOdfCanvas().getElement().classList.add("virtualSelections");
++ eventManager.subscribe("keydown", keyDownHandler.handleEvent);
++ eventManager.subscribe("keypress", keyPressHandler.handleEvent);
++ eventManager.subscribe("keyup", dummyHandler);
++ eventManager.subscribe("beforecut", handleBeforeCut);
++ eventManager.subscribe("cut", handleCut);
++ eventManager.subscribe("copy", handleCopy);
++ eventManager.subscribe("beforepaste", handleBeforePaste);
++ eventManager.subscribe("paste", handlePaste);
++ eventManager.subscribe("mousedown", handleMouseDown);
++ eventManager.subscribe("mousemove", drawShadowCursorTask.trigger);
++ eventManager.subscribe("mouseup", handleMouseUp);
++ eventManager.subscribe("contextmenu", handleContextMenu);
++ eventManager.subscribe("focus", delayedMaintainCursor);
++ odtDocument.subscribe(ops.OdtDocument.signalOperationExecuted, redrawRegionSelectionTask.trigger);
++ odtDocument.subscribe(ops.OdtDocument.signalOperationExecuted, updateUndoStack);
++ op = new ops.OpAddCursor;
++ op.init({memberid:inputMemberId});
++ session.enqueue([op]);
++ if(undoManager) {
++ undoManager.saveInitialState()
++ }
++ };
++ this.endEditing = function() {
++ var op;
++ op = new ops.OpRemoveCursor;
++ op.init({memberid:inputMemberId});
++ session.enqueue([op]);
++ if(undoManager) {
++ undoManager.resetInitialState()
++ }
++ odtDocument.unsubscribe(ops.OdtDocument.signalOperationExecuted, updateUndoStack);
++ odtDocument.unsubscribe(ops.OdtDocument.signalOperationExecuted, redrawRegionSelectionTask.trigger);
++ eventManager.unsubscribe("keydown", keyDownHandler.handleEvent);
++ eventManager.unsubscribe("keypress", keyPressHandler.handleEvent);
++ eventManager.unsubscribe("keyup", dummyHandler);
++ eventManager.unsubscribe("cut", handleCut);
++ eventManager.unsubscribe("beforecut", handleBeforeCut);
++ eventManager.unsubscribe("copy", handleCopy);
++ eventManager.unsubscribe("paste", handlePaste);
++ eventManager.unsubscribe("beforepaste", handleBeforePaste);
++ eventManager.unsubscribe("mousemove", drawShadowCursorTask.trigger);
++ eventManager.unsubscribe("mousedown", handleMouseDown);
++ eventManager.unsubscribe("mouseup", handleMouseUp);
++ eventManager.unsubscribe("contextmenu", handleContextMenu);
++ eventManager.unsubscribe("focus", delayedMaintainCursor);
++ odtDocument.getOdfCanvas().getElement().classList.remove("virtualSelections")
++ };
++ this.getInputMemberId = function() {
++ return inputMemberId
++ };
++ this.getSession = function() {
++ return session
++ };
++ this.setUndoManager = function(manager) {
++ if(undoManager) {
++ undoManager.unsubscribe(gui.UndoManager.signalUndoStackChanged, forwardUndoStackChange)
++ }
++ undoManager = manager;
++ if(undoManager) {
++ undoManager.setOdtDocument(odtDocument);
++ undoManager.setPlaybackFunction(function(op) {
++ op.execute(odtDocument)
++ });
++ undoManager.subscribe(gui.UndoManager.signalUndoStackChanged, forwardUndoStackChange)
++ }
++ };
++ this.getUndoManager = function() {
++ return undoManager
++ };
++ this.getAnnotationController = function() {
++ return annotationController
++ };
++ this.getDirectTextStyler = function() {
++ return directTextStyler
++ };
++ this.getDirectParagraphStyler = function() {
++ return directParagraphStyler
++ };
++ this.getImageManager = function() {
++ return imageManager
++ };
++ this.getTextManipulator = function() {
++ return textManipulator
++ };
++ this.getEventManager = function() {
++ return eventManager
++ };
++ this.getKeyboardHandlers = function() {
++ return{keydown:keyDownHandler, keypress:keyPressHandler}
++ };
++ this.destroy = function(callback) {
++ var destroyCallbacks = [drawShadowCursorTask.destroy, directTextStyler.destroy];
++ if(directParagraphStyler) {
++ destroyCallbacks.push(directParagraphStyler.destroy)
++ }
++ async.destroyAll(destroyCallbacks, callback)
++ };
++ function returnTrue(fn) {
++ return function() {
++ fn();
++ return true
++ }
++ }
++ function rangeSelectionOnly(fn) {
++ return function(e) {
++ var selectionType = odtDocument.getCursor(inputMemberId).getSelectionType();
++ if(selectionType === ops.OdtCursor.RangeSelection) {
++ return fn(e)
++ }
++ return true
+ }
- })
- };
- this.registerCursor = function(cursor, virtualSelectionsInitiallyVisible) {
- var memberId = cursor.getMemberId(), selectionView = new gui.SelectionView(cursor);
- if(virtualSelectionsInitiallyVisible) {
- selectionView.show()
- }else {
- selectionView.hide()
+ }
- selectionViews[memberId] = selectionView;
- return selectionView
- };
- this.destroy = function(callback) {
- var selectionViewArray = getSelectionViews();
- (function destroySelectionView(i, err) {
- if(err) {
- callback(err)
++ function init() {
++ var isMacOS = window.navigator.appVersion.toLowerCase().indexOf("mac") !== -1, modifier = gui.KeyboardHandler.Modifier, keyCode = gui.KeyboardHandler.KeyCode;
++ drawShadowCursorTask = new core.ScheduledTask(updateShadowCursor, 0);
++ redrawRegionSelectionTask = new core.ScheduledTask(maintainCursorSelection, 0);
++ keyDownHandler.bind(keyCode.Tab, modifier.None, rangeSelectionOnly(function() {
++ textManipulator.insertText("\t");
++ return true
++ }));
++ keyDownHandler.bind(keyCode.Left, modifier.None, rangeSelectionOnly(moveCursorToLeft));
++ keyDownHandler.bind(keyCode.Right, modifier.None, rangeSelectionOnly(moveCursorToRight));
++ keyDownHandler.bind(keyCode.Up, modifier.None, rangeSelectionOnly(moveCursorUp));
++ keyDownHandler.bind(keyCode.Down, modifier.None, rangeSelectionOnly(moveCursorDown));
++ keyDownHandler.bind(keyCode.Backspace, modifier.None, returnTrue(textManipulator.removeTextByBackspaceKey));
++ keyDownHandler.bind(keyCode.Delete, modifier.None, textManipulator.removeTextByDeleteKey);
++ keyDownHandler.bind(keyCode.Left, modifier.Shift, rangeSelectionOnly(extendSelectionToLeft));
++ keyDownHandler.bind(keyCode.Right, modifier.Shift, rangeSelectionOnly(extendSelectionToRight));
++ keyDownHandler.bind(keyCode.Up, modifier.Shift, rangeSelectionOnly(extendSelectionUp));
++ keyDownHandler.bind(keyCode.Down, modifier.Shift, rangeSelectionOnly(extendSelectionDown));
++ keyDownHandler.bind(keyCode.Home, modifier.None, rangeSelectionOnly(moveCursorToLineStart));
++ keyDownHandler.bind(keyCode.End, modifier.None, rangeSelectionOnly(moveCursorToLineEnd));
++ keyDownHandler.bind(keyCode.Home, modifier.Ctrl, rangeSelectionOnly(moveCursorToDocumentStart));
++ keyDownHandler.bind(keyCode.End, modifier.Ctrl, rangeSelectionOnly(moveCursorToDocumentEnd));
++ keyDownHandler.bind(keyCode.Home, modifier.Shift, rangeSelectionOnly(extendSelectionToLineStart));
++ keyDownHandler.bind(keyCode.End, modifier.Shift, rangeSelectionOnly(extendSelectionToLineEnd));
++ keyDownHandler.bind(keyCode.Up, modifier.CtrlShift, rangeSelectionOnly(extendSelectionToParagraphStart));
++ keyDownHandler.bind(keyCode.Down, modifier.CtrlShift, rangeSelectionOnly(extendSelectionToParagraphEnd));
++ keyDownHandler.bind(keyCode.Home, modifier.CtrlShift, rangeSelectionOnly(extendSelectionToDocumentStart));
++ keyDownHandler.bind(keyCode.End, modifier.CtrlShift, rangeSelectionOnly(extendSelectionToDocumentEnd));
++ if(isMacOS) {
++ keyDownHandler.bind(keyCode.Clear, modifier.None, textManipulator.removeCurrentSelection);
++ keyDownHandler.bind(keyCode.Left, modifier.Meta, rangeSelectionOnly(moveCursorToLineStart));
++ keyDownHandler.bind(keyCode.Right, modifier.Meta, rangeSelectionOnly(moveCursorToLineEnd));
++ keyDownHandler.bind(keyCode.Home, modifier.Meta, rangeSelectionOnly(moveCursorToDocumentStart));
++ keyDownHandler.bind(keyCode.End, modifier.Meta, rangeSelectionOnly(moveCursorToDocumentEnd));
++ keyDownHandler.bind(keyCode.Left, modifier.MetaShift, rangeSelectionOnly(extendSelectionToLineStart));
++ keyDownHandler.bind(keyCode.Right, modifier.MetaShift, rangeSelectionOnly(extendSelectionToLineEnd));
++ keyDownHandler.bind(keyCode.Up, modifier.AltShift, rangeSelectionOnly(extendSelectionToParagraphStart));
++ keyDownHandler.bind(keyCode.Down, modifier.AltShift, rangeSelectionOnly(extendSelectionToParagraphEnd));
++ keyDownHandler.bind(keyCode.Up, modifier.MetaShift, rangeSelectionOnly(extendSelectionToDocumentStart));
++ keyDownHandler.bind(keyCode.Down, modifier.MetaShift, rangeSelectionOnly(extendSelectionToDocumentEnd));
++ keyDownHandler.bind(keyCode.A, modifier.Meta, rangeSelectionOnly(extendSelectionToEntireDocument));
++ keyDownHandler.bind(keyCode.B, modifier.Meta, rangeSelectionOnly(directTextStyler.toggleBold));
++ keyDownHandler.bind(keyCode.I, modifier.Meta, rangeSelectionOnly(directTextStyler.toggleItalic));
++ keyDownHandler.bind(keyCode.U, modifier.Meta, rangeSelectionOnly(directTextStyler.toggleUnderline));
++ if(directParagraphStyler) {
++ keyDownHandler.bind(keyCode.L, modifier.MetaShift, rangeSelectionOnly(directParagraphStyler.alignParagraphLeft));
++ keyDownHandler.bind(keyCode.E, modifier.MetaShift, rangeSelectionOnly(directParagraphStyler.alignParagraphCenter));
++ keyDownHandler.bind(keyCode.R, modifier.MetaShift, rangeSelectionOnly(directParagraphStyler.alignParagraphRight));
++ keyDownHandler.bind(keyCode.J, modifier.MetaShift, rangeSelectionOnly(directParagraphStyler.alignParagraphJustified))
++ }
++ if(annotationController) {
++ keyDownHandler.bind(keyCode.C, modifier.MetaShift, annotationController.addAnnotation)
++ }
++ keyDownHandler.bind(keyCode.Z, modifier.Meta, undo);
++ keyDownHandler.bind(keyCode.Z, modifier.MetaShift, redo)
+ }else {
- if(i < selectionViewArray.length) {
- selectionViewArray[i].destroy(function(err) {
- destroySelectionView(i + 1, err)
- })
- }else {
- callback()
++ keyDownHandler.bind(keyCode.A, modifier.Ctrl, rangeSelectionOnly(extendSelectionToEntireDocument));
++ keyDownHandler.bind(keyCode.B, modifier.Ctrl, rangeSelectionOnly(directTextStyler.toggleBold));
++ keyDownHandler.bind(keyCode.I, modifier.Ctrl, rangeSelectionOnly(directTextStyler.toggleItalic));
++ keyDownHandler.bind(keyCode.U, modifier.Ctrl, rangeSelectionOnly(directTextStyler.toggleUnderline));
++ if(directParagraphStyler) {
++ keyDownHandler.bind(keyCode.L, modifier.CtrlShift, rangeSelectionOnly(directParagraphStyler.alignParagraphLeft));
++ keyDownHandler.bind(keyCode.E, modifier.CtrlShift, rangeSelectionOnly(directParagraphStyler.alignParagraphCenter));
++ keyDownHandler.bind(keyCode.R, modifier.CtrlShift, rangeSelectionOnly(directParagraphStyler.alignParagraphRight));
++ keyDownHandler.bind(keyCode.J, modifier.CtrlShift, rangeSelectionOnly(directParagraphStyler.alignParagraphJustified))
++ }
++ if(annotationController) {
++ keyDownHandler.bind(keyCode.C, modifier.CtrlAlt, annotationController.addAnnotation)
+ }
++ keyDownHandler.bind(keyCode.Z, modifier.Ctrl, undo);
++ keyDownHandler.bind(keyCode.Z, modifier.CtrlShift, redo)
+ }
- })(0, undefined)
- }
- };
++ keyPressHandler.setDefault(rangeSelectionOnly(function(e) {
++ var text = stringFromKeyPress(e);
++ if(text && !(e.altKey || (e.ctrlKey || e.metaKey))) {
++ textManipulator.insertText(text);
++ return true
++ }
++ return false
++ }));
++ keyPressHandler.bind(keyCode.Enter, modifier.None, rangeSelectionOnly(textManipulator.enqueueParagraphSplittingOps))
++ }
++ init()
++ };
++ return gui.SessionController
++}();
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.EventNotifier");
- runtime.loadClass("core.DomUtils");
- runtime.loadClass("odf.OdfUtils");
- runtime.loadClass("odf.Namespaces");
- runtime.loadClass("gui.SelectionMover");
- runtime.loadClass("core.PositionFilterChain");
- runtime.loadClass("ops.StepsTranslator");
- runtime.loadClass("ops.TextPositionFilter");
- runtime.loadClass("ops.Member");
- ops.OdtDocument = function OdtDocument(odfCanvas) {
- var self = this, odfUtils, domUtils, cursors = {}, members = {}, eventNotifier = new core.EventNotifier([ops.OdtDocument.signalMemberAdded, ops.OdtDocument.signalMemberUpdated, ops.OdtDocument.signalMemberRemoved, ops.OdtDocument.signalCursorAdded, ops.OdtDocument.signalCursorRemoved, ops.OdtDocument.signalCursorMoved, ops.OdtDocument.signalParagraphChanged, ops.OdtDocument.signalParagraphStyleModified, ops.OdtDocument.signalCommonStyleCreated, ops.OdtDocument.signalCommonStyleDeleted [...]
- ops.OdtDocument.signalOperationExecuted, ops.OdtDocument.signalUndoStackChanged, ops.OdtDocument.signalStepsInserted, ops.OdtDocument.signalStepsRemoved]), FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT, FILTER_REJECT = core.PositionFilter.FilterResult.FILTER_REJECT, filter, stepsTranslator, lastEditingOp, unsupportedMetadataRemoved = false;
- function getRootNode() {
- var element = odfCanvas.odfContainer().getContentElement(), localName = element && element.localName;
- runtime.assert(localName === "text", "Unsupported content element type '" + localName + "' for OdtDocument");
- return element
- }
- function getDOM() {
- return(getRootNode().ownerDocument)
++runtime.loadClass("gui.Caret");
++gui.CaretManager = function CaretManager(sessionController) {
++ var carets = {}, window = runtime.getWindow(), scrollIntoViewScheduled = false;
++ function getCaret(memberId) {
++ return carets.hasOwnProperty(memberId) ? carets[memberId] : null
+ }
- this.getDOM = getDOM;
- function isRoot(node) {
- if(node.namespaceURI === odf.Namespaces.officens && node.localName === "text" || node.namespaceURI === odf.Namespaces.officens && node.localName === "annotation") {
- return true
- }
- return false
++ function getCarets() {
++ return Object.keys(carets).map(function(memberid) {
++ return carets[memberid]
++ })
+ }
- function getRoot(node) {
- while(node && !isRoot(node)) {
- node = (node.parentNode)
- }
- return node
++ function getCanvasElement() {
++ return sessionController.getSession().getOdtDocument().getOdfCanvas().getElement()
+ }
- this.getRootElement = getRoot;
- function RootFilter(anchor) {
- this.acceptPosition = function(iterator) {
- var node = iterator.container(), anchorNode;
- if(typeof anchor === "string") {
- anchorNode = cursors[anchor].getNode()
- }else {
- anchorNode = anchor
- }
- if(getRoot(node) === getRoot(anchorNode)) {
- return FILTER_ACCEPT
- }
- return FILTER_REJECT
++ function removeCaret(memberId) {
++ if(memberId === sessionController.getInputMemberId()) {
++ getCanvasElement().removeAttribute("tabindex")
+ }
++ delete carets[memberId]
+ }
- function getIteratorAtPosition(position) {
- var iterator = gui.SelectionMover.createPositionIterator(getRootNode()), point = stepsTranslator.convertStepsToDomPoint(position);
- iterator.setUnfilteredPosition(point.node, point.offset);
- return iterator
- }
- this.getIteratorAtPosition = getIteratorAtPosition;
- this.convertDomPointToCursorStep = function(node, offset) {
- return stepsTranslator.convertDomPointToSteps(node, offset)
- };
- this.convertDomToCursorRange = function(anchorNode, anchorOffset, focusNode, focusOffset) {
- var point1, point2;
- point1 = stepsTranslator.convertDomPointToSteps(anchorNode, anchorOffset);
- if(anchorNode === focusNode && anchorOffset === focusOffset) {
- point2 = point1
- }else {
- point2 = stepsTranslator.convertDomPointToSteps(focusNode, focusOffset)
- }
- return{position:point1, length:point2 - point1}
- };
- this.convertCursorToDomRange = function(position, length) {
- var range = getDOM().createRange(), point1, point2;
- point1 = stepsTranslator.convertStepsToDomPoint(position);
- if(length) {
- point2 = stepsTranslator.convertStepsToDomPoint(position + length);
- if(length > 0) {
- range.setStart(point1.node, point1.offset);
- range.setEnd(point2.node, point2.offset)
- }else {
- range.setStart(point2.node, point2.offset);
- range.setEnd(point1.node, point1.offset)
- }
- }else {
- range.setStart(point1.node, point1.offset)
- }
- return range
- };
- function getTextNodeAtStep(steps, memberid) {
- var iterator = getIteratorAtPosition(steps), node = iterator.container(), lastTextNode, nodeOffset = 0, cursorNode = null;
- if(node.nodeType === Node.TEXT_NODE) {
- lastTextNode = (node);
- nodeOffset = iterator.unfilteredDomOffset()
- }else {
- lastTextNode = getDOM().createTextNode("");
- nodeOffset = 0;
- node.insertBefore(lastTextNode, iterator.rightNode())
- }
- if(memberid && (cursors[memberid] && self.getCursorPosition(memberid) === steps)) {
- cursorNode = cursors[memberid].getNode();
- while(cursorNode.nextSibling && cursorNode.nextSibling.localName === "cursor") {
- cursorNode.parentNode.insertBefore(cursorNode.nextSibling, cursorNode)
- }
- if(lastTextNode.length > 0 && lastTextNode.nextSibling !== cursorNode) {
- lastTextNode = getDOM().createTextNode("");
- nodeOffset = 0
++ function refreshLocalCaretBlinking(cursor) {
++ var caret, memberId = cursor.getMemberId();
++ if(memberId === sessionController.getInputMemberId()) {
++ caret = getCaret(memberId);
++ if(caret) {
++ caret.refreshCursorBlinking()
+ }
- cursorNode.parentNode.insertBefore(lastTextNode, cursorNode)
- }
- while(lastTextNode.previousSibling && lastTextNode.previousSibling.nodeType === Node.TEXT_NODE) {
- lastTextNode.previousSibling.appendData(lastTextNode.data);
- nodeOffset = lastTextNode.previousSibling.length;
- lastTextNode = (lastTextNode.previousSibling);
- lastTextNode.parentNode.removeChild(lastTextNode.nextSibling)
+ }
- return{textNode:lastTextNode, offset:nodeOffset}
- }
- function getParagraphElement(node) {
- return odfUtils.getParagraphElement(node)
- }
- function getStyleElement(styleName, styleFamily) {
- return odfCanvas.getFormatting().getStyleElement(styleName, styleFamily)
- }
- this.getStyleElement = getStyleElement;
- function getParagraphStyleElement(styleName) {
- return getStyleElement(styleName, "paragraph")
+ }
- function getParagraphStyleAttributes(styleName) {
- var node = getParagraphStyleElement(styleName);
- if(node) {
- return odfCanvas.getFormatting().getInheritedStyleAttributes(node)
++ function executeEnsureCaretVisible() {
++ var caret = getCaret(sessionController.getInputMemberId());
++ scrollIntoViewScheduled = false;
++ if(caret) {
++ caret.ensureVisible()
+ }
- return null
+ }
- function handleOperationExecuted(op) {
- var spec = op.spec(), memberId = spec.memberid, date = (new Date(spec.timestamp)).toISOString(), metadataManager = odfCanvas.odfContainer().getMetadataManager(), fullName;
- if(op.isEdit) {
- fullName = self.getMember(memberId).getProperties().fullName;
- metadataManager.setMetadata({"dc:creator":fullName, "dc:date":date}, null);
- if(!lastEditingOp) {
- metadataManager.incrementEditingCycles();
- if(!unsupportedMetadataRemoved) {
- metadataManager.setMetadata(null, ["meta:editing-duration", "meta:document-statistic"])
- }
++ function scheduleCaretVisibilityCheck() {
++ var caret = getCaret(sessionController.getInputMemberId());
++ if(caret) {
++ caret.handleUpdate();
++ if(!scrollIntoViewScheduled) {
++ scrollIntoViewScheduled = true;
++ runtime.setTimeout(executeEnsureCaretVisible, 50)
+ }
- lastEditingOp = op
+ }
+ }
- function upgradeWhitespaceToElement(textNode, offset) {
- runtime.assert(textNode.data[offset] === " ", "upgradeWhitespaceToElement: textNode.data[offset] should be a literal space");
- var space = textNode.ownerDocument.createElementNS(odf.Namespaces.textns, "text:s");
- space.appendChild(textNode.ownerDocument.createTextNode(" "));
- textNode.deleteData(offset, 1);
- if(offset > 0) {
- textNode = (textNode.splitText(offset))
++ function ensureLocalCaretVisible(info) {
++ if(info.memberId === sessionController.getInputMemberId()) {
++ scheduleCaretVisibilityCheck()
+ }
- textNode.parentNode.insertBefore(space, textNode);
- return space
+ }
- function upgradeWhitespacesAtPosition(position) {
- var iterator = getIteratorAtPosition(position), container, offset, i;
- iterator.previousPosition();
- iterator.previousPosition();
- for(i = -1;i <= 1;i += 1) {
- container = iterator.container();
- offset = iterator.unfilteredDomOffset();
- if(container.nodeType === Node.TEXT_NODE && (container.data[offset] === " " && odfUtils.isSignificantWhitespace(container, offset))) {
- container = upgradeWhitespaceToElement((container), offset);
- iterator.moveToEndOfNode(container)
- }
- iterator.nextPosition()
++ function focusLocalCaret() {
++ var caret = getCaret(sessionController.getInputMemberId());
++ if(caret) {
++ caret.setFocus()
+ }
+ }
- this.upgradeWhitespacesAtPosition = upgradeWhitespacesAtPosition;
- this.downgradeWhitespacesAtPosition = function(position) {
- var iterator = getIteratorAtPosition(position), container, offset, firstSpaceElementChild, lastSpaceElementChild;
- container = iterator.container();
- offset = iterator.unfilteredDomOffset();
- while(!odfUtils.isCharacterElement(container) && container.childNodes[offset]) {
- container = container.childNodes[offset];
- offset = 0
++ function blurLocalCaret() {
++ var caret = getCaret(sessionController.getInputMemberId());
++ if(caret) {
++ caret.removeFocus()
+ }
- if(container.nodeType === Node.TEXT_NODE) {
- container = container.parentNode
++ }
++ function showLocalCaret() {
++ var caret = getCaret(sessionController.getInputMemberId());
++ if(caret) {
++ caret.show()
+ }
- if(odfUtils.isDowngradableSpaceElement(container)) {
- firstSpaceElementChild = container.firstChild;
- lastSpaceElementChild = container.lastChild;
- domUtils.mergeIntoParent(container);
- if(lastSpaceElementChild !== firstSpaceElementChild) {
- domUtils.normalizeTextNodes(lastSpaceElementChild)
- }
- domUtils.normalizeTextNodes(firstSpaceElementChild)
++ }
++ function hideLocalCaret() {
++ var caret = getCaret(sessionController.getInputMemberId());
++ if(caret) {
++ caret.hide()
+ }
++ }
++ this.registerCursor = function(cursor, caretAvatarInitiallyVisible, blinkOnRangeSelect) {
++ var memberid = cursor.getMemberId(), caret = new gui.Caret(cursor, caretAvatarInitiallyVisible, blinkOnRangeSelect);
++ carets[memberid] = caret;
++ if(memberid === sessionController.getInputMemberId()) {
++ runtime.log("Starting to track input on new cursor of " + memberid);
++ cursor.handleUpdate = scheduleCaretVisibilityCheck;
++ getCanvasElement().setAttribute("tabindex", -1);
++ sessionController.getEventManager().focus()
++ }else {
++ cursor.handleUpdate = caret.handleUpdate
++ }
++ return caret
+ };
- this.getParagraphStyleElement = getParagraphStyleElement;
- this.getParagraphElement = getParagraphElement;
- this.getParagraphStyleAttributes = getParagraphStyleAttributes;
- this.getTextNodeAtStep = getTextNodeAtStep;
- this.fixCursorPositions = function() {
- var rootConstrainedFilter = new core.PositionFilterChain;
- rootConstrainedFilter.addFilter("BaseFilter", filter);
- Object.keys(cursors).forEach(function(memberId) {
- var cursor = cursors[memberId], stepCounter = cursor.getStepCounter(), stepsSelectionLength, positionsToAdjustFocus, positionsToAdjustAnchor, positionsToAnchor, cursorMoved = false;
- rootConstrainedFilter.addFilter("RootFilter", self.createRootFilter(memberId));
- stepsSelectionLength = stepCounter.countStepsToPosition(cursor.getAnchorNode(), 0, rootConstrainedFilter);
- if(!stepCounter.isPositionWalkable(rootConstrainedFilter)) {
- cursorMoved = true;
- positionsToAdjustFocus = stepCounter.countPositionsToNearestStep(cursor.getNode(), 0, rootConstrainedFilter);
- positionsToAdjustAnchor = stepCounter.countPositionsToNearestStep(cursor.getAnchorNode(), 0, rootConstrainedFilter);
- cursor.move(positionsToAdjustFocus);
- if(stepsSelectionLength !== 0) {
- if(positionsToAdjustAnchor > 0) {
- stepsSelectionLength += 1
- }
- if(positionsToAdjustFocus > 0) {
- stepsSelectionLength -= 1
- }
- positionsToAnchor = stepCounter.countSteps(stepsSelectionLength, rootConstrainedFilter);
- cursor.move(positionsToAnchor);
- cursor.move(-positionsToAnchor, true)
- }
++ this.getCaret = getCaret;
++ this.getCarets = getCarets;
++ this.destroy = function(callback) {
++ var odtDocument = sessionController.getSession().getOdtDocument(), eventManager = sessionController.getEventManager(), caretArray = getCarets();
++ odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, ensureLocalCaretVisible);
++ odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, refreshLocalCaretBlinking);
++ odtDocument.unsubscribe(ops.OdtDocument.signalCursorRemoved, removeCaret);
++ eventManager.unsubscribe("focus", focusLocalCaret);
++ eventManager.unsubscribe("blur", blurLocalCaret);
++ window.removeEventListener("focus", showLocalCaret, false);
++ window.removeEventListener("blur", hideLocalCaret, false);
++ (function destroyCaret(i, err) {
++ if(err) {
++ callback(err)
+ }else {
- if(stepsSelectionLength === 0) {
- cursorMoved = true;
- cursor.move(0)
++ if(i < caretArray.length) {
++ caretArray[i].destroy(function(err) {
++ destroyCaret(i + 1, err)
++ })
++ }else {
++ callback()
+ }
+ }
- if(cursorMoved) {
- self.emit(ops.OdtDocument.signalCursorMoved, cursor)
- }
- rootConstrainedFilter.removeFilter("RootFilter")
- })
- };
- this.getDistanceFromCursor = function(memberid, node, offset) {
- var cursor = cursors[memberid], focusPosition, targetPosition;
- runtime.assert(node !== null && node !== undefined, "OdtDocument.getDistanceFromCursor called without node");
- if(cursor) {
- focusPosition = stepsTranslator.convertDomPointToSteps(cursor.getNode(), 0);
- targetPosition = stepsTranslator.convertDomPointToSteps(node, offset)
- }
- return targetPosition - focusPosition
- };
- this.getCursorPosition = function(memberid) {
- var cursor = cursors[memberid];
- return cursor ? stepsTranslator.convertDomPointToSteps(cursor.getNode(), 0) : 0
- };
- this.getCursorSelection = function(memberid) {
- var cursor = cursors[memberid], focusPosition = 0, anchorPosition = 0;
- if(cursor) {
- focusPosition = stepsTranslator.convertDomPointToSteps(cursor.getNode(), 0);
- anchorPosition = stepsTranslator.convertDomPointToSteps(cursor.getAnchorNode(), 0)
- }
- return{position:anchorPosition, length:focusPosition - anchorPosition}
- };
- this.getPositionFilter = function() {
- return filter
- };
- this.getOdfCanvas = function() {
- return odfCanvas
- };
- this.getRootNode = getRootNode;
- this.addMember = function(member) {
- runtime.assert(members[member.getMemberId()] === undefined, "This member already exists");
- members[member.getMemberId()] = member
- };
- this.getMember = function(memberId) {
- return members.hasOwnProperty(memberId) ? members[memberId] : null
- };
- this.removeMember = function(memberId) {
- delete members[memberId]
- };
- this.getCursor = function(memberid) {
- return cursors[memberid]
- };
- this.getCursors = function() {
- var list = [], i;
- for(i in cursors) {
- if(cursors.hasOwnProperty(i)) {
- list.push(cursors[i])
- }
- }
- return list
- };
- this.addCursor = function(cursor) {
- runtime.assert(Boolean(cursor), "OdtDocument::addCursor without cursor");
- var distanceToFirstTextNode = cursor.getStepCounter().countSteps(1, filter), memberid = cursor.getMemberId();
- runtime.assert(typeof memberid === "string", "OdtDocument::addCursor has cursor without memberid");
- runtime.assert(!cursors[memberid], "OdtDocument::addCursor is adding a duplicate cursor with memberid " + memberid);
- cursor.move(distanceToFirstTextNode);
- cursors[memberid] = cursor
- };
- this.removeCursor = function(memberid) {
- var cursor = cursors[memberid];
- if(cursor) {
- cursor.removeFromOdtDocument();
- delete cursors[memberid];
- self.emit(ops.OdtDocument.signalCursorRemoved, memberid);
- return true
- }
- return false
- };
- this.getFormatting = function() {
- return odfCanvas.getFormatting()
- };
- this.emit = function(eventid, args) {
- eventNotifier.emit(eventid, args)
- };
- this.subscribe = function(eventid, cb) {
- eventNotifier.subscribe(eventid, cb)
- };
- this.unsubscribe = function(eventid, cb) {
- eventNotifier.unsubscribe(eventid, cb)
- };
- this.createRootFilter = function(inputMemberId) {
- return new RootFilter(inputMemberId)
- };
- this.close = function(callback) {
- callback()
- };
- this.destroy = function(callback) {
- callback()
++ })(0, undefined);
++ carets = {}
+ };
+ function init() {
- filter = new ops.TextPositionFilter(getRootNode);
- odfUtils = new odf.OdfUtils;
- domUtils = new core.DomUtils;
- stepsTranslator = new ops.StepsTranslator(getRootNode, gui.SelectionMover.createPositionIterator, filter, 500);
- eventNotifier.subscribe(ops.OdtDocument.signalStepsInserted, stepsTranslator.handleStepsInserted);
- eventNotifier.subscribe(ops.OdtDocument.signalStepsRemoved, stepsTranslator.handleStepsRemoved);
- eventNotifier.subscribe(ops.OdtDocument.signalOperationExecuted, handleOperationExecuted)
++ var odtDocument = sessionController.getSession().getOdtDocument(), eventManager = sessionController.getEventManager();
++ odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, ensureLocalCaretVisible);
++ odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, refreshLocalCaretBlinking);
++ odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, removeCaret);
++ eventManager.subscribe("focus", focusLocalCaret);
++ eventManager.subscribe("blur", blurLocalCaret);
++ window.addEventListener("focus", showLocalCaret, false);
++ window.addEventListener("blur", hideLocalCaret, false)
+ }
+ init()
+};
- ops.OdtDocument.signalMemberAdded = "member/added";
- ops.OdtDocument.signalMemberUpdated = "member/updated";
- ops.OdtDocument.signalMemberRemoved = "member/removed";
- ops.OdtDocument.signalCursorAdded = "cursor/added";
- ops.OdtDocument.signalCursorRemoved = "cursor/removed";
- ops.OdtDocument.signalCursorMoved = "cursor/moved";
- ops.OdtDocument.signalParagraphChanged = "paragraph/changed";
- ops.OdtDocument.signalTableAdded = "table/added";
- ops.OdtDocument.signalCommonStyleCreated = "style/created";
- ops.OdtDocument.signalCommonStyleDeleted = "style/deleted";
- ops.OdtDocument.signalParagraphStyleModified = "paragraphstyle/modified";
- ops.OdtDocument.signalOperationExecuted = "operation/executed";
- ops.OdtDocument.signalUndoStackChanged = "undo/changed";
- ops.OdtDocument.signalStepsInserted = "steps/inserted";
- ops.OdtDocument.signalStepsRemoved = "steps/removed";
- (function() {
- return ops.OdtDocument
- })();
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("ops.TrivialOperationRouter");
- runtime.loadClass("ops.OperationFactory");
- runtime.loadClass("ops.OdtDocument");
- ops.Session = function Session(odfCanvas) {
- var self = this, operationFactory = new ops.OperationFactory, odtDocument = new ops.OdtDocument(odfCanvas), operationRouter = null;
- this.setOperationFactory = function(opFactory) {
- operationFactory = opFactory;
- if(operationRouter) {
- operationRouter.setOperationFactory(operationFactory)
++runtime.loadClass("gui.Caret");
++runtime.loadClass("ops.EditInfo");
++runtime.loadClass("gui.EditInfoMarker");
++gui.SessionViewOptions = function() {
++ this.editInfoMarkersInitiallyVisible = true;
++ this.caretAvatarsInitiallyVisible = true;
++ this.caretBlinksOnRangeSelect = true
++};
++gui.SessionView = function() {
++ function configOption(userValue, defaultValue) {
++ return userValue !== undefined ? Boolean(userValue) : defaultValue
++ }
++ function SessionView(viewOptions, localMemberId, session, caretManager, selectionViewManager) {
++ var avatarInfoStyles, editInfons = "urn:webodf:names:editinfo", editInfoMap = {}, showEditInfoMarkers = configOption(viewOptions.editInfoMarkersInitiallyVisible, true), showCaretAvatars = configOption(viewOptions.caretAvatarsInitiallyVisible, true), blinkOnRangeSelect = configOption(viewOptions.caretBlinksOnRangeSelect, true), rerenderIntervalId, rerenderSelectionViews = false, RERENDER_INTERVAL = 200;
++ function createAvatarInfoNodeMatch(nodeName, memberId, pseudoClass) {
++ return nodeName + '[editinfo|memberid="' + memberId + '"]' + pseudoClass
+ }
- };
- this.setOperationRouter = function(opRouter) {
- operationRouter = opRouter;
- opRouter.setPlaybackFunction(function(op) {
- op.execute(odtDocument);
- odtDocument.emit(ops.OdtDocument.signalOperationExecuted, op)
- });
- opRouter.setOperationFactory(operationFactory)
- };
- this.getOperationFactory = function() {
- return operationFactory
- };
- this.getOdtDocument = function() {
- return odtDocument
- };
- this.enqueue = function(ops) {
- operationRouter.push(ops)
- };
- this.close = function(callback) {
- operationRouter.close(function(err) {
- if(err) {
- callback(err)
++ function getAvatarInfoStyle(nodeName, memberId, pseudoClass) {
++ var node = avatarInfoStyles.firstChild, nodeMatch = createAvatarInfoNodeMatch(nodeName, memberId, pseudoClass) + "{";
++ while(node) {
++ if(node.nodeType === Node.TEXT_NODE && node.data.indexOf(nodeMatch) === 0) {
++ return node
++ }
++ node = node.nextSibling
++ }
++ return null
++ }
++ function setAvatarInfoStyle(memberId, name, color) {
++ function setStyle(nodeName, rule, pseudoClass) {
++ var styleRule = createAvatarInfoNodeMatch(nodeName, memberId, pseudoClass) + rule, styleNode = getAvatarInfoStyle(nodeName, memberId, pseudoClass);
++ if(styleNode) {
++ styleNode.data = styleRule
++ }else {
++ avatarInfoStyles.appendChild(document.createTextNode(styleRule))
++ }
++ }
++ setStyle("div.editInfoMarker", "{ background-color: " + color + "; }", "");
++ setStyle("span.editInfoColor", "{ background-color: " + color + "; }", "");
++ setStyle("span.editInfoAuthor", '{ content: "' + name + '"; }', ":before");
++ setStyle("dc|creator", "{ background-color: " + color + "; }", "");
++ setStyle("div.selectionOverlay", "{ background-color: " + color + ";}", "")
++ }
++ function highlightEdit(element, memberId, timestamp) {
++ var editInfo, editInfoMarker, id = "", editInfoNode = element.getElementsByTagNameNS(editInfons, "editinfo")[0];
++ if(editInfoNode) {
++ id = editInfoNode.getAttributeNS(editInfons, "id");
++ editInfoMarker = editInfoMap[id]
+ }else {
- odtDocument.close(callback)
++ id = Math.random().toString();
++ editInfo = new ops.EditInfo(element, session.getOdtDocument());
++ editInfoMarker = new gui.EditInfoMarker(editInfo, showEditInfoMarkers);
++ editInfoNode = element.getElementsByTagNameNS(editInfons, "editinfo")[0];
++ editInfoNode.setAttributeNS(editInfons, "id", id);
++ editInfoMap[id] = editInfoMarker
+ }
- })
- };
- this.destroy = function(callback) {
- odtDocument.destroy(callback)
- };
- function init() {
- self.setOperationRouter(new ops.TrivialOperationRouter)
++ editInfoMarker.addEdit(memberId, new Date(timestamp))
++ }
++ function setEditInfoMarkerVisibility(visible) {
++ var editInfoMarker, keyname;
++ for(keyname in editInfoMap) {
++ if(editInfoMap.hasOwnProperty(keyname)) {
++ editInfoMarker = editInfoMap[keyname];
++ if(visible) {
++ editInfoMarker.show()
++ }else {
++ editInfoMarker.hide()
++ }
++ }
++ }
++ }
++ function setCaretAvatarVisibility(visible) {
++ caretManager.getCarets().forEach(function(caret) {
++ if(visible) {
++ caret.showHandle()
++ }else {
++ caret.hideHandle()
++ }
++ })
++ }
++ this.showEditInfoMarkers = function() {
++ if(showEditInfoMarkers) {
++ return
++ }
++ showEditInfoMarkers = true;
++ setEditInfoMarkerVisibility(showEditInfoMarkers)
++ };
++ this.hideEditInfoMarkers = function() {
++ if(!showEditInfoMarkers) {
++ return
++ }
++ showEditInfoMarkers = false;
++ setEditInfoMarkerVisibility(showEditInfoMarkers)
++ };
++ this.showCaretAvatars = function() {
++ if(showCaretAvatars) {
++ return
++ }
++ showCaretAvatars = true;
++ setCaretAvatarVisibility(showCaretAvatars)
++ };
++ this.hideCaretAvatars = function() {
++ if(!showCaretAvatars) {
++ return
++ }
++ showCaretAvatars = false;
++ setCaretAvatarVisibility(showCaretAvatars)
++ };
++ this.getSession = function() {
++ return session
++ };
++ this.getCaret = function(memberid) {
++ return caretManager.getCaret(memberid)
++ };
++ function renderMemberData(member) {
++ var memberId = member.getMemberId(), properties = member.getProperties();
++ setAvatarInfoStyle(memberId, properties.fullName, properties.color);
++ if(localMemberId === memberId) {
++ setAvatarInfoStyle("", "", properties.color)
++ }
++ }
++ function onCursorAdded(cursor) {
++ var memberId = cursor.getMemberId(), properties = session.getOdtDocument().getMember(memberId).getProperties(), caret;
++ caretManager.registerCursor(cursor, showCaretAvatars, blinkOnRangeSelect);
++ selectionViewManager.registerCursor(cursor, true);
++ caret = caretManager.getCaret(memberId);
++ if(caret) {
++ caret.setAvatarImageUrl(properties.imageUrl);
++ caret.setColor(properties.color)
++ }
++ runtime.log("+++ View here +++ eagerly created an Caret for '" + memberId + "'! +++")
++ }
++ function onCursorMoved(cursor) {
++ var memberId = cursor.getMemberId(), localSelectionView = selectionViewManager.getSelectionView(localMemberId), shadowSelectionView = selectionViewManager.getSelectionView(gui.ShadowCursor.ShadowCursorMemberId), localCaret = caretManager.getCaret(localMemberId);
++ if(memberId === localMemberId) {
++ shadowSelectionView.hide();
++ if(localSelectionView) {
++ localSelectionView.show()
++ }
++ if(localCaret) {
++ localCaret.show()
++ }
++ }else {
++ if(memberId === gui.ShadowCursor.ShadowCursorMemberId) {
++ shadowSelectionView.show();
++ if(localSelectionView) {
++ localSelectionView.hide()
++ }
++ if(localCaret) {
++ localCaret.hide()
++ }
++ }
++ }
++ }
++ function onCursorRemoved(memberid) {
++ selectionViewManager.removeSelectionView(memberid)
++ }
++ function onParagraphChanged(info) {
++ highlightEdit(info.paragraphElement, info.memberId, info.timeStamp)
++ }
++ function requestRerenderOfSelectionViews() {
++ rerenderSelectionViews = true
++ }
++ function startRerenderLoop() {
++ rerenderIntervalId = runtime.getWindow().setInterval(function() {
++ if(rerenderSelectionViews) {
++ selectionViewManager.rerenderSelectionViews();
++ rerenderSelectionViews = false
++ }
++ }, RERENDER_INTERVAL)
++ }
++ function stopRerenderLoop() {
++ runtime.getWindow().clearInterval(rerenderIntervalId)
++ }
++ this.destroy = function(callback) {
++ var odtDocument = session.getOdtDocument(), editInfoArray = Object.keys(editInfoMap).map(function(keyname) {
++ return editInfoMap[keyname]
++ });
++ odtDocument.unsubscribe(ops.OdtDocument.signalMemberAdded, renderMemberData);
++ odtDocument.unsubscribe(ops.OdtDocument.signalMemberUpdated, renderMemberData);
++ odtDocument.unsubscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
++ odtDocument.unsubscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
++ odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged);
++ odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
++ odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, requestRerenderOfSelectionViews);
++ odtDocument.unsubscribe(ops.OdtDocument.signalTableAdded, requestRerenderOfSelectionViews);
++ odtDocument.unsubscribe(ops.OdtDocument.signalParagraphStyleModified, requestRerenderOfSelectionViews);
++ stopRerenderLoop();
++ avatarInfoStyles.parentNode.removeChild(avatarInfoStyles);
++ (function destroyEditInfo(i, err) {
++ if(err) {
++ callback(err)
++ }else {
++ if(i < editInfoArray.length) {
++ editInfoArray[i].destroy(function(err) {
++ destroyEditInfo(i + 1, err)
++ })
++ }else {
++ callback()
++ }
++ }
++ })(0, undefined)
++ };
++ function init() {
++ var odtDocument = session.getOdtDocument(), head = document.getElementsByTagName("head")[0];
++ odtDocument.subscribe(ops.OdtDocument.signalMemberAdded, renderMemberData);
++ odtDocument.subscribe(ops.OdtDocument.signalMemberUpdated, renderMemberData);
++ odtDocument.subscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
++ odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
++ odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged);
++ odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
++ startRerenderLoop();
++ odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, requestRerenderOfSelectionViews);
++ odtDocument.subscribe(ops.OdtDocument.signalTableAdded, requestRerenderOfSelectionViews);
++ odtDocument.subscribe(ops.OdtDocument.signalParagraphStyleModified, requestRerenderOfSelectionViews);
++ avatarInfoStyles = document.createElementNS(head.namespaceURI, "style");
++ avatarInfoStyles.type = "text/css";
++ avatarInfoStyles.media = "screen, print, handheld, projection";
++ avatarInfoStyles.appendChild(document.createTextNode("@namespace editinfo url(urn:webodf:names:editinfo);"));
++ avatarInfoStyles.appendChild(document.createTextNode("@namespace dc url(http://purl.org/dc/elements/1.1/);"));
++ head.appendChild(avatarInfoStyles)
++ }
++ init()
+ }
- init()
- };
++ return SessionView
++}();
+var webodf_css = "@namespace draw url(urn:oasis:names:tc:opendocument:xmlns:drawing:1.0);\n at namespace fo url(urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0);\n at namespace office url(urn:oasis:names:tc:opendocument:xmlns:office:1.0);\n at namespace presentation url(urn:oasis:names:tc:opendocument:xmlns:presentation:1.0);\n at namespace style url(urn:oasis:names:tc:opendocument:xmlns:style:1.0);\n at namespace svg url(urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0);\n at namespa [...]
- var webodf_version = "0.4.2-1451-gc9cf878";
+
diff --cc apps/documents/js/3rdparty/webodf/webodf.js
index 306f4d9,0000000..f483b7d
mode 100644,000000..100644
--- a/apps/documents/js/3rdparty/webodf/webodf.js
+++ b/apps/documents/js/3rdparty/webodf/webodf.js
@@@ -1,3131 -1,0 +1,3100 @@@
+// Input 0
- /*
-
-
- Copyright (C) 2012 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- var core={},gui={},xmldom={},odf={},ops={};
++var webodf_version="0.4.2-1556-gf8a94ee";
+// Input 1
- function Runtime(){}Runtime.prototype.getVariable=function(g){};Runtime.prototype.toJson=function(g){};Runtime.prototype.fromJson=function(g){};Runtime.prototype.byteArrayFromString=function(g,l){};Runtime.prototype.byteArrayToString=function(g,l){};Runtime.prototype.read=function(g,l,c,m){};Runtime.prototype.readFile=function(g,l,c){};Runtime.prototype.readFileSync=function(g,l){};Runtime.prototype.loadXML=function(g,l){};Runtime.prototype.writeFile=function(g,l,c){};
- Runtime.prototype.isFile=function(g,l){};Runtime.prototype.getFileSize=function(g,l){};Runtime.prototype.deleteFile=function(g,l){};Runtime.prototype.log=function(g,l){};Runtime.prototype.setTimeout=function(g,l){};Runtime.prototype.clearTimeout=function(g){};Runtime.prototype.libraryPaths=function(){};Runtime.prototype.type=function(){};Runtime.prototype.getDOMImplementation=function(){};Runtime.prototype.parseXML=function(g){};Runtime.prototype.getWindow=function(){};
- Runtime.prototype.assert=function(g,l,c){};var IS_COMPILED_CODE=!0;
- Runtime.byteArrayToString=function(g,l){function c(c){var b="",p,r=c.length;for(p=0;p<r;p+=1)b+=String.fromCharCode(c[p]&255);return b}function m(c){var b="",p,r=c.length,d=[],k,a,e,h;for(p=0;p<r;p+=1)k=c[p],128>k?d.push(k):(p+=1,a=c[p],194<=k&&224>k?d.push((k&31)<<6|a&63):(p+=1,e=c[p],224<=k&&240>k?d.push((k&15)<<12|(a&63)<<6|e&63):(p+=1,h=c[p],240<=k&&245>k&&(k=(k&7)<<18|(a&63)<<12|(e&63)<<6|h&63,k-=65536,d.push((k>>10)+55296,(k&1023)+56320))))),1E3===d.length&&(b+=String.fromCharCode [...]
- d),d.length=0);return b+String.fromCharCode.apply(null,d)}var f;"utf8"===l?f=m(g):("binary"!==l&&this.log("Unsupported encoding: "+l),f=c(g));return f};Runtime.getVariable=function(g){try{return eval(g)}catch(l){}};Runtime.toJson=function(g){return JSON.stringify(g)};Runtime.fromJson=function(g){return JSON.parse(g)};Runtime.getFunctionName=function(g){return void 0===g.name?(g=/function\s+(\w+)/.exec(g))&&g[1]:g.name};
- function BrowserRuntime(g){function l(b,r){var d,k,a;void 0!==r?a=b:r=b;g?(k=g.ownerDocument,a&&(d=k.createElement("span"),d.className=a,d.appendChild(k.createTextNode(a)),g.appendChild(d),g.appendChild(k.createTextNode(" "))),d=k.createElement("span"),0<r.length&&"<"===r[0]?d.innerHTML=r:d.appendChild(k.createTextNode(r)),g.appendChild(d),g.appendChild(k.createElement("br"))):console&&console.log(r);"alert"===a&&alert(r)}function c(c,r,d){if(0!==d.status||d.responseText)if(200===d.stat [...]
- "string"!==typeof d.response)"binary"===r?(r=d.response,r=new Uint8Array(r)):r=String(d.response);else if("binary"===r)if(null!==d.responseBody&&"undefined"!==String(typeof VBArray)){r=(new VBArray(d.responseBody)).toArray();d=r.length;var k,a=new Uint8Array(new ArrayBuffer(d));for(k=0;k<d;k+=1)a[k]=r[k];r=a}else r=n.byteArrayFromString(d.responseText,"binary");else r=d.responseText;b[c]=r;c={err:null,data:r}}else c={err:d.responseText||d.statusText,data:null};else c={err:"File "+c+" is [...]
- return c}function m(b,c,d){var k=new XMLHttpRequest;k.open("GET",b,d);k.overrideMimeType&&("binary"!==c?k.overrideMimeType("text/plain; charset="+c):k.overrideMimeType("text/plain; charset=x-user-defined"));return k}function f(p,r,d){function k(){var e;4===a.readyState&&(e=c(p,r,a),d(e.err,e.data))}if(b.hasOwnProperty(p))d(null,b[p]);else{var a=m(p,r,!0);a.onreadystatechange=k;try{a.send(null)}catch(e){d(e.message,null)}}}var n=this,b={};this.byteArrayFromString=function(b,c){var d;if(" [...]
- b.length;var k,a,e,h=0;for(a=0;a<d;a+=1)e=b.charCodeAt(a),h+=1+(128<e)+(2048<e);k=new Uint8Array(new ArrayBuffer(h));for(a=h=0;a<d;a+=1)e=b.charCodeAt(a),128>e?(k[h]=e,h+=1):2048>e?(k[h]=192|e>>>6,k[h+1]=128|e&63,h+=2):(k[h]=224|e>>>12&15,k[h+1]=128|e>>>6&63,k[h+2]=128|e&63,h+=3)}else for("binary"!==c&&n.log("unknown encoding: "+c),d=b.length,k=new Uint8Array(new ArrayBuffer(d)),a=0;a<d;a+=1)k[a]=b.charCodeAt(a)&255;return d=k};this.byteArrayToString=Runtime.byteArrayToString;this.getVa [...]
- this.fromJson=Runtime.fromJson;this.toJson=Runtime.toJson;this.readFile=f;this.read=function(b,c,d,k){f(b,"binary",function(a,e){var h=null;if(e){if("string"===typeof e)throw"This should not happen.";h=e.subarray(c,c+d)}k(a,h)})};this.readFileSync=function(b,r){var d=m(b,r,!1),k;try{d.send(null);k=c(b,r,d);if(k.err)throw k.err;if(null===k.data)throw"No data read from "+b+".";}catch(a){throw a;}return k.data};this.writeFile=function(c,r,d){b[c]=r;var k=new XMLHttpRequest,a;k.open("PUT",c [...]
- function(){4===k.readyState&&(0!==k.status||k.responseText?200<=k.status&&300>k.status||0===k.status?d(null):d("Status "+String(k.status)+": "+k.responseText||k.statusText):d("File "+c+" is empty."))};a=r.buffer&&!k.sendAsBinary?r.buffer:n.byteArrayToString(r,"binary");try{k.sendAsBinary?k.sendAsBinary(a):k.send(a)}catch(e){n.log("HUH? "+e+" "+r),d(e.message)}};this.deleteFile=function(c,r){delete b[c];var d=new XMLHttpRequest;d.open("DELETE",c,!0);d.onreadystatechange=function(){4===d. [...]
- (200>d.status&&300<=d.status?r(d.responseText):r(null))};d.send(null)};this.loadXML=function(b,c){var d=new XMLHttpRequest;d.open("GET",b,!0);d.overrideMimeType&&d.overrideMimeType("text/xml");d.onreadystatechange=function(){4===d.readyState&&(0!==d.status||d.responseText?200===d.status||0===d.status?c(null,d.responseXML):c(d.responseText,null):c("File "+b+" is empty.",null))};try{d.send(null)}catch(k){c(k.message,null)}};this.isFile=function(b,c){n.getFileSize(b,function(d){c(-1!==d)}) [...]
- function(c,r){if(b.hasOwnProperty(c)&&"string"!==typeof b[c])r(b[c].length);else{var d=new XMLHttpRequest;d.open("HEAD",c,!0);d.onreadystatechange=function(){if(4===d.readyState){var b=d.getResponseHeader("Content-Length");b?r(parseInt(b,10)):f(c,"binary",function(a,e){a?r(-1):r(e.length)})}};d.send(null)}};this.log=l;this.assert=function(b,c,d){if(!b)throw l("alert","ASSERTION FAILED:\n"+c),d&&d(),c;};this.setTimeout=function(b,c){return setTimeout(function(){b()},c)};this.clearTimeout [...]
- this.libraryPaths=function(){return["lib"]};this.setCurrentDirectory=function(){};this.type=function(){return"BrowserRuntime"};this.getDOMImplementation=function(){return window.document.implementation};this.parseXML=function(b){return(new DOMParser).parseFromString(b,"text/xml")};this.exit=function(b){l("Calling exit with code "+String(b)+", but exit() is not implemented.")};this.getWindow=function(){return window}}
- function NodeJSRuntime(){function g(b){var d=b.length,k,a=new Uint8Array(new ArrayBuffer(d));for(k=0;k<d;k+=1)a[k]=b[k];return a}function l(b,d,k){function a(a,h){if(a)return k(a,null);if(!h)return k("No data for "+b+".",null);if("string"===typeof h)return k(a,h);k(a,g(h))}b=f.resolve(n,b);"binary"!==d?m.readFile(b,d,a):m.readFile(b,null,a)}var c=this,m=require("fs"),f=require("path"),n="",b,p;this.byteArrayFromString=function(b,d){var k=new Buffer(b,d),a,e=k.length,h=new Uint8Array(new [...]
- for(a=0;a<e;a+=1)h[a]=k[a];return h};this.byteArrayToString=Runtime.byteArrayToString;this.getVariable=Runtime.getVariable;this.fromJson=Runtime.fromJson;this.toJson=Runtime.toJson;this.readFile=l;this.loadXML=function(b,d){l(b,"utf-8",function(k,a){if(k)return d(k,null);if(!a)return d("No data for "+b+".",null);d(null,c.parseXML(a))})};this.writeFile=function(b,d,k){d=new Buffer(d);b=f.resolve(n,b);m.writeFile(b,d,"binary",function(a){k(a||null)})};this.deleteFile=function(b,d){b=f.res [...]
- m.unlink(b,d)};this.read=function(b,d,k,a){b=f.resolve(n,b);m.open(b,"r+",666,function(e,h){if(e)a(e,null);else{var b=new Buffer(k);m.read(h,b,0,k,d,function(e){m.close(h);a(e,g(b))})}})};this.readFileSync=function(b,d){var k=m.readFileSync(b,"binary"===d?null:d);if(null===k)throw"File "+b+" could not be read.";"binary"===d&&(k=g(k));return k};this.isFile=function(b,d){b=f.resolve(n,b);m.stat(b,function(b,a){d(!b&&a.isFile())})};this.getFileSize=function(b,d){b=f.resolve(n,b);m.stat(b,f [...]
- a){b?d(-1):d(a.size)})};this.log=function(b,d){var k;void 0!==d?k=b:d=b;"alert"===k&&process.stderr.write("\n!!!!! ALERT !!!!!\n");process.stderr.write(d+"\n");"alert"===k&&process.stderr.write("!!!!! ALERT !!!!!\n")};this.assert=function(b,d,k){b||(process.stderr.write("ASSERTION FAILED: "+d),k&&k())};this.setTimeout=function(b,d){return setTimeout(function(){b()},d)};this.clearTimeout=function(b){clearTimeout(b)};this.libraryPaths=function(){return[__dirname]};this.setCurrentDirectory [...]
- b};this.currentDirectory=function(){return n};this.type=function(){return"NodeJSRuntime"};this.getDOMImplementation=function(){return p};this.parseXML=function(c){return b.parseFromString(c,"text/xml")};this.exit=process.exit;this.getWindow=function(){return null};b=new (require("xmldom").DOMParser);p=c.parseXML("<a/>").implementation}
- function RhinoRuntime(){function g(b,c){var f;void 0!==c?f=b:c=b;"alert"===f&&print("\n!!!!! ALERT !!!!!");print(c);"alert"===f&&print("!!!!! ALERT !!!!!")}var l=this,c=Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance(),m,f,n="";c.setValidating(!1);c.setNamespaceAware(!0);c.setExpandEntityReferences(!1);c.setSchema(null);f=Packages.org.xml.sax.EntityResolver({resolveEntity:function(b,c){var f=new Packages.java.io.FileReader(c);return new Packages.org.xml.sax.InputSource(f)} [...]
- m.setEntityResolver(f);this.byteArrayFromString=function(b,c){var f=[],d,k=b.length;for(d=0;d<k;d+=1)f[d]=b.charCodeAt(d)&255;return f};this.byteArrayToString=Runtime.byteArrayToString;this.getVariable=Runtime.getVariable;this.fromJson=Runtime.fromJson;this.toJson=Runtime.toJson;this.loadXML=function(b,c){var f=new Packages.java.io.File(b),d;try{d=m.parse(f)}catch(k){print(k);c(k);return}c(null,d)};this.readFile=function(b,c,f){n&&(b=n+"/"+b);var d=new Packages.java.io.File(b),k="binary [...]
- c;d.isFile()?(b=readFile(b,k),"binary"===c&&(b=l.byteArrayFromString(b,"binary")),f(null,b)):f(b+" is not a file.")};this.writeFile=function(b,c,f){n&&(b=n+"/"+b);b=new Packages.java.io.FileOutputStream(b);var d,k=c.length;for(d=0;d<k;d+=1)b.write(c[d]);b.close();f(null)};this.deleteFile=function(b,c){n&&(b=n+"/"+b);(new Packages.java.io.File(b))["delete"]()?c(null):c("Could not delete "+b)};this.read=function(b,c,f,d){n&&(b=n+"/"+b);var k;k=b;var a="binary";(new Packages.java.io.File(k [...]
- ("binary"===a&&(a="latin1"),k=readFile(k,a)):k=null;k?d(null,this.byteArrayFromString(k.substring(c,c+f),"binary")):d("Cannot read "+b)};this.readFileSync=function(b,c){if(!c)return"";var f=readFile(b,c);if(null===f)throw"File could not be read.";return f};this.isFile=function(b,c){n&&(b=n+"/"+b);var f=new Packages.java.io.File(b);c(f.isFile())};this.getFileSize=function(b,c){n&&(b=n+"/"+b);var f=new Packages.java.io.File(b);c(f.length())};this.log=g;this.assert=function(b,c,f){b||(g("a [...]
- c),f&&f())};this.setTimeout=function(b){b();return 0};this.clearTimeout=function(){};this.libraryPaths=function(){return["lib"]};this.setCurrentDirectory=function(b){n=b};this.currentDirectory=function(){return n};this.type=function(){return"RhinoRuntime"};this.getDOMImplementation=function(){return m.getDOMImplementation()};this.parseXML=function(b){return m.parse(b)};this.exit=quit;this.getWindow=function(){return null}}
- var runtime=function(){return"undefined"!==String(typeof window)?new BrowserRuntime(window.document.getElementById("logoutput")):"undefined"!==String(typeof require)?new NodeJSRuntime:new RhinoRuntime}();
- (function(){function g(c){var f=c[0],g;g=eval("if (typeof "+f+" === 'undefined') {eval('"+f+" = {};');}"+f);for(f=1;f<c.length-1;f+=1)g=g.hasOwnProperty(c[f])?g[c[f]]:g[c[f]]={};return g[c[c.length-1]]}var l={},c={};runtime.loadClass=function(m){function f(b){b=b.replace(/\./g,"/")+".js";var d=runtime.libraryPaths(),k,a,e,h;runtime.currentDirectory&&d.push(runtime.currentDirectory());for(k=0;k<d.length;k+=1){a=d[k];if(!c.hasOwnProperty(a))try{(e=runtime.readFileSync(d[k]+"/manifest.js", [...]
- e.length?(h=e,c[a]=eval(h)):c[a]=null}catch(q){c[a]=null,runtime.log("Cannot load manifest for "+a+".")}e=null;if((a=c[a])&&a.indexOf&&-1!==a.indexOf(b))return d[k]+"/"+b}return null}function n(b){var d,c;c=f(b);if(!c)throw b+" is not listed in any manifest.js.";try{d=runtime.readFileSync(c,"utf8")}catch(a){throw runtime.log("Error loading "+b+" "+a),a;}if(void 0===d)throw"Cannot load class "+b;d=d+("\n//# sourceURL="+c)+("\n//@ sourceURL="+c);try{d=eval(b+" = eval(code);")}catch(e){thr [...]
- b+" "+e),e;}return d}if(!IS_COMPILED_CODE&&!l.hasOwnProperty(m)){var b=m.split("."),p;p=g(b);if(!p&&(p=n(m),!p||Runtime.getFunctionName(p)!==b[b.length-1]))throw runtime.log("Loaded code is not for "+b[b.length-1]),"Loaded code is not for "+b[b.length-1];l[m]=!0}}})();(function(){var g=function(){};runtime.getTranslator=function(){return g};runtime.setTranslator=function(l){g=l};runtime.tr=function(l){var c=g(l);return c&&"string"===String(typeof c)?c:l}})();
- (function(g){function l(c){if(c.length){var g=c[0];runtime.readFile(g,"utf8",function(f,l){function b(){var b;(b=eval(r))&&runtime.exit(b)}var p="",r=l;-1!==g.indexOf("/")&&(p=g.substring(0,g.indexOf("/")));runtime.setCurrentDirectory(p);f?(runtime.log(f),runtime.exit(1)):null===r?(runtime.log("No code found for "+g),runtime.exit(1)):b.apply(null,c)})}}g=g?Array.prototype.slice.call(g):[];"NodeJSRuntime"===runtime.type()?l(process.argv.slice(2)):"RhinoRuntime"===runtime.type()?l(g):l(g. [...]
++function Runtime(){}Runtime.prototype.getVariable=function(g){};Runtime.prototype.toJson=function(g){};Runtime.prototype.fromJson=function(g){};Runtime.prototype.byteArrayFromString=function(g,k){};Runtime.prototype.byteArrayToString=function(g,k){};Runtime.prototype.read=function(g,k,e,n){};Runtime.prototype.readFile=function(g,k,e){};Runtime.prototype.readFileSync=function(g,k){};Runtime.prototype.loadXML=function(g,k){};Runtime.prototype.writeFile=function(g,k,e){};
++Runtime.prototype.isFile=function(g,k){};Runtime.prototype.getFileSize=function(g,k){};Runtime.prototype.deleteFile=function(g,k){};Runtime.prototype.log=function(g,k){};Runtime.prototype.setTimeout=function(g,k){};Runtime.prototype.clearTimeout=function(g){};Runtime.prototype.libraryPaths=function(){};Runtime.prototype.currentDirectory=function(){};Runtime.prototype.setCurrentDirectory=function(g){};Runtime.prototype.type=function(){};Runtime.prototype.getDOMImplementation=function(){};
++Runtime.prototype.parseXML=function(g){};Runtime.prototype.exit=function(g){};Runtime.prototype.getWindow=function(){};Runtime.prototype.assert=function(g,k,e){};var IS_COMPILED_CODE=!0;
++Runtime.byteArrayToString=function(g,k){function e(e){var b="",h,r=e.length;for(h=0;h<r;h+=1)b+=String.fromCharCode(e[h]&255);return b}function n(e){var b="",h,r=e.length,d=[],f,a,c,p;for(h=0;h<r;h+=1)f=e[h],128>f?d.push(f):(h+=1,a=e[h],194<=f&&224>f?d.push((f&31)<<6|a&63):(h+=1,c=e[h],224<=f&&240>f?d.push((f&15)<<12|(a&63)<<6|c&63):(h+=1,p=e[h],240<=f&&245>f&&(f=(f&7)<<18|(a&63)<<12|(c&63)<<6|p&63,f-=65536,d.push((f>>10)+55296,(f&1023)+56320))))),1E3===d.length&&(b+=String.fromCharCode [...]
++d),d.length=0);return b+String.fromCharCode.apply(null,d)}var m;"utf8"===k?m=n(g):("binary"!==k&&this.log("Unsupported encoding: "+k),m=e(g));return m};Runtime.getVariable=function(g){try{return eval(g)}catch(k){}};Runtime.toJson=function(g){return JSON.stringify(g)};Runtime.fromJson=function(g){return JSON.parse(g)};Runtime.getFunctionName=function(g){return void 0===g.name?(g=/function\s+(\w+)/.exec(g))&&g[1]:g.name};
++function BrowserRuntime(g){function k(h,b){var d,f,a;void 0!==b?a=h:b=h;g?(f=g.ownerDocument,a&&(d=f.createElement("span"),d.className=a,d.appendChild(f.createTextNode(a)),g.appendChild(d),g.appendChild(f.createTextNode(" "))),d=f.createElement("span"),0<b.length&&"<"===b[0]?d.innerHTML=b:d.appendChild(f.createTextNode(b)),g.appendChild(d),g.appendChild(f.createElement("br"))):console&&console.log(b);"alert"===a&&alert(b)}function e(h,r,d){if(0!==d.status||d.responseText)if(200===d.stat [...]
++"string"!==typeof d.response)"binary"===r?(r=d.response,r=new Uint8Array(r)):r=String(d.response);else if("binary"===r)if(null!==d.responseBody&&"undefined"!==String(typeof VBArray)){r=(new VBArray(d.responseBody)).toArray();d=r.length;var f,a=new Uint8Array(new ArrayBuffer(d));for(f=0;f<d;f+=1)a[f]=r[f];r=a}else r=q.byteArrayFromString(d.responseText,"binary");else r=d.responseText;b[h]=r;h={err:null,data:r}}else h={err:d.responseText||d.statusText,data:null};else h={err:"File "+h+" is [...]
++return h}function n(h,b,d){var f=new XMLHttpRequest;f.open("GET",h,d);f.overrideMimeType&&("binary"!==b?f.overrideMimeType("text/plain; charset="+b):f.overrideMimeType("text/plain; charset=x-user-defined"));return f}function m(h,r,d){function f(){var c;4===a.readyState&&(c=e(h,r,a),d(c.err,c.data))}if(b.hasOwnProperty(h))d(null,b[h]);else{var a=n(h,r,!0);a.onreadystatechange=f;try{a.send(null)}catch(c){d(c.message,null)}}}var q=this,b={};this.byteArrayFromString=function(b,e){var d;if(" [...]
++b.length;var f,a,c,p=0;for(a=0;a<d;a+=1)c=b.charCodeAt(a),p+=1+(128<c)+(2048<c);f=new Uint8Array(new ArrayBuffer(p));for(a=p=0;a<d;a+=1)c=b.charCodeAt(a),128>c?(f[p]=c,p+=1):2048>c?(f[p]=192|c>>>6,f[p+1]=128|c&63,p+=2):(f[p]=224|c>>>12&15,f[p+1]=128|c>>>6&63,f[p+2]=128|c&63,p+=3)}else for("binary"!==e&&q.log("unknown encoding: "+e),d=b.length,f=new Uint8Array(new ArrayBuffer(d)),a=0;a<d;a+=1)f[a]=b.charCodeAt(a)&255;return d=f};this.byteArrayToString=Runtime.byteArrayToString;this.getVa [...]
++this.fromJson=Runtime.fromJson;this.toJson=Runtime.toJson;this.readFile=m;this.read=function(b,e,d,f){m(b,"binary",function(a,c){var p=null;if(c){if("string"===typeof c)throw"This should not happen.";p=c.subarray(e,e+d)}f(a,p)})};this.readFileSync=function(b,r){var d=n(b,r,!1),f;try{d.send(null);f=e(b,r,d);if(f.err)throw f.err;if(null===f.data)throw"No data read from "+b+".";}catch(a){throw a;}return f.data};this.writeFile=function(h,e,d){b[h]=e;var f=new XMLHttpRequest,a;f.open("PUT",h [...]
++function(){4===f.readyState&&(0!==f.status||f.responseText?200<=f.status&&300>f.status||0===f.status?d(null):d("Status "+String(f.status)+": "+f.responseText||f.statusText):d("File "+h+" is empty."))};a=e.buffer&&!f.sendAsBinary?e.buffer:q.byteArrayToString(e,"binary");try{f.sendAsBinary?f.sendAsBinary(a):f.send(a)}catch(c){q.log("HUH? "+c+" "+e),d(c.message)}};this.deleteFile=function(h,e){delete b[h];var d=new XMLHttpRequest;d.open("DELETE",h,!0);d.onreadystatechange=function(){4===d. [...]
++(200>d.status&&300<=d.status?e(d.responseText):e(null))};d.send(null)};this.loadXML=function(b,e){var d=new XMLHttpRequest;d.open("GET",b,!0);d.overrideMimeType&&d.overrideMimeType("text/xml");d.onreadystatechange=function(){4===d.readyState&&(0!==d.status||d.responseText?200===d.status||0===d.status?e(null,d.responseXML):e(d.responseText,null):e("File "+b+" is empty.",null))};try{d.send(null)}catch(f){e(f.message,null)}};this.isFile=function(b,e){q.getFileSize(b,function(d){e(-1!==d)}) [...]
++function(h,e){if(b.hasOwnProperty(h)&&"string"!==typeof b[h])e(b[h].length);else{var d=new XMLHttpRequest;d.open("HEAD",h,!0);d.onreadystatechange=function(){if(4===d.readyState){var f=d.getResponseHeader("Content-Length");f?e(parseInt(f,10)):m(h,"binary",function(a,c){a?e(-1):e(c.length)})}};d.send(null)}};this.log=k;this.assert=function(b,e,d){if(!b)throw k("alert","ASSERTION FAILED:\n"+e),d&&d(),e;};this.setTimeout=function(b,e){return setTimeout(function(){b()},e)};this.clearTimeout [...]
++this.libraryPaths=function(){return["lib"]};this.setCurrentDirectory=function(){};this.currentDirectory=function(){return""};this.type=function(){return"BrowserRuntime"};this.getDOMImplementation=function(){return window.document.implementation};this.parseXML=function(b){return(new DOMParser).parseFromString(b,"text/xml")};this.exit=function(b){k("Calling exit with code "+String(b)+", but exit() is not implemented.")};this.getWindow=function(){return window}}
++function NodeJSRuntime(){function g(b){var d=b.length,f,a=new Uint8Array(new ArrayBuffer(d));for(f=0;f<d;f+=1)a[f]=b[f];return a}function k(b,d,f){function a(a,d){if(a)return f(a,null);if(!d)return f("No data for "+b+".",null);if("string"===typeof d)return f(a,d);f(a,g(d))}b=m.resolve(q,b);"binary"!==d?n.readFile(b,d,a):n.readFile(b,null,a)}var e=this,n=require("fs"),m=require("path"),q="",b,h;this.byteArrayFromString=function(b,d){var f=new Buffer(b,d),a,c=f.length,p=new Uint8Array(new [...]
++for(a=0;a<c;a+=1)p[a]=f[a];return p};this.byteArrayToString=Runtime.byteArrayToString;this.getVariable=Runtime.getVariable;this.fromJson=Runtime.fromJson;this.toJson=Runtime.toJson;this.readFile=k;this.loadXML=function(b,d){k(b,"utf-8",function(f,a){if(f)return d(f,null);if(!a)return d("No data for "+b+".",null);d(null,e.parseXML(a))})};this.writeFile=function(b,d,f){d=new Buffer(d);b=m.resolve(q,b);n.writeFile(b,d,"binary",function(a){f(a||null)})};this.deleteFile=function(b,d){b=m.res [...]
++n.unlink(b,d)};this.read=function(b,d,f,a){b=m.resolve(q,b);n.open(b,"r+",666,function(c,p){if(c)a(c,null);else{var l=new Buffer(f);n.read(p,l,0,f,d,function(c){n.close(p);a(c,g(l))})}})};this.readFileSync=function(b,d){var f;f=n.readFileSync(b,"binary"===d?null:d);if(null===f)throw"File "+b+" could not be read.";"binary"===d&&(f=g(f));return f};this.isFile=function(b,d){b=m.resolve(q,b);n.stat(b,function(f,a){d(!f&&a.isFile())})};this.getFileSize=function(b,d){b=m.resolve(q,b);n.stat(b [...]
++a){f?d(-1):d(a.size)})};this.log=function(b,d){var f;void 0!==d?f=b:d=b;"alert"===f&&process.stderr.write("\n!!!!! ALERT !!!!!\n");process.stderr.write(d+"\n");"alert"===f&&process.stderr.write("!!!!! ALERT !!!!!\n")};this.assert=function(b,d,f){b||(process.stderr.write("ASSERTION FAILED: "+d),f&&f())};this.setTimeout=function(b,d){return setTimeout(function(){b()},d)};this.clearTimeout=function(b){clearTimeout(b)};this.libraryPaths=function(){return[__dirname]};this.setCurrentDirectory [...]
++b};this.currentDirectory=function(){return q};this.type=function(){return"NodeJSRuntime"};this.getDOMImplementation=function(){return h};this.parseXML=function(e){return b.parseFromString(e,"text/xml")};this.exit=process.exit;this.getWindow=function(){return null};b=new (require("xmldom").DOMParser);h=e.parseXML("<a/>").implementation}
++function RhinoRuntime(){function g(b,e){var d;void 0!==e?d=b:e=b;"alert"===d&&print("\n!!!!! ALERT !!!!!");print(e);"alert"===d&&print("!!!!! ALERT !!!!!")}var k=this,e={},n=e.javax.xml.parsers.DocumentBuilderFactory.newInstance(),m,q,b="";n.setValidating(!1);n.setNamespaceAware(!0);n.setExpandEntityReferences(!1);n.setSchema(null);q=e.org.xml.sax.EntityResolver({resolveEntity:function(b,m){var d=new e.java.io.FileReader(m);return new e.org.xml.sax.InputSource(d)}});m=n.newDocumentBuild [...]
++this.byteArrayFromString=function(b,e){var d,f=b.length,a=new Uint8Array(new ArrayBuffer(f));for(d=0;d<f;d+=1)a[d]=b.charCodeAt(d)&255;return a};this.byteArrayToString=Runtime.byteArrayToString;this.getVariable=Runtime.getVariable;this.fromJson=Runtime.fromJson;this.toJson=Runtime.toJson;this.loadXML=function(b,g){var d=new e.java.io.File(b),f=null;try{f=m.parse(d)}catch(a){return print(a),g(a,null)}g(null,f)};this.readFile=function(h,m,d){b&&(h=b+"/"+h);var f=new e.java.io.File(h),a="b [...]
++"latin1":m;f.isFile()?((h=readFile(h,a))&&"binary"===m&&(h=k.byteArrayFromString(h,"binary")),d(null,h)):d(h+" is not a file.",null)};this.writeFile=function(h,m,d){b&&(h=b+"/"+h);h=new e.java.io.FileOutputStream(h);var f,a=m.length;for(f=0;f<a;f+=1)h.write(m[f]);h.close();d(null)};this.deleteFile=function(h,m){b&&(h=b+"/"+h);var d=new e.java.io.File(h),f=h+Math.random(),f=new e.java.io.File(f);d.rename(f)?(f.deleteOnExit(),m(null)):m("Could not delete "+h)};this.read=function(h,m,d,f){ [...]
++h);var a;a=h;var c="binary";(new e.java.io.File(a)).isFile()?("binary"===c&&(c="latin1"),a=readFile(a,c)):a=null;a?f(null,this.byteArrayFromString(a.substring(m,m+d),"binary")):f("Cannot read "+h,null)};this.readFileSync=function(b,e){if(!e)return"";var d=readFile(b,e);if(null===d)throw"File could not be read.";return d};this.isFile=function(h,m){b&&(h=b+"/"+h);var d=new e.java.io.File(h);m(d.isFile())};this.getFileSize=function(h,m){b&&(h=b+"/"+h);var d=new e.java.io.File(h);m(d.length [...]
++g;this.assert=function(b,e,d){b||(g("alert","ASSERTION FAILED: "+e),d&&d())};this.setTimeout=function(b){b();return 0};this.clearTimeout=function(){};this.libraryPaths=function(){return["lib"]};this.setCurrentDirectory=function(e){b=e};this.currentDirectory=function(){return b};this.type=function(){return"RhinoRuntime"};this.getDOMImplementation=function(){return m.getDOMImplementation()};this.parseXML=function(b){b=new e.java.io.StringReader(b);b=new e.org.xml.sax.InputSource(b);return [...]
++this.exit=quit;this.getWindow=function(){return null}}Runtime.create=function(){return"undefined"!==String(typeof window)?new BrowserRuntime(window.document.getElementById("logoutput")):"undefined"!==String(typeof require)?new NodeJSRuntime:new RhinoRuntime};var runtime=Runtime.create(),core={},gui={},xmldom={},odf={},ops={};
++(function(){function g(b,e){var m=b+"/manifest.json",d,f;if(!q.hasOwnProperty(m)){q[m]=1;try{d=runtime.readFileSync(m,"utf-8")}catch(a){console.log(String(a));return}m=JSON.parse(d);for(f in m)m.hasOwnProperty(f)&&(e[f]={dir:b,deps:m[f]})}}function k(b,e,m){var d=e[b].deps,f={};m[b]=f;d.forEach(function(a){f[a]=1});d.forEach(function(a){m[a]||k(a,e,m)});d.forEach(function(a){Object.keys(m[a]).forEach(function(a){f[a]=1})})}function e(b,e){function m(a,c){var d,l=e[a];if(-1===f.indexOf(a [...]
++for(d=0;d<b.length;d+=1)l[b[d]]&&m(b[d],c);c.pop();f.push(a)}}var d,f=[];for(d=0;d<b.length;d+=1)m(b[d],[]);return f}function n(b,e){for(var m=0;m<b.length&&void 0!==e[m];)null!==e[m]&&(eval(e[m]),e[m]=null),m+=1}var m={},q={};runtime.loadClass=function(b){if(!IS_COMPILED_CODE){var h=b.replace(".","/")+".js";if(!q.hasOwnProperty(h)){if(!(0<Object.keys(m).length)){var r=runtime.libraryPaths(),h={},d;runtime.currentDirectory()&&g(runtime.currentDirectory(),h);for(d=0;d<r.length;d+=1)g(r[d [...]
++d={};for(f in h)h.hasOwnProperty(f)&&k(f,h,d);for(f in h)h.hasOwnProperty(f)&&(r=Object.keys(d[f]),h[f].deps=e(r,d),h[f].deps.push(f));m=h}f=b.replace(".","/")+".js";b=[];f=m[f].deps;for(h=0;h<f.length;h+=1)q.hasOwnProperty(f[h])||b.push(f[h]);f=[];f.length=b.length;for(h=b.length-1;0<=h;h-=1)q[b[h]]=1,void 0===f[h]&&(r=b[h],r=m[r].dir+"/"+r,d=runtime.readFileSync(r,"utf-8"),d+="\n//# sourceURL="+r,d+="\n//@ sourceURL="+r,f[h]=d);n(b,f)}}}})();
++(function(){var g=function(g){return g};runtime.getTranslator=function(){return g};runtime.setTranslator=function(k){g=k};runtime.tr=function(k){var e=g(k);return e&&"string"===String(typeof e)?e:k}})();
++(function(g){function k(e){if(e.length){var g=e[0];runtime.readFile(g,"utf8",function(m,k){function b(){var d;(d=eval(r))&&runtime.exit(d)}var h="",r=k;-1!==g.indexOf("/")&&(h=g.substring(0,g.indexOf("/")));runtime.setCurrentDirectory(h);m?(runtime.log(m),runtime.exit(1)):null===r?(runtime.log("No code found for "+g),runtime.exit(1)):b.apply(null,e)})}}g=g?Array.prototype.slice.call(g):[];"NodeJSRuntime"===runtime.type()?k(process.argv.slice(2)):"RhinoRuntime"===runtime.type()?k(g):k(g. [...]
+String(typeof arguments)&&arguments);
+// Input 2
- function makeBase64(){function g(a){var e,h=a.length,b=new Uint8Array(new ArrayBuffer(h));for(e=0;e<h;e+=1)b[e]=a.charCodeAt(e)&255;return b}function l(a){var e,h="",b,d=a.length-2;for(b=0;b<d;b+=3)e=a[b]<<16|a[b+1]<<8|a[b+2],h+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e>>>18],h+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e>>>12&63],h+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e>>>6&63],h+="ABCDEFGHIJKLMNOPQRSTUV [...]
- 63];b===d+1?(e=a[b]<<4,h+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e>>>6],h+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e&63],h+="=="):b===d&&(e=a[b]<<10|a[b+1]<<2,h+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e>>>12],h+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e>>>6&63],h+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e&63],h+="=");return h}function c(a){a=a.replace( [...]
- "");var e=a.length,h=new Uint8Array(new ArrayBuffer(3*e)),b=a.length%4,d=0,c,k;for(c=0;c<e;c+=4)k=(q[a.charAt(c)]||0)<<18|(q[a.charAt(c+1)]||0)<<12|(q[a.charAt(c+2)]||0)<<6|(q[a.charAt(c+3)]||0),h[d]=k>>16,h[d+1]=k>>8&255,h[d+2]=k&255,d+=3;e=3*e-[0,0,2,1][b];return h.subarray(0,e)}function m(a){var e,h,b=a.length,d=0,c=new Uint8Array(new ArrayBuffer(3*b));for(e=0;e<b;e+=1)h=a[e],128>h?c[d++]=h:(2048>h?c[d++]=192|h>>>6:(c[d++]=224|h>>>12&15,c[d++]=128|h>>>6&63),c[d++]=128|h&63);return c. [...]
- d)}function f(a){var e,h,b,d,c=a.length,k=new Uint8Array(new ArrayBuffer(c)),q=0;for(e=0;e<c;e+=1)h=a[e],128>h?k[q++]=h:(e+=1,b=a[e],224>h?k[q++]=(h&31)<<6|b&63:(e+=1,d=a[e],k[q++]=(h&15)<<12|(b&63)<<6|d&63));return k.subarray(0,q)}function n(a){return l(g(a))}function b(a){return String.fromCharCode.apply(String,c(a))}function p(a){return f(g(a))}function r(a){a=f(a);for(var e="",h=0;h<a.length;)e+=String.fromCharCode.apply(String,a.subarray(h,h+45E3)),h+=45E3;return e}function d(a,e,h [...]
- c,k="";for(c=e;c<h;c+=1)e=a.charCodeAt(c)&255,128>e?k+=String.fromCharCode(e):(c+=1,b=a.charCodeAt(c)&255,224>e?k+=String.fromCharCode((e&31)<<6|b&63):(c+=1,d=a.charCodeAt(c)&255,k+=String.fromCharCode((e&15)<<12|(b&63)<<6|d&63)));return k}function k(a,e){function h(){var k=c+1E5;k>a.length&&(k=a.length);b+=d(a,c,k);c=k;k=c===a.length;e(b,k)&&!k&&runtime.setTimeout(h,0)}var b="",c=0;1E5>a.length?e(d(a,0,a.length),!0):("string"!==typeof a&&(a=a.slice()),h())}function a(a){return m(g(a))} [...]
- m(a))}function h(a){return String.fromCharCode.apply(String,m(g(a)))}var q=function(a){var e={},h,b;h=0;for(b=a.length;h<b;h+=1)e[a.charAt(h)]=h;return e}("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),u,x,v=runtime.getWindow(),y,w;v&&v.btoa?(y=v.btoa,u=function(a){return y(h(a))}):(y=n,u=function(e){return l(a(e))});v&&v.atob?(w=v.atob,x=function(a){a=w(a);return d(a,0,a.length)}):(w=b,x=function(a){return r(c(a))});core.Base64=function(){this.convertByteArrayToBas [...]
- l;this.convertBase64ToByteArray=this.convertBase64ToUTF8Array=c;this.convertUTF16ArrayToByteArray=this.convertUTF16ArrayToUTF8Array=m;this.convertByteArrayToUTF16Array=this.convertUTF8ArrayToUTF16Array=f;this.convertUTF8StringToBase64=n;this.convertBase64ToUTF8String=b;this.convertUTF8StringToUTF16Array=p;this.convertByteArrayToUTF16String=this.convertUTF8ArrayToUTF16String=r;this.convertUTF8StringToUTF16String=k;this.convertUTF16StringToByteArray=this.convertUTF16StringToUTF8Array=a;th [...]
- e;this.convertUTF16StringToUTF8String=h;this.convertUTF16StringToBase64=u;this.convertBase64ToUTF16String=x;this.fromBase64=b;this.toBase64=n;this.atob=w;this.btoa=y;this.utob=h;this.btou=k;this.encode=u;this.encodeURI=function(a){return u(a).replace(/[+\/]/g,function(a){return"+"===a?"-":"_"}).replace(/\\=+$/,"")};this.decode=function(a){return x(a.replace(/[\-_]/g,function(a){return"-"===a?"+":"/"}))};return this};return core.Base64}core.Base64=makeBase64();
++core.Async=function(){this.forEach=function(g,k,e){function n(h){b!==q&&(h?(b=q,e(h)):(b+=1,b===q&&e(null)))}var m,q=g.length,b=0;for(m=0;m<q;m+=1)k(g[m],n)};this.destroyAll=function(g,k){function e(n,m){if(m)k(m);else if(n<g.length)g[n](function(m){e(n+1,m)});else k()}e(0,void 0)}};
+// Input 3
- core.RawDeflate=function(){function g(){this.dl=this.fc=0}function l(){this.extra_bits=this.static_tree=this.dyn_tree=null;this.max_code=this.max_length=this.elems=this.extra_base=0}function c(a,e,h,b){this.good_length=a;this.max_lazy=e;this.nice_length=h;this.max_chain=b}function m(){this.next=null;this.len=0;this.ptr=[];this.ptr.length=f;this.off=0}var f=8192,n,b,p,r,d=null,k,a,e,h,q,u,x,v,y,w,t,s,D,A,B,M,z,K,F,Q,$,ia,R,ma,ba,ga,S,Y,V,G,I,ha,N,O,Z,ka,ca,T,P,L,ea,E,U,H,la,fa,W,ja,C,sa, [...]
- 0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],oa=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],za=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],va=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],wa;wa=[new c(0,0,0,0),new c(4,4,8,4),new c(4,5,16,8),new c(4,6,32,32),new c(4,4,16,16),new c(8,16,32,32),new c(8,16,128,128),new c(8,32,128,256),new c(32,128,258,1024),new c(32,258,258,4096)];var da=function(e){d[a+k++]=e;if(a+k===f){var h;if(0!==k){null!==n?(e=n,n=n. [...]
- e.next=null;e.len=e.off=0;null===b?b=p=e:p=p.next=e;e.len=k-a;for(h=0;h<e.len;h++)e.ptr[h]=d[a+h];k=a=0}}},X=function(e){e&=65535;a+k<f-2?(d[a+k++]=e&255,d[a+k++]=e>>>8):(da(e&255),da(e>>>8))},qa=function(){t=(t<<5^h[z+3-1]&255)&8191;s=x[32768+t];x[z&32767]=s;x[32768+t]=z},aa=function(a,e){y>16-e?(v|=a<<y,X(v),v=a>>16-y,y+=e-16):(v|=a<<y,y+=e)},J=function(a,e){aa(e[a].fc,e[a].dl)},pa=function(a,e,h){return a[e].fc<a[h].fc||a[e].fc===a[h].fc&&ca[e]<=ca[h]},Aa=function(a,e,h){var b;for(b= [...]
- sa.length;b++)a[e+b]=sa.charCodeAt(na++)&255;return b},ua=function(){var a,e,b=65536-Q-z;if(-1===b)b--;else if(65274<=z){for(a=0;32768>a;a++)h[a]=h[a+32768];K-=32768;z-=32768;w-=32768;for(a=0;8192>a;a++)e=x[32768+a],x[32768+a]=32768<=e?e-32768:0;for(a=0;32768>a;a++)e=x[a],x[a]=32768<=e?e-32768:0;b+=32768}F||(a=Aa(h,z+Q,b),0>=a?F=!0:Q+=a)},ya=function(a){var e=$,b=z,d,c=M,k=32506<z?z-32506:0,q=z+258,f=h[b+c-1],s=h[b+c];M>=ma&&(e>>=2);do if(d=a,h[d+c]===s&&h[d+c-1]===f&&h[d]===h[b]&&h[++d [...]
- 2;d++;do++b;while(h[b]===h[++d]&&h[++b]===h[++d]&&h[++b]===h[++d]&&h[++b]===h[++d]&&h[++b]===h[++d]&&h[++b]===h[++d]&&h[++b]===h[++d]&&h[++b]===h[++d]&&b<q);d=258-(q-b);b=q-258;if(d>c){K=a;c=d;if(258<=d)break;f=h[b+c-1];s=h[b+c]}a=x[a&32767]}while(a>k&&0!==--e);return c},ra=function(a,e){u[U++]=e;0===a?ba[e].fc++:(a--,ba[T[e]+256+1].fc++,ga[(256>a?P[a]:P[256+(a>>7)])&255].fc++,q[H++]=a,fa|=W);W<<=1;0===(U&7)&&(E[la++]=fa,fa=0,W=1);if(2<R&&0===(U&4095)){var h=8*U,b=z-w,d;for(d=0;30>d;d++ [...]
- (5+oa[d]);h>>=3;if(H<parseInt(U/2,10)&&h<parseInt(b/2,10))return!0}return 8191===U||8192===H},xa=function(a,e){for(var h=O[e],b=e<<1;b<=Z;){b<Z&&pa(a,O[b+1],O[b])&&b++;if(pa(a,h,O[b]))break;O[e]=O[b];e=b;b<<=1}O[e]=h},Ba=function(a,e){var h=0;do h|=a&1,a>>=1,h<<=1;while(0<--e);return h>>1},Ea=function(a,e){var h=[];h.length=16;var b=0,d;for(d=1;15>=d;d++)b=b+N[d-1]<<1,h[d]=b;for(b=0;b<=e;b++)d=a[b].dl,0!==d&&(a[b].fc=Ba(h[d]++,d))},Da=function(a){var e=a.dyn_tree,h=a.static_tree,b=a.ele [...]
- k=b;Z=0;ka=573;for(d=0;d<b;d++)0!==e[d].fc?(O[++Z]=c=d,ca[d]=0):e[d].dl=0;for(;2>Z;)d=O[++Z]=2>c?++c:0,e[d].fc=1,ca[d]=0,ja--,null!==h&&(C-=h[d].dl);a.max_code=c;for(d=Z>>1;1<=d;d--)xa(e,d);do d=O[1],O[1]=O[Z--],xa(e,1),h=O[1],O[--ka]=d,O[--ka]=h,e[k].fc=e[d].fc+e[h].fc,ca[k]=ca[d]>ca[h]+1?ca[d]:ca[h]+1,e[d].dl=e[h].dl=k,O[1]=k++,xa(e,1);while(2<=Z);O[--ka]=O[1];k=a.dyn_tree;d=a.extra_bits;var b=a.extra_base,h=a.max_code,q=a.max_length,f=a.static_tree,s,g,l,p,B=0;for(g=0;15>=g;g++)N[g]= [...]
- 0;for(a=ka+1;573>a;a++)s=O[a],g=k[k[s].dl].dl+1,g>q&&(g=q,B++),k[s].dl=g,s>h||(N[g]++,l=0,s>=b&&(l=d[s-b]),p=k[s].fc,ja+=p*(g+l),null!==f&&(C+=p*(f[s].dl+l)));if(0!==B){do{for(g=q-1;0===N[g];)g--;N[g]--;N[g+1]+=2;N[q]--;B-=2}while(0<B);for(g=q;0!==g;g--)for(s=N[g];0!==s;)d=O[--a],d>h||(k[d].dl!==g&&(ja+=(g-k[d].dl)*k[d].fc,k[d].fc=g),s--)}Ea(e,c)},Fa=function(a,e){var h,b=-1,d,c=a[0].dl,k=0,q=7,f=4;0===c&&(q=138,f=3);a[e+1].dl=65535;for(h=0;h<=e;h++)d=c,c=a[h+1].dl,++k<q&&d===c||(k<f?V[ [...]
- d?(d!==b&&V[d].fc++,V[16].fc++):10>=k?V[17].fc++:V[18].fc++,k=0,b=d,0===c?(q=138,f=3):d===c?(q=6,f=3):(q=7,f=4))},Ga=function(){8<y?X(v):0<y&&da(v);y=v=0},Ha=function(a,e){var h,b=0,d=0,c=0,k=0,f,g;if(0!==U){do 0===(b&7)&&(k=E[c++]),h=u[b++]&255,0===(k&1)?J(h,a):(f=T[h],J(f+256+1,a),g=ta[f],0!==g&&(h-=L[f],aa(h,g)),h=q[d++],f=(256>h?P[h]:P[256+(h>>7)])&255,J(f,e),g=oa[f],0!==g&&(h-=ea[f],aa(h,g))),k>>=1;while(b<U)}J(256,a)},Ia=function(a,e){var h,b=-1,d,c=a[0].dl,k=0,q=7,f=4;0===c&&(q=1 [...]
- 0;h<=e;h++)if(d=c,c=a[h+1].dl,!(++k<q&&d===c)){if(k<f){do J(d,V);while(0!==--k)}else 0!==d?(d!==b&&(J(d,V),k--),J(16,V),aa(k-3,2)):10>=k?(J(17,V),aa(k-3,3)):(J(18,V),aa(k-11,7));k=0;b=d;0===c?(q=138,f=3):d===c?(q=6,f=3):(q=7,f=4)}},Ja=function(){var a;for(a=0;286>a;a++)ba[a].fc=0;for(a=0;30>a;a++)ga[a].fc=0;for(a=0;19>a;a++)V[a].fc=0;ba[256].fc=1;fa=U=H=la=ja=C=0;W=1},Ca=function(a){var e,b,d,c;c=z-w;E[la]=fa;Da(G);Da(I);Fa(ba,G.max_code);Fa(ga,I.max_code);Da(ha);for(d=18;3<=d&&0===V[va [...]
- ja+=3*(d+1)+14;e=ja+3+7>>3;b=C+3+7>>3;b<=e&&(e=b);if(c+4<=e&&0<=w)for(aa(0+a,3),Ga(),X(c),X(~c),d=0;d<c;d++)da(h[w+d]);else if(b===e)aa(2+a,3),Ha(S,Y);else{aa(4+a,3);c=G.max_code+1;e=I.max_code+1;d+=1;aa(c-257,5);aa(e-1,5);aa(d-4,4);for(b=0;b<d;b++)aa(V[va[b]].dl,3);Ia(ba,c-1);Ia(ga,e-1);Ha(ba,ga)}Ja();0!==a&&Ga()},Ka=function(e,h,c){var q,f,g;for(q=0;null!==b&&q<c;){f=c-q;f>b.len&&(f=b.len);for(g=0;g<f;g++)e[h+q+g]=b.ptr[b.off+g];b.off+=f;b.len-=f;q+=f;0===b.len&&(f=b,b=b.next,f.next=n [...]
- c)return q;if(a<k){f=c-q;f>k-a&&(f=k-a);for(g=0;g<f;g++)e[h+q+g]=d[a+g];a+=f;q+=f;k===a&&(k=a=0)}return q},La=function(d,c,q){var f;if(!r){if(!F){y=v=0;var g,l;if(0===Y[0].dl){G.dyn_tree=ba;G.static_tree=S;G.extra_bits=ta;G.extra_base=257;G.elems=286;G.max_length=15;G.max_code=0;I.dyn_tree=ga;I.static_tree=Y;I.extra_bits=oa;I.extra_base=0;I.elems=30;I.max_length=15;I.max_code=0;ha.dyn_tree=V;ha.static_tree=null;ha.extra_bits=za;ha.extra_base=0;ha.elems=19;ha.max_length=7;for(l=g=ha.max_ [...]
- l;l++)for(L[l]=g,f=0;f<1<<ta[l];f++)T[g++]=l;T[g-1]=l;for(l=g=0;16>l;l++)for(ea[l]=g,f=0;f<1<<oa[l];f++)P[g++]=l;for(g>>=7;30>l;l++)for(ea[l]=g<<7,f=0;f<1<<oa[l]-7;f++)P[256+g++]=l;for(f=0;15>=f;f++)N[f]=0;for(f=0;143>=f;)S[f++].dl=8,N[8]++;for(;255>=f;)S[f++].dl=9,N[9]++;for(;279>=f;)S[f++].dl=7,N[7]++;for(;287>=f;)S[f++].dl=8,N[8]++;Ea(S,287);for(f=0;30>f;f++)Y[f].dl=5,Y[f].fc=Ba(f,5);Ja()}for(f=0;8192>f;f++)x[32768+f]=0;ia=wa[R].max_lazy;ma=wa[R].good_length;$=wa[R].max_chain;w=z=0;Q [...]
- if(0>=Q)F=!0,Q=0;else{for(F=!1;262>Q&&!F;)ua();for(f=t=0;2>f;f++)t=(t<<5^h[f]&255)&8191}b=null;a=k=0;3>=R?(M=2,B=0):(B=2,A=0);e=!1}r=!0;if(0===Q)return e=!0,0}f=Ka(d,c,q);if(f===q)return q;if(e)return f;if(3>=R)for(;0!==Q&&null===b;){qa();0!==s&&32506>=z-s&&(B=ya(s),B>Q&&(B=Q));if(3<=B)if(l=ra(z-K,B-3),Q-=B,B<=ia){B--;do z++,qa();while(0!==--B);z++}else z+=B,B=0,t=h[z]&255,t=(t<<5^h[z+1]&255)&8191;else l=ra(0,h[z]&255),Q--,z++;l&&(Ca(0),w=z);for(;262>Q&&!F;)ua()}else for(;0!==Q&&null=== [...]
- B;D=K;B=2;0!==s&&M<ia&&32506>=z-s&&(B=ya(s),B>Q&&(B=Q),3===B&&4096<z-K&&B--);if(3<=M&&B<=M){l=ra(z-1-D,M-3);Q-=M-1;M-=2;do z++,qa();while(0!==--M);A=0;B=2;z++;l&&(Ca(0),w=z)}else 0!==A?ra(0,h[z-1]&255)&&(Ca(0),w=z):A=1,z++,Q--;for(;262>Q&&!F;)ua()}0===Q&&(0!==A&&ra(0,h[z-1]&255),Ca(1),e=!0);return f+Ka(d,f+c,q-f)};this.deflate=function(a,e){var c,k;sa=a;na=0;"undefined"===String(typeof e)&&(e=6);(c=e)?1>c?c=1:9<c&&(c=9):c=6;R=c;F=r=!1;if(null===d){n=b=p=null;d=[];d.length=f;h=[];h.lengt [...]
- [];q.length=8192;u=[];u.length=32832;x=[];x.length=65536;ba=[];ba.length=573;for(c=0;573>c;c++)ba[c]=new g;ga=[];ga.length=61;for(c=0;61>c;c++)ga[c]=new g;S=[];S.length=288;for(c=0;288>c;c++)S[c]=new g;Y=[];Y.length=30;for(c=0;30>c;c++)Y[c]=new g;V=[];V.length=39;for(c=0;39>c;c++)V[c]=new g;G=new l;I=new l;ha=new l;N=[];N.length=16;O=[];O.length=573;ca=[];ca.length=573;T=[];T.length=256;P=[];P.length=512;L=[];L.length=29;ea=[];ea.length=30;E=[];E.length=1024}var s=Array(1024),B=[],m=[]; [...]
- 0,s.length);0<c;){m.length=c;for(k=0;k<c;k++)m[k]=String.fromCharCode(s[k]);B[B.length]=m.join("");c=La(s,0,s.length)}sa="";return B.join("")}};
++function makeBase64(){function g(a){var c,d=a.length,b=new Uint8Array(new ArrayBuffer(d));for(c=0;c<d;c+=1)b[c]=a.charCodeAt(c)&255;return b}function k(a){var c,d="",b,f=a.length-2;for(b=0;b<f;b+=3)c=a[b]<<16|a[b+1]<<8|a[b+2],d+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c>>>18],d+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c>>>12&63],d+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c>>>6&63],d+="ABCDEFGHIJKLMNOPQRSTUV [...]
++63];b===f+1?(c=a[b]<<4,d+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c>>>6],d+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c&63],d+="=="):b===f&&(c=a[b]<<10|a[b+1]<<2,d+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c>>>12],d+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c>>>6&63],d+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c&63],d+="=");return d}function e(a){a=a.replace( [...]
++"");var c=a.length,d=new Uint8Array(new ArrayBuffer(3*c)),b=a.length%4,f=0,p,e;for(p=0;p<c;p+=4)e=(l[a.charAt(p)]||0)<<18|(l[a.charAt(p+1)]||0)<<12|(l[a.charAt(p+2)]||0)<<6|(l[a.charAt(p+3)]||0),d[f]=e>>16,d[f+1]=e>>8&255,d[f+2]=e&255,f+=3;c=3*c-[0,0,2,1][b];return d.subarray(0,c)}function n(a){var c,d,b=a.length,f=0,p=new Uint8Array(new ArrayBuffer(3*b));for(c=0;c<b;c+=1)d=a[c],128>d?p[f++]=d:(2048>d?p[f++]=192|d>>>6:(p[f++]=224|d>>>12&15,p[f++]=128|d>>>6&63),p[f++]=128|d&63);return p. [...]
++f)}function m(a){var c,d,b,f,p=a.length,l=new Uint8Array(new ArrayBuffer(p)),e=0;for(c=0;c<p;c+=1)d=a[c],128>d?l[e++]=d:(c+=1,b=a[c],224>d?l[e++]=(d&31)<<6|b&63:(c+=1,f=a[c],l[e++]=(d&15)<<12|(b&63)<<6|f&63));return l.subarray(0,e)}function q(a){return k(g(a))}function b(a){return String.fromCharCode.apply(String,e(a))}function h(a){return m(g(a))}function r(a){a=m(a);for(var c="",d=0;d<a.length;)c+=String.fromCharCode.apply(String,a.subarray(d,d+45E3)),d+=45E3;return c}function d(a,c,d [...]
++p,l="";for(p=c;p<d;p+=1)c=a.charCodeAt(p)&255,128>c?l+=String.fromCharCode(c):(p+=1,b=a.charCodeAt(p)&255,224>c?l+=String.fromCharCode((c&31)<<6|b&63):(p+=1,f=a.charCodeAt(p)&255,l+=String.fromCharCode((c&15)<<12|(b&63)<<6|f&63)));return l}function f(a,c){function b(){var l=p+1E5;l>a.length&&(l=a.length);f+=d(a,p,l);p=l;l=p===a.length;c(f,l)&&!l&&runtime.setTimeout(b,0)}var f="",p=0;1E5>a.length?c(d(a,0,a.length),!0):("string"!==typeof a&&(a=a.slice()),b())}function a(a){return n(g(a))} [...]
++n(a))}function p(a){return String.fromCharCode.apply(String,n(g(a)))}var l=function(a){var c={},d,b;d=0;for(b=a.length;d<b;d+=1)c[a.charAt(d)]=d;return c}("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),u,B,w=runtime.getWindow(),y,v;w&&w.btoa?(y=w.btoa,u=function(a){return y(p(a))}):(y=q,u=function(c){return k(a(c))});w&&w.atob?(v=w.atob,B=function(a){a=v(a);return d(a,0,a.length)}):(v=b,B=function(a){return r(e(a))});core.Base64=function(){this.convertByteArrayToBas [...]
++k;this.convertBase64ToByteArray=this.convertBase64ToUTF8Array=e;this.convertUTF16ArrayToByteArray=this.convertUTF16ArrayToUTF8Array=n;this.convertByteArrayToUTF16Array=this.convertUTF8ArrayToUTF16Array=m;this.convertUTF8StringToBase64=q;this.convertBase64ToUTF8String=b;this.convertUTF8StringToUTF16Array=h;this.convertByteArrayToUTF16String=this.convertUTF8ArrayToUTF16String=r;this.convertUTF8StringToUTF16String=f;this.convertUTF16StringToByteArray=this.convertUTF16StringToUTF8Array=a;th [...]
++c;this.convertUTF16StringToUTF8String=p;this.convertUTF16StringToBase64=u;this.convertBase64ToUTF16String=B;this.fromBase64=b;this.toBase64=q;this.atob=v;this.btoa=y;this.utob=p;this.btou=f;this.encode=u;this.encodeURI=function(a){return u(a).replace(/[+\/]/g,function(a){return"+"===a?"-":"_"}).replace(/\\=+$/,"")};this.decode=function(a){return B(a.replace(/[\-_]/g,function(a){return"-"===a?"+":"/"}))};return this};return core.Base64}core.Base64=makeBase64();
+// Input 4
- core.ByteArray=function(g){this.pos=0;this.data=g;this.readUInt32LE=function(){this.pos+=4;var g=this.data,c=this.pos;return g[--c]<<24|g[--c]<<16|g[--c]<<8|g[--c]};this.readUInt16LE=function(){this.pos+=2;var g=this.data,c=this.pos;return g[--c]<<8|g[--c]}};
++core.ByteArray=function(g){this.pos=0;this.data=g;this.readUInt32LE=function(){this.pos+=4;var g=this.data,e=this.pos;return g[--e]<<24|g[--e]<<16|g[--e]<<8|g[--e]};this.readUInt16LE=function(){this.pos+=2;var g=this.data,e=this.pos;return g[--e]<<8|g[--e]}};
+// Input 5
- core.ByteArrayWriter=function(g){function l(b){b>f-m&&(f=Math.max(2*f,m+b),b=new Uint8Array(new ArrayBuffer(f)),b.set(n),n=b)}var c=this,m=0,f=1024,n=new Uint8Array(new ArrayBuffer(f));this.appendByteArrayWriter=function(b){c.appendByteArray(b.getByteArray())};this.appendByteArray=function(b){var c=b.length;l(c);n.set(b,m);m+=c};this.appendArray=function(b){var c=b.length;l(c);n.set(b,m);m+=c};this.appendUInt16LE=function(b){c.appendArray([b&255,b>>8&255])};this.appendUInt32LE=function( [...]
- 255,b>>8&255,b>>16&255,b>>24&255])};this.appendString=function(b){c.appendByteArray(runtime.byteArrayFromString(b,g))};this.getLength=function(){return m};this.getByteArray=function(){var b=new Uint8Array(new ArrayBuffer(m));b.set(n.subarray(0,m));return b}};
++core.ByteArrayWriter=function(g){function k(b){b>m-n&&(m=Math.max(2*m,n+b),b=new Uint8Array(new ArrayBuffer(m)),b.set(q),q=b)}var e=this,n=0,m=1024,q=new Uint8Array(new ArrayBuffer(m));this.appendByteArrayWriter=function(b){e.appendByteArray(b.getByteArray())};this.appendByteArray=function(b){var e=b.length;k(e);q.set(b,n);n+=e};this.appendArray=function(b){var e=b.length;k(e);q.set(b,n);n+=e};this.appendUInt16LE=function(b){e.appendArray([b&255,b>>8&255])};this.appendUInt32LE=function( [...]
++255,b>>8&255,b>>16&255,b>>24&255])};this.appendString=function(b){e.appendByteArray(runtime.byteArrayFromString(b,g))};this.getLength=function(){return n};this.getByteArray=function(){var b=new Uint8Array(new ArrayBuffer(n));b.set(q.subarray(0,n));return b}};
+// Input 6
- core.RawInflate=function(){var g,l,c=null,m,f,n,b,p,r,d,k,a,e,h,q,u,x,v=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535],y=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],w=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,99,99],t=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],s=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13], [...]
- 0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],A=function(){this.list=this.next=null},B=function(){this.n=this.b=this.e=0;this.t=null},M=function(a,e,h,b,d,c){this.BMAX=16;this.N_MAX=288;this.status=0;this.root=null;this.m=0;var k=Array(this.BMAX+1),q,f,g,s,l,p,m,r=Array(this.BMAX+1),n,w,u,t=new B,z=Array(this.BMAX);s=Array(this.N_MAX);var K,x=Array(this.BMAX+1),v,F,M;M=this.root=null;for(l=0;l<k.length;l++)k[l]=0;for(l=0;l<r.length;l++)r[l]=0;for(l=0;l<z.length;l++)z[l]=null;for(l=0;l<s.length [...]
- 0;for(l=0;l<x.length;l++)x[l]=0;q=256<e?a[256]:this.BMAX;n=a;w=0;l=e;do k[n[w]]++,w++;while(0<--l);if(k[0]==e)this.root=null,this.status=this.m=0;else{for(p=1;p<=this.BMAX&&0==k[p];p++);m=p;c<p&&(c=p);for(l=this.BMAX;0!=l&&0==k[l];l--);g=l;c>l&&(c=l);for(v=1<<p;p<l;p++,v<<=1)if(0>(v-=k[p])){this.status=2;this.m=c;return}if(0>(v-=k[l]))this.status=2,this.m=c;else{k[l]+=v;x[1]=p=0;n=k;w=1;for(u=2;0<--l;)x[u++]=p+=n[w++];n=a;l=w=0;do 0!=(p=n[w++])&&(s[x[p]++]=l);while(++l<e);e=x[g];x[0]=l= [...]
- s=-1;K=r[0]=0;u=null;for(F=0;m<=g;m++)for(a=k[m];0<a--;){for(;m>K+r[1+s];){K+=r[1+s];s++;F=(F=g-K)>c?c:F;if((f=1<<(p=m-K))>a+1)for(f-=a+1,u=m;++p<F&&!((f<<=1)<=k[++u]);)f-=k[u];K+p>q&&K<q&&(p=q-K);F=1<<p;r[1+s]=p;u=Array(F);for(f=0;f<F;f++)u[f]=new B;M=null==M?this.root=new A:M.next=new A;M.next=null;M.list=u;z[s]=u;0<s&&(x[s]=l,t.b=r[s],t.e=16+p,t.t=u,p=(l&(1<<K)-1)>>K-r[s],z[s-1][p].e=t.e,z[s-1][p].b=t.b,z[s-1][p].n=t.n,z[s-1][p].t=t.t)}t.b=m-K;w>=e?t.e=99:n[w]<h?(t.e=256>n[w]?16:15,t [...]
- (t.e=d[n[w]-h],t.n=b[n[w++]-h]);f=1<<m-K;for(p=l>>K;p<F;p+=f)u[p].e=t.e,u[p].b=t.b,u[p].n=t.n,u[p].t=t.t;for(p=1<<m-1;0!=(l&p);p>>=1)l^=p;for(l^=p;(l&(1<<K)-1)!=x[s];)K-=r[s],s--}this.m=r[1];this.status=0!=v&&1!=g?1:0}}},z=function(a){for(;b<a;){var e=n,h;h=u.length==x?-1:u[x++];n=e|h<<b;b+=8}},K=function(a){return n&v[a]},F=function(a){n>>=a;b-=a},Q=function(b,c,f){var s,B,m;if(0==f)return 0;for(m=0;;){z(h);B=a.list[K(h)];for(s=B.e;16<s;){if(99==s)return-1;F(B.b);s-=16;z(s);B=B.t[K(s)] [...]
- if(16==s)l&=32767,b[c+m++]=g[l++]=B.n;else{if(15==s)break;z(s);d=B.n+K(s);F(s);z(q);B=e.list[K(q)];for(s=B.e;16<s;){if(99==s)return-1;F(B.b);s-=16;z(s);B=B.t[K(s)];s=B.e}F(B.b);z(s);k=l-B.n-K(s);for(F(s);0<d&&m<f;)d--,k&=32767,l&=32767,b[c+m++]=g[l++]=g[k++]}if(m==f)return f}p=-1;return m},$,ia=function(b,d,c){var k,f,g,l,p,B,m,r=Array(316);for(k=0;k<r.length;k++)r[k]=0;z(5);B=257+K(5);F(5);z(5);m=1+K(5);F(5);z(4);k=4+K(4);F(4);if(286<B||30<m)return-1;for(f=0;f<k;f++)z(3),r[D[f]]=K(3),F [...]
- f;f++)r[D[f]]=0;h=7;f=new M(r,19,19,null,null,h);if(0!=f.status)return-1;a=f.root;h=f.m;l=B+m;for(k=g=0;k<l;)if(z(h),p=a.list[K(h)],f=p.b,F(f),f=p.n,16>f)r[k++]=g=f;else if(16==f){z(2);f=3+K(2);F(2);if(k+f>l)return-1;for(;0<f--;)r[k++]=g}else{17==f?(z(3),f=3+K(3),F(3)):(z(7),f=11+K(7),F(7));if(k+f>l)return-1;for(;0<f--;)r[k++]=0;g=0}h=9;f=new M(r,B,257,y,w,h);0==h&&(f.status=1);if(0!=f.status)return-1;a=f.root;h=f.m;for(k=0;k<m;k++)r[k]=r[k+B];q=6;f=new M(r,m,0,t,s,q);e=f.root;q=f.m;ret [...]
- 257<B||0!=f.status?-1:Q(b,d,c)};this.inflate=function(B,v){null==g&&(g=Array(65536));b=n=l=0;p=-1;r=!1;d=k=0;a=null;u=B;x=0;var A=new Uint8Array(new ArrayBuffer(v));a:{var D,S;for(D=0;D<v&&(!r||-1!=p);){if(0<d){if(0!=p)for(;0<d&&D<v;)d--,k&=32767,l&=32767,A[0+D++]=g[l++]=g[k++];else{for(;0<d&&D<v;)d--,l&=32767,z(8),A[0+D++]=g[l++]=K(8),F(8);0==d&&(p=-1)}if(D==v)break}if(-1==p){if(r)break;z(1);0!=K(1)&&(r=!0);F(1);z(2);p=K(2);F(2);a=null;d=0}switch(p){case 0:S=A;var Y=0+D,V=v-D,G=void 0, [...]
- z(16);G=K(16);F(16);z(16);if(G!=(~n&65535))S=-1;else{F(16);d=G;for(G=0;0<d&&G<V;)d--,l&=32767,z(8),S[Y+G++]=g[l++]=K(8),F(8);0==d&&(p=-1);S=G}break;case 1:if(null!=a)S=Q(A,0+D,v-D);else b:{S=A;Y=0+D;V=v-D;if(null==c){for(var I=void 0,G=Array(288),I=void 0,I=0;144>I;I++)G[I]=8;for(;256>I;I++)G[I]=9;for(;280>I;I++)G[I]=7;for(;288>I;I++)G[I]=8;f=7;I=new M(G,288,257,y,w,f);if(0!=I.status){alert("HufBuild error: "+I.status);S=-1;break b}c=I.root;f=I.m;for(I=0;30>I;I++)G[I]=5;$=5;I=new M(G,30 [...]
- if(1<I.status){c=null;alert("HufBuild error: "+I.status);S=-1;break b}m=I.root;$=I.m}a=c;e=m;h=f;q=$;S=Q(S,Y,V)}break;case 2:S=null!=a?Q(A,0+D,v-D):ia(A,0+D,v-D);break;default:S=-1}if(-1==S)break a;D+=S}}u=null;return A}};
++core.CSSUnits=function(){var g=this,k={"in":1,cm:2.54,mm:25.4,pt:72,pc:12};this.convert=function(e,g,m){return e*k[m]/k[g]};this.convertMeasure=function(e,k){var m,q;e&&k?(m=parseFloat(e),q=e.replace(m.toString(),""),m=g.convert(m,q,k).toString()):m="";return m};this.getUnits=function(e){return e.substr(e.length-2,e.length)}};
+// Input 7
+/*
+
- Copyright (C) 2012 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- core.LoopWatchDog=function(g,l){var c=Date.now(),m=0;this.check=function(){var f;if(g&&(f=Date.now(),f-c>g))throw runtime.log("alert","watchdog timeout"),"timeout!";if(0<l&&(m+=1,m>l))throw runtime.log("alert","watchdog loop overflow"),"loop overflow";}};
++(function(){function g(){var e,g,m,q,b;void 0===k&&(b=(e=runtime.getWindow())&&e.document,k={rangeBCRIgnoresElementBCR:!1,unscaledRangeClientRects:!1},b&&(q=b.createElement("div"),q.style.position="absolute",q.style.left="-99999px",q.style.transform="scale(2)",q.style["-webkit-transform"]="scale(2)",g=b.createElement("div"),q.appendChild(g),b.body.appendChild(q),e=b.createRange(),e.selectNode(g),k.rangeBCRIgnoresElementBCR=0===e.getClientRects().length,g.appendChild(b.createTextNode("Re [...]
++g=g.getBoundingClientRect(),m=e.getBoundingClientRect(),k.unscaledRangeClientRects=2<Math.abs(g.height-m.height),e.detach(),b.body.removeChild(q),e=Object.keys(k).map(function(b){return b+":"+String(k[b])}).join(", "),runtime.log("Detected browser quirks - "+e)));return k}var k;core.DomUtils=function(){function e(a,c){return 0>=a.compareBoundaryPoints(Range.START_TO_START,c)&&0<=a.compareBoundaryPoints(Range.END_TO_END,c)}function k(a,c){return 0>=a.compareBoundaryPoints(Range.END_TO_ST [...]
++a.compareBoundaryPoints(Range.START_TO_END,c)}function m(a,c){var d=null;a.nodeType===Node.TEXT_NODE&&(0===a.length?(a.parentNode.removeChild(a),c.nodeType===Node.TEXT_NODE&&(d=c)):(c.nodeType===Node.TEXT_NODE&&(a.appendData(c.data),c.parentNode.removeChild(c)),d=a));return d}function q(a){for(var c=a.parentNode;a.firstChild;)c.insertBefore(a.firstChild,a);c.removeChild(a);return c}function b(a,c){for(var d=a.parentNode,f=a.firstChild,e;f;)e=f.nextSibling,b(f,c),f=e;c(a)&&(d=q(a));retur [...]
++c){return a===c||Boolean(a.compareDocumentPosition(c)&Node.DOCUMENT_POSITION_CONTAINED_BY)}function r(a,c){for(var d=0,b;a.parentNode!==c;)runtime.assert(null!==a.parentNode,"parent is null"),a=a.parentNode;for(b=c.firstChild;b!==a;)d+=1,b=b.nextSibling;return d}function d(a,c,b){Object.keys(c).forEach(function(f){var e=f.split(":"),h=e[1],m=b(e[0]),e=c[f];"object"===typeof e&&Object.keys(e).length?(f=m?a.getElementsByTagNameNS(m,h)[0]||a.ownerDocument.createElementNS(m,f):a.getElements [...]
++a.ownerDocument.createElement(f),a.appendChild(f),d(f,e,b)):m&&a.setAttributeNS(m,f,String(e))})}var f=null;this.splitBoundaries=function(a){var c=[],d,b;if(a.startContainer.nodeType===Node.TEXT_NODE||a.endContainer.nodeType===Node.TEXT_NODE){if(d=a.endContainer){d=a.endOffset;b=a.endContainer;if(d<b.childNodes.length)for(b=b.childNodes.item(d),d=0;b.firstChild;)b=b.firstChild;else for(;b.lastChild;)b=b.lastChild,d=b.nodeType===Node.TEXT_NODE?b.textContent.length:b.childNodes.length;d={ [...]
++offset:d}}a.setEnd(d.container,d.offset);d=a.endContainer;0!==a.endOffset&&d.nodeType===Node.TEXT_NODE&&(b=d,a.endOffset!==b.length&&(c.push(b.splitText(a.endOffset)),c.push(b)));d=a.startContainer;0!==a.startOffset&&d.nodeType===Node.TEXT_NODE&&(b=d,a.startOffset!==b.length&&(d=b.splitText(a.startOffset),c.push(b),c.push(d),a.setStart(d,0)))}return c};this.containsRange=e;this.rangesIntersect=k;this.getNodesInRange=function(a,c){for(var d=[],b=a.commonAncestorContainer,f,e=a.startConta [...]
++Node.TEXT_NODE?b.parentNode:b,NodeFilter.SHOW_ALL,c,!1),b=e.currentNode=a.startContainer;b;){f=c(b);if(f===NodeFilter.FILTER_ACCEPT)d.push(b);else if(f===NodeFilter.FILTER_REJECT)break;b=b.parentNode}d.reverse();for(b=e.nextNode();b;)d.push(b),b=e.nextNode();return d};this.normalizeTextNodes=function(a){a&&a.nextSibling&&(a=m(a,a.nextSibling));a&&a.previousSibling&&m(a.previousSibling,a)};this.rangeContainsNode=function(a,c){var d=c.ownerDocument.createRange(),b=c.ownerDocument.createRa [...]
++a.startOffset);d.setEnd(a.endContainer,a.endOffset);b.selectNodeContents(c);f=e(d,b);d.detach();b.detach();return f};this.mergeIntoParent=q;this.removeUnwantedNodes=b;this.getElementsByTagNameNS=function(a,c,d){var b=[];a=a.getElementsByTagNameNS(c,d);b.length=d=a.length;for(c=0;c<d;c+=1)b[c]=a.item(c);return b};this.rangeIntersectsNode=function(a,c){var d=c.ownerDocument.createRange(),b;d.selectNodeContents(c);b=k(a,d);d.detach();return b};this.containsNode=function(a,c){return a===c|| [...]
++this.comparePoints=function(a,c,d,b){if(a===d)return b-c;var f=a.compareDocumentPosition(d);2===f?f=-1:4===f?f=1:10===f?(c=r(a,d),f=c<b?1:-1):(b=r(d,a),f=b<c?-1:1);return f};this.adaptRangeDifferenceToZoomLevel=function(a,c){return g().unscaledRangeClientRects?a:a/c};this.getBoundingClientRect=function(a){var c=a.ownerDocument,d=g();if((!1===d.unscaledRangeClientRects||d.rangeBCRIgnoresElementBCR)&&a.nodeType===Node.ELEMENT_NODE)return a.getBoundingClientRect();var b;f?b=f:f=b=c.createR [...]
++c.selectNode(a);return c.getBoundingClientRect()};this.mapKeyValObjOntoNode=function(a,c,d){Object.keys(c).forEach(function(b){var f=b.split(":"),e=f[1],f=d(f[0]),h=c[b];f?(e=a.getElementsByTagNameNS(f,e)[0],e||(e=a.ownerDocument.createElementNS(f,b),a.appendChild(e)),e.textContent=h):runtime.log("Key ignored: "+b)})};this.removeKeyElementsFromNode=function(a,c,d){c.forEach(function(c){var b=c.split(":"),f=b[1];(b=d(b[0]))?(f=a.getElementsByTagNameNS(b,f)[0])?f.parentNode.removeChild(f) [...]
++c+" not found."):runtime.log("Property Name ignored: "+c)})};this.getKeyValRepresentationOfNode=function(a,c){for(var d={},b=a.firstElementChild,f;b;){if(f=c(b.namespaceURI))d[f+":"+b.localName]=b.textContent;b=b.nextElementSibling}return d};this.mapObjOntoNode=d;(function(a){var c,d;d=runtime.getWindow();null!==d&&(c=d.navigator.appVersion.toLowerCase(),d=-1===c.indexOf("chrome")&&(-1!==c.indexOf("applewebkit")||-1!==c.indexOf("safari")),c=c.indexOf("msie"),d||c)&&(a.containsNode=h)})( [...]
+// Input 8
- core.Utils=function(){function g(l,c){c&&Array.isArray(c)?l=(l||[]).concat(c.map(function(c){return g({},c)})):c&&"object"===typeof c?(l=l||{},Object.keys(c).forEach(function(m){l[m]=g(l[m],c[m])})):l=c;return l}this.hashString=function(g){var c=0,m,f;m=0;for(f=g.length;m<f;m+=1)c=(c<<5)-c+g.charCodeAt(m),c|=0;return c};this.mergeObjects=g};
- // Input 9
+/*
+
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- (function(){function g(){var c,g,f,n,b;void 0===l&&(b=(c=runtime.getWindow())&&c.document,l={rangeBCRIgnoresElementBCR:!1,unscaledRangeClientRects:!1},b&&(n=b.createElement("div"),n.style.position="absolute",n.style.left="-99999px",n.style.transform="scale(2)",n.style["-webkit-transform"]="scale(2)",g=b.createElement("div"),n.appendChild(g),b.body.appendChild(n),c=b.createRange(),c.selectNode(g),l.rangeBCRIgnoresElementBCR=0===c.getClientRects().length,g.appendChild(b.createTextNode("Re [...]
- g=g.getBoundingClientRect(),f=c.getBoundingClientRect(),l.unscaledRangeClientRects=2<Math.abs(g.height-f.height),c.detach(),b.body.removeChild(n),c=Object.keys(l).map(function(b){return b+":"+String(l[b])}).join(", "),runtime.log("Detected browser quirks - "+c)));return l}var l;core.DomUtils=function(){function c(a,e){return 0>=a.compareBoundaryPoints(Range.START_TO_START,e)&&0<=a.compareBoundaryPoints(Range.END_TO_END,e)}function l(a,e){return 0>=a.compareBoundaryPoints(Range.END_TO_ST [...]
- a.compareBoundaryPoints(Range.START_TO_END,e)}function f(a,e){var h=null;a.nodeType===Node.TEXT_NODE&&(0===a.length?(a.parentNode.removeChild(a),e.nodeType===Node.TEXT_NODE&&(h=e)):(e.nodeType===Node.TEXT_NODE&&(a.appendData(e.data),e.parentNode.removeChild(e)),h=a));return h}function n(a){for(var e=a.parentNode;a.firstChild;)e.insertBefore(a.firstChild,a);e.removeChild(a);return e}function b(a,e){for(var h=a.parentNode,d=a.firstChild,c;d;)c=d.nextSibling,b(d,e),d=c;e(a)&&(h=n(a));retur [...]
- e){return a===e||Boolean(a.compareDocumentPosition(e)&Node.DOCUMENT_POSITION_CONTAINED_BY)}function r(a,e){for(var h=0,b;a.parentNode!==e;)runtime.assert(null!==a.parentNode,"parent is null"),a=a.parentNode;for(b=e.firstChild;b!==a;)h+=1,b=b.nextSibling;return h}function d(a,e,h){Object.keys(e).forEach(function(b){var c=b.split(":"),k=c[1],f=h(c[0]),c=e[b];"object"===typeof c&&Object.keys(c).length?(b=a.getElementsByTagNameNS(f,k)[0]||a.ownerDocument.createElementNS(f,b),a.appendChild(b [...]
- f&&a.setAttributeNS(f,b,c)})}var k=null;this.splitBoundaries=function(a){var e=[],h,b;if(a.startContainer.nodeType===Node.TEXT_NODE||a.endContainer.nodeType===Node.TEXT_NODE){if(h=a.endContainer){h=a.endOffset;b=a.endContainer;if(h<b.childNodes.length)for(b=b.childNodes.item(h),h=0;b.firstChild;)b=b.firstChild;else for(;b.lastChild;)b=b.lastChild,h=b.nodeType===Node.TEXT_NODE?b.textContent.length:b.childNodes.length;h={container:b,offset:h}}a.setEnd(h.container,h.offset);h=a.endContaine [...]
- h.nodeType===Node.TEXT_NODE&&(b=h,a.endOffset!==b.length&&(e.push(b.splitText(a.endOffset)),e.push(b)));h=a.startContainer;0!==a.startOffset&&h.nodeType===Node.TEXT_NODE&&(b=h,a.startOffset!==b.length&&(h=b.splitText(a.startOffset),e.push(b),e.push(h),a.setStart(h,0)))}return e};this.containsRange=c;this.rangesIntersect=l;this.getNodesInRange=function(a,e){for(var h=[],b=a.commonAncestorContainer,d,c=a.startContainer.ownerDocument.createTreeWalker(b.nodeType===Node.TEXT_NODE?b.parentNod [...]
- e,!1),b=c.currentNode=a.startContainer;b;){d=e(b);if(d===NodeFilter.FILTER_ACCEPT)h.push(b);else if(d===NodeFilter.FILTER_REJECT)break;b=b.parentNode}h.reverse();for(b=c.nextNode();b;)h.push(b),b=c.nextNode();return h};this.normalizeTextNodes=function(a){a&&a.nextSibling&&(a=f(a,a.nextSibling));a&&a.previousSibling&&f(a.previousSibling,a)};this.rangeContainsNode=function(a,e){var h=e.ownerDocument.createRange(),b=e.ownerDocument.createRange(),d;h.setStart(a.startContainer,a.startOffset) [...]
- a.endOffset);b.selectNodeContents(e);d=c(h,b);h.detach();b.detach();return d};this.mergeIntoParent=n;this.removeUnwantedNodes=b;this.getElementsByTagNameNS=function(a,e,b){return Array.prototype.slice.call(a.getElementsByTagNameNS(e,b))};this.rangeIntersectsNode=function(a,e){var b=e.ownerDocument.createRange(),d;b.selectNodeContents(e);d=l(a,b);b.detach();return d};this.containsNode=function(a,e){return a===e||a.contains(e)};this.comparePoints=function(a,e,b,d){if(a===b)return d-e;var [...]
- 2===c?c=-1:4===c?c=1:10===c?(e=r(a,b),c=e<d?1:-1):(d=r(b,a),c=d<e?-1:1);return c};this.adaptRangeDifferenceToZoomLevel=function(a,e){return g().unscaledRangeClientRects?a:a/e};this.getBoundingClientRect=function(a){var e=a.ownerDocument,b=g();if((!1===b.unscaledRangeClientRects||b.rangeBCRIgnoresElementBCR)&&a.nodeType===Node.ELEMENT_NODE)return a.getBoundingClientRect();var d;k?d=k:k=d=e.createRange();e=d;e.selectNode(a);return e.getBoundingClientRect()};this.mapKeyValObjOntoNode=funct [...]
- d.split(":"),k=c[1],c=b(c[0]),f=e[d];c?(k=a.getElementsByTagNameNS(c,k)[0],k||(k=a.ownerDocument.createElementNS(c,d),a.appendChild(k)),k.textContent=f):runtime.log("Key ignored: "+d)})};this.removeKeyElementsFromNode=function(a,e,b){e.forEach(function(e){var d=e.split(":"),c=d[1];(d=b(d[0]))?(c=a.getElementsByTagNameNS(d,c)[0])?c.parentNode.removeChild(c):runtime.log("Element for "+e+" not found."):runtime.log("Property Name ignored: "+e)})};this.getKeyValRepresentationOfNode=function( [...]
- {},d=a.firstElementChild,c;d;){if(c=e(d.namespaceURI))b[c+":"+d.localName]=d.textContent;d=d.nextElementSibling}return b};this.mapObjOntoNode=d;(function(a){var e,b;b=runtime.getWindow();null!==b&&(e=b.navigator.appVersion.toLowerCase(),b=-1===e.indexOf("chrome")&&(-1!==e.indexOf("applewebkit")||-1!==e.indexOf("safari")),e=e.indexOf("msie"),b||e)&&(a.containsNode=p)})(this)};return core.DomUtils})();
- // Input 10
- runtime.loadClass("core.DomUtils");
- core.Cursor=function(g,l){function c(a){a.parentNode&&(p.push(a.previousSibling),p.push(a.nextSibling),a.parentNode.removeChild(a))}function m(a,e,b){if(e.nodeType===Node.TEXT_NODE){runtime.assert(Boolean(e),"putCursorIntoTextNode: invalid container");var d=e.parentNode;runtime.assert(Boolean(d),"putCursorIntoTextNode: container without parent");runtime.assert(0<=b&&b<=e.length,"putCursorIntoTextNode: offset is out of bounds");0===b?d.insertBefore(a,e):(b!==e.length&&e.splitText(b),d.in [...]
- e.nextSibling))}else e.nodeType===Node.ELEMENT_NODE&&e.insertBefore(a,e.childNodes.item(b));p.push(a.previousSibling);p.push(a.nextSibling)}var f=g.createElementNS("urn:webodf:names:cursor","cursor"),n=g.createElementNS("urn:webodf:names:cursor","anchor"),b,p=[],r=null,d,k=new core.DomUtils;this.getNode=function(){return f};this.getAnchorNode=function(){return n.parentNode?n:f};this.getSelectedRange=function(){d?(r.setStartBefore(f),r.collapse(!0)):(r.setStartAfter(b?n:f),r.setEndBefore [...]
- this.setSelectedRange=function(a,e){r&&r!==a&&r.detach();r=a;b=!1!==e;(d=a.collapsed)?(c(n),c(f),m(f,a.startContainer,a.startOffset)):(c(n),c(f),m(b?f:n,a.endContainer,a.endOffset),m(b?n:f,a.startContainer,a.startOffset));p.forEach(k.normalizeTextNodes);p.length=0};this.hasForwardSelection=function(){return b};this.remove=function(){c(f);p.forEach(k.normalizeTextNodes);p.length=0};f.setAttributeNS("urn:webodf:names:cursor","memberId",l);n.setAttributeNS("urn:webodf:names:cursor","member [...]
- // Input 11
++core.EventNotifier=function(g){var k={};this.emit=function(e,g){var m,q;runtime.assert(k.hasOwnProperty(e),'unknown event fired "'+e+'"');q=k[e];for(m=0;m<q.length;m+=1)q[m](g)};this.subscribe=function(e,g){runtime.assert(k.hasOwnProperty(e),'tried to subscribe to unknown event "'+e+'"');k[e].push(g);runtime.log('event "'+e+'" subscribed.')};this.unsubscribe=function(e,g){var m;runtime.assert(k.hasOwnProperty(e),'tried to unsubscribe from unknown event "'+e+'"');m=k[e].indexOf(g);runtim [...]
++m,'tried to unsubscribe unknown callback from event "'+e+'"');-1!==m&&k[e].splice(m,1);runtime.log('event "'+e+'" unsubscribed.')};(function(){var e,n;for(e=0;e<g.length;e+=1)n=g[e],runtime.assert(!k.hasOwnProperty(n),'Duplicated event ids: "'+n+'" registered more than once.'),k[n]=[]})()};
++// Input 9
+/*
+
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2012 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- core.EventNotifier=function(g){var l={};this.emit=function(c,g){var f,n;runtime.assert(l.hasOwnProperty(c),'unknown event fired "'+c+'"');n=l[c];for(f=0;f<n.length;f+=1)n[f](g)};this.subscribe=function(c,g){runtime.assert(l.hasOwnProperty(c),'tried to subscribe to unknown event "'+c+'"');l[c].push(g);runtime.log('event "'+c+'" subscribed.')};this.unsubscribe=function(c,g){var f;runtime.assert(l.hasOwnProperty(c),'tried to unsubscribe from unknown event "'+c+'"');f=l[c].indexOf(g);runtim [...]
- f,'tried to unsubscribe unknown callback from event "'+c+'"');-1!==f&&l[c].splice(f,1);runtime.log('event "'+c+'" unsubscribed.')};(function(){var c,m;for(c=0;c<g.length;c+=1)m=g[c],runtime.assert(!l.hasOwnProperty(m),'Duplicated event ids: "'+m+'" registered more than once.'),l[m]=[]})()};
++core.LoopWatchDog=function(g,k){var e=Date.now(),n=0;this.check=function(){var m;if(g&&(m=Date.now(),m-e>g))throw runtime.log("alert","watchdog timeout"),"timeout!";if(0<k&&(n+=1,n>k))throw runtime.log("alert","watchdog loop overflow"),"loop overflow";}};
++// Input 10
++core.PositionIterator=function(g,k,e,n){function m(){this.acceptNode=function(a){return!a||a.nodeType===c&&0===a.length?u:l}}function q(a){this.acceptNode=function(d){return!d||d.nodeType===c&&0===d.length?u:a.acceptNode(d)}}function b(){var a=d.currentNode,b=a.nodeType;f=b===c?a.length-1:b===p?1:0}function h(){if(null===d.previousSibling()){if(!d.parentNode()||d.currentNode===g)return d.firstChild(),!1;f=0}else b();return!0}var r=this,d,f,a,c=Node.TEXT_NODE,p=Node.ELEMENT_NODE,l=NodeFi [...]
++u=NodeFilter.FILTER_REJECT;this.nextPosition=function(){var a=d.currentNode,b=a.nodeType;if(a===g)return!1;if(0===f&&b===p)null===d.firstChild()&&(f=1);else if(b===c&&f+1<a.length)f+=1;else if(null!==d.nextSibling())f=0;else if(d.parentNode())f=1;else return!1;return!0};this.previousPosition=function(){var a=!0,e=d.currentNode;0===f?a=h():e.nodeType===c?f-=1:null!==d.lastChild()?b():e===g?a=!1:f=0;return a};this.previousNode=h;this.container=function(){var a=d.currentNode,b=a.nodeType;0 [...]
++c&&(a=a.parentNode);return a};this.rightNode=function(){var b=d.currentNode,e=b.nodeType;if(e===c&&f===b.length)for(b=b.nextSibling;b&&a(b)!==l;)b=b.nextSibling;else e===p&&1===f&&(b=null);return b};this.leftNode=function(){var c=d.currentNode;if(0===f)for(c=c.previousSibling;c&&a(c)!==l;)c=c.previousSibling;else if(c.nodeType===p)for(c=c.lastChild;c&&a(c)!==l;)c=c.previousSibling;return c};this.getCurrentNode=function(){return d.currentNode};this.unfilteredDomOffset=function(){if(d.cur [...]
++c)return f;for(var a=0,b=d.currentNode,b=1===f?b.lastChild:b.previousSibling;b;)a+=1,b=b.previousSibling;return a};this.getPreviousSibling=function(){var a=d.currentNode,c=d.previousSibling();d.currentNode=a;return c};this.getNextSibling=function(){var a=d.currentNode,c=d.nextSibling();d.currentNode=a;return c};this.setUnfilteredPosition=function(b,e){var p,h;runtime.assert(null!==b&&void 0!==b,"PositionIterator.setUnfilteredPosition called without container");d.currentNode=b;if(b.nodeT [...]
++e,runtime.assert(e<=b.length,"Error in setPosition: "+e+" > "+b.length),runtime.assert(0<=e,"Error in setPosition: "+e+" < 0"),e===b.length&&(d.nextSibling()?f=0:d.parentNode()?f=1:runtime.assert(!1,"Error in setUnfilteredPosition: position not valid.")),!0;p=a(b);for(h=b.parentNode;h&&h!==g&&p===l;)p=a(h),p!==l&&(d.currentNode=h),h=h.parentNode;e<b.childNodes.length&&p!==NodeFilter.FILTER_REJECT?(d.currentNode=b.childNodes.item(e),p=a(d.currentNode),f=0):f=1;p===NodeFilter.FILTER_REJEC [...]
++l)return r.nextPosition();runtime.assert(a(d.currentNode)===l,"PositionIterater.setUnfilteredPosition call resulted in an non-visible node being set");return!0};this.moveToEnd=function(){d.currentNode=g;f=1};this.moveToEndOfNode=function(a){a.nodeType===c?r.setUnfilteredPosition(a,a.length):(d.currentNode=a,f=1)};this.getNodeFilter=function(){return a};a=(e?new q(e):new m).acceptNode;a.acceptNode=a;k=k||4294967295;runtime.assert(g.nodeType!==Node.TEXT_NODE,"Internet Explorer doesn't all [...]
++d=g.ownerDocument.createTreeWalker(g,k,a,n);f=0;null===d.firstChild()&&(f=1)};
++// Input 11
++core.zip_HuftNode=function(){this.n=this.b=this.e=0;this.t=null};core.zip_HuftList=function(){this.list=this.next=null};
++core.RawInflate=function(){function g(a,c,d,b,f,e){this.BMAX=16;this.N_MAX=288;this.status=0;this.root=null;this.m=0;var p=Array(this.BMAX+1),l,h,m,g,x,k,n,r=Array(this.BMAX+1),v,q,s,F=new core.zip_HuftNode,u=Array(this.BMAX);g=Array(this.N_MAX);var t,z=Array(this.BMAX+1),A,U,P;P=this.root=null;for(x=0;x<p.length;x++)p[x]=0;for(x=0;x<r.length;x++)r[x]=0;for(x=0;x<u.length;x++)u[x]=null;for(x=0;x<g.length;x++)g[x]=0;for(x=0;x<z.length;x++)z[x]=0;l=256<c?a[256]:this.BMAX;v=a;q=0;x=c;do p[ [...]
++while(0<--x);if(p[0]===c)this.root=null,this.status=this.m=0;else{for(k=1;k<=this.BMAX&&0===p[k];k++);n=k;e<k&&(e=k);for(x=this.BMAX;0!==x&&0===p[x];x--);m=x;e>x&&(e=x);for(A=1<<k;k<x;k++,A<<=1)if(A-=p[k],0>A){this.status=2;this.m=e;return}A-=p[x];if(0>A)this.status=2,this.m=e;else{p[x]+=A;z[1]=k=0;v=p;q=1;for(s=2;0<--x;)k+=v[q++],z[s++]=k;v=a;x=q=0;do k=v[q++],0!==k&&(g[z[k]++]=x);while(++x<c);c=z[m];z[0]=x=0;v=g;q=0;g=-1;t=r[0]=0;s=null;U=0;for(n=n-1+1;n<=m;n++)for(a=p[n];0<a--;){for( [...]
++r[1+g];g++;U=m-t;U=U>e?e:U;k=n-t;h=1<<k;if(h>a+1)for(h-=a+1,s=n;++k<U;){h<<=1;if(h<=p[++s])break;h-=p[s]}t+k>l&&t<l&&(k=l-t);U=1<<k;r[1+g]=k;s=Array(U);for(h=0;h<U;h++)s[h]=new core.zip_HuftNode;P=null===P?this.root=new core.zip_HuftList:P.next=new core.zip_HuftList;P.next=null;P.list=s;u[g]=s;0<g&&(z[g]=x,F.b=r[g],F.e=16+k,F.t=s,k=(x&(1<<t)-1)>>t-r[g],u[g-1][k].e=F.e,u[g-1][k].b=F.b,u[g-1][k].n=F.n,u[g-1][k].t=F.t)}F.b=n-t;q>=c?F.e=99:v[q]<d?(F.e=256>v[q]?16:15,F.n=v[q++]):(F.e=f[v[q]- [...]
++d]);h=1<<n-t;for(k=x>>t;k<U;k+=h)s[k].e=F.e,s[k].b=F.b,s[k].n=F.n,s[k].t=F.t;for(k=1<<n-1;0!==(x&k);k>>=1)x^=k;for(x^=k;(x&(1<<t)-1)!==z[g];)t-=r[g],g--}this.m=r[1];this.status=0!==A&&1!==m?1:0}}}function k(d){for(;c<d;){var b=a,f;f=s.length===N?-1:s[N++];a=b|f<<c;c+=8}}function e(c){return a&z[c]}function n(d){a>>=d;c-=d}function m(a,c,d){var f,l,m;if(0===d)return 0;for(m=0;;){k(v);l=w.list[e(v)];for(f=l.e;16<f;){if(99===f)return-1;n(l.b);f-=16;k(f);l=l.t[e(f)];f=l.e}n(l.b);if(16===f)h [...]
++m++]=b[h++]=l.n;else{if(15===f)break;k(f);u=l.n+e(f);n(f);k(t);l=y.list[e(t)];for(f=l.e;16<f;){if(99===f)return-1;n(l.b);f-=16;k(f);l=l.t[e(f)];f=l.e}n(l.b);k(f);B=h-l.n-e(f);for(n(f);0<u&&m<d;)u--,B&=32767,h&=32767,a[c+m++]=b[h++]=b[B++]}if(m===d)return d}p=-1;return m}function q(a,c,d){var b,f,p,l,h,r,q,s=Array(316);for(b=0;b<s.length;b++)s[b]=0;k(5);r=257+e(5);n(5);k(5);q=1+e(5);n(5);k(4);b=4+e(4);n(4);if(286<r||30<q)return-1;for(f=0;f<b;f++)k(3),s[P[f]]=e(3),n(3);for(f=b;19>f;f++)s[ [...]
++7;f=new g(s,19,19,null,null,v);if(0!==f.status)return-1;w=f.root;v=f.m;l=r+q;for(b=p=0;b<l;)if(k(v),h=w.list[e(v)],f=h.b,n(f),f=h.n,16>f)s[b++]=p=f;else if(16===f){k(2);f=3+e(2);n(2);if(b+f>l)return-1;for(;0<f--;)s[b++]=p}else{17===f?(k(3),f=3+e(3),n(3)):(k(7),f=11+e(7),n(7));if(b+f>l)return-1;for(;0<f--;)s[b++]=0;p=0}v=9;f=new g(s,r,257,x,R,v);0===v&&(f.status=1);if(0!==f.status)return-1;w=f.root;v=f.m;for(b=0;b<q;b++)s[b]=s[b+r];t=6;f=new g(s,q,0,F,U,t);y=f.root;t=f.m;return 0===t&&25 [...]
++-1:m(a,c,d)}var b=[],h,r=null,d,f,a,c,p,l,u,B,w,y,v,t,s,N,z=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535],x=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],R=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,99,99],F=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],U=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],P=[16,17,18, [...]
++10,5,11,4,12,3,13,2,14,1,15],A;this.inflate=function(z,P){b.length=65536;c=a=h=0;p=-1;l=!1;u=B=0;w=null;s=z;N=0;var G=new Uint8Array(new ArrayBuffer(P));a:for(var Z=0,O;Z<P&&(!l||-1!==p);){if(0<u){if(0!==p)for(;0<u&&Z<P;)u--,B&=32767,h&=32767,G[0+Z]=b[h]=b[B],Z+=1,h+=1,B+=1;else{for(;0<u&&Z<P;)u-=1,h&=32767,k(8),G[0+Z]=b[h]=e(8),Z+=1,h+=1,n(8);0===u&&(p=-1)}if(Z===P)break}if(-1===p){if(l)break;k(1);0!==e(1)&&(l=!0);n(1);k(2);p=e(2);n(2);w=null;u=0}switch(p){case 0:O=G;var ba=0+Z,K=P-Z,I [...]
++c&7;n(I);k(16);I=e(16);n(16);k(16);if(I!==(~a&65535))O=-1;else{n(16);u=I;for(I=0;0<u&&I<K;)u--,h&=32767,k(8),O[ba+I++]=b[h++]=e(8),n(8);0===u&&(p=-1);O=I}break;case 1:if(null!==w)O=m(G,0+Z,P-Z);else b:{O=G;ba=0+Z;K=P-Z;if(null===r){for(var C=void 0,I=Array(288),C=void 0,C=0;144>C;C++)I[C]=8;for(C=144;256>C;C++)I[C]=9;for(C=256;280>C;C++)I[C]=7;for(C=280;288>C;C++)I[C]=8;f=7;C=new g(I,288,257,x,R,f);if(0!==C.status){alert("HufBuild error: "+C.status);O=-1;break b}r=C.root;f=C.m;for(C=0;3 [...]
++5;A=5;C=new g(I,30,0,F,U,A);if(1<C.status){r=null;alert("HufBuild error: "+C.status);O=-1;break b}d=C.root;A=C.m}w=r;y=d;v=f;t=A;O=m(O,ba,K)}break;case 2:O=null!==w?m(G,0+Z,P-Z):q(G,0+Z,P-Z);break;default:O=-1}if(-1===O)break a;Z+=O}s=new Uint8Array(new ArrayBuffer(0));return G}};
+// Input 12
- core.UnitTest=function(){};core.UnitTest.prototype.setUp=function(){};core.UnitTest.prototype.tearDown=function(){};core.UnitTest.prototype.description=function(){};core.UnitTest.prototype.tests=function(){};core.UnitTest.prototype.asyncTests=function(){};
- core.UnitTest.provideTestAreaDiv=function(){var g=runtime.getWindow().document,l=g.getElementById("testarea");runtime.assert(!l,'Unclean test environment, found a div with id "testarea".');l=g.createElement("div");l.setAttribute("id","testarea");g.body.appendChild(l);return l};
- core.UnitTest.cleanupTestAreaDiv=function(){var g=runtime.getWindow().document,l=g.getElementById("testarea");runtime.assert(!!l&&l.parentNode===g.body,'Test environment broken, found no div with id "testarea" below body.');g.body.removeChild(l)};core.UnitTest.createOdtDocument=function(g,l){var c="<?xml version='1.0' encoding='UTF-8'?>",c=c+"<office:document";Object.keys(l).forEach(function(g){c+=" xmlns:"+g+'="'+l[g]+'"'});c+=">";c+=g;c+="</office:document>";return runtime.parseXML(c)};
- core.UnitTestRunner=function(){function g(c){b+=1;runtime.log("fail",c)}function l(b,d){var c;try{if(b.length!==d.length)return g("array of length "+b.length+" should be "+d.length+" long"),!1;for(c=0;c<b.length;c+=1)if(b[c]!==d[c])return g(b[c]+" should be "+d[c]+" at array index "+c),!1}catch(a){return!1}return!0}function c(b,d,k){var a=b.attributes,e=a.length,h,f,l;for(h=0;h<e;h+=1)if(f=a.item(h),"xmlns"!==f.prefix&&"urn:webodf:names:steps"!==f.namespaceURI){l=d.getAttributeNS(f.name [...]
- if(!d.hasAttributeNS(f.namespaceURI,f.localName))return g("Attribute "+f.localName+" with value "+f.value+" was not present"),!1;if(l!==f.value)return g("Attribute "+f.localName+" was "+l+" should be "+f.value),!1}return k?!0:c(d,b,!0)}function m(b,d){if(b.nodeType!==d.nodeType)return g("Nodetype '"+b.nodeType+"' should be '"+d.nodeType+"'"),!1;if(b.nodeType===Node.TEXT_NODE){if(b.data===d.data)return!0;g("Textnode data '"+b.data+"' should be '"+d.data+"'");return!1}runtime.assert(b.nod [...]
- "Only textnodes and elements supported.");if(b.namespaceURI!==d.namespaceURI)return g("namespace '"+b.namespaceURI+"' should be '"+d.namespaceURI+"'"),!1;if(b.localName!==d.localName)return g("localName '"+b.localName+"' should be '"+d.localName+"'"),!1;if(!c(b,d,!1))return!1;for(var k=b.firstChild,a=d.firstChild;k;){if(!a)return g("Nodetype '"+k.nodeType+"' is unexpected here."),!1;if(!m(k,a))return!1;k=k.nextSibling;a=a.nextSibling}return a?(g("Nodetype '"+a.nodeType+"' is missing her [...]
- function f(b,d){return 0===d?b===d&&1/b===1/d:b===d?!0:"number"===typeof d&&isNaN(d)?"number"===typeof b&&isNaN(b):Object.prototype.toString.call(d)===Object.prototype.toString.call([])?l(b,d):"object"===typeof d&&"object"===typeof b?d.constructor===Element||d.constructor===Node?m(d,b):p(d,b):!1}function n(b,d,c){"string"===typeof d&&"string"===typeof c||runtime.log("WARN: shouldBe() expects string arguments");var a,e;try{e=eval(d)}catch(h){a=h}b=eval(c);a?g(d+" should be "+b+". Threw e [...]
- a):f(e,b)?runtime.log("pass",d+" is "+c):String(typeof e)===String(typeof b)?(c=0===e&&0>1/e?"-0":String(e),g(d+" should be "+b+". Was "+c+".")):g(d+" should be "+b+" (of type "+typeof b+"). Was "+e+" (of type "+typeof e+").")}var b=0,p;p=function(b,d){var c=Object.keys(b),a=Object.keys(d);c.sort();a.sort();return l(c,a)&&Object.keys(b).every(function(a){var h=b[a],c=d[a];return f(h,c)?!0:(g(h+" should be "+c+" for key "+a),!1)})};this.areNodesEqual=m;this.shouldBeNull=function(b,d){n(b [...]
- this.shouldBeNonNull=function(b,d){var c,a;try{a=eval(d)}catch(e){c=e}c?g(d+" should be non-null. Threw exception "+c):null!==a?runtime.log("pass",d+" is non-null."):g(d+" should be non-null. Was "+a)};this.shouldBe=n;this.countFailedTests=function(){return b}};
- core.UnitTester=function(){function g(c,f){return"<span style='color:blue;cursor:pointer' onclick='"+f+"'>"+c+"</span>"}var l=0,c={};this.runTests=function(m,f,n){function b(a){if(0===a.length)c[p]=k,l+=r.countFailedTests(),f();else{e=a[0];var h=Runtime.getFunctionName(e);runtime.log("Running "+h);q=r.countFailedTests();d.setUp();e(function(){d.tearDown();k[h]=q===r.countFailedTests();b(a.slice(1))})}}var p=Runtime.getFunctionName(m)||"",r=new core.UnitTestRunner,d=new m(r),k={},a,e,h,q [...]
- runtime.type();if(c.hasOwnProperty(p))runtime.log("Test "+p+" has already run.");else{u?runtime.log("<span>Running "+g(p,'runSuite("'+p+'");')+": "+d.description()+"</span>"):runtime.log("Running "+p+": "+d.description);h=d.tests();for(a=0;a<h.length;a+=1)e=h[a],m=Runtime.getFunctionName(e)||e.testName,n.length&&-1===n.indexOf(m)||(u?runtime.log("<span>Running "+g(m,'runTest("'+p+'","'+m+'")')+"</span>"):runtime.log("Running "+m),q=r.countFailedTests(),d.setUp(),e(),d.tearDown(),k[m]=q= [...]
- b(d.asyncTests())}};this.countFailedTests=function(){return l};this.results=function(){return c}};
++core.ScheduledTask=function(g,k){function e(){q&&(runtime.clearTimeout(m),q=!1)}function n(){e();g.apply(void 0,b);b=null}var m,q=!1,b=[];this.trigger=function(){b=Array.prototype.slice.call(arguments);q||(q=!0,m=runtime.setTimeout(n,k))};this.triggerImmediate=function(){b=Array.prototype.slice.call(arguments);n()};this.processRequests=function(){q&&n()};this.cancel=e;this.destroy=function(b){e();b()}};
+// Input 13
- core.PositionIterator=function(g,l,c,m){function f(){this.acceptNode=function(a){return!a||a.nodeType===e&&0===a.length?u:q}}function n(a){this.acceptNode=function(b){return!b||b.nodeType===e&&0===b.length?u:a.acceptNode(b)}}function b(){var a=d.currentNode,b=a.nodeType;k=b===e?a.length-1:b===h?1:0}function p(){if(null===d.previousSibling()){if(!d.parentNode()||d.currentNode===g)return d.firstChild(),!1;k=0}else b();return!0}var r=this,d,k,a,e=Node.TEXT_NODE,h=Node.ELEMENT_NODE,q=NodeFi [...]
- u=NodeFilter.FILTER_REJECT;this.nextPosition=function(){var a=d.currentNode,b=a.nodeType;if(a===g)return!1;if(0===k&&b===h)null===d.firstChild()&&(k=1);else if(b===e&&k+1<a.length)k+=1;else if(null!==d.nextSibling())k=0;else if(d.parentNode())k=1;else return!1;return!0};this.previousPosition=function(){var a=!0,h=d.currentNode;0===k?a=p():h.nodeType===e?k-=1:null!==d.lastChild()?b():h===g?a=!1:k=0;return a};this.previousNode=p;this.container=function(){var a=d.currentNode,b=a.nodeType;0 [...]
- e&&(a=a.parentNode);return a};this.rightNode=function(){var b=d.currentNode,c=b.nodeType;if(c===e&&k===b.length)for(b=b.nextSibling;b&&a(b)!==q;)b=b.nextSibling;else c===h&&1===k&&(b=null);return b};this.leftNode=function(){var b=d.currentNode;if(0===k)for(b=b.previousSibling;b&&a(b)!==q;)b=b.previousSibling;else if(b.nodeType===h)for(b=b.lastChild;b&&a(b)!==q;)b=b.previousSibling;return b};this.getCurrentNode=function(){return d.currentNode};this.unfilteredDomOffset=function(){if(d.cur [...]
- e)return k;for(var a=0,b=d.currentNode,b=1===k?b.lastChild:b.previousSibling;b;)a+=1,b=b.previousSibling;return a};this.getPreviousSibling=function(){var a=d.currentNode,b=d.previousSibling();d.currentNode=a;return b};this.getNextSibling=function(){var a=d.currentNode,b=d.nextSibling();d.currentNode=a;return b};this.setUnfilteredPosition=function(b,h){var c,f;runtime.assert(null!==b&&void 0!==b,"PositionIterator.setUnfilteredPosition called without container");d.currentNode=b;if(b.nodeT [...]
- h,runtime.assert(h<=b.length,"Error in setPosition: "+h+" > "+b.length),runtime.assert(0<=h,"Error in setPosition: "+h+" < 0"),h===b.length&&(d.nextSibling()?k=0:d.parentNode()?k=1:runtime.assert(!1,"Error in setUnfilteredPosition: position not valid.")),!0;c=a(b);for(f=b.parentNode;f&&f!==g&&c===q;)c=a(f),c!==q&&(d.currentNode=f),f=f.parentNode;h<b.childNodes.length&&c!==NodeFilter.FILTER_REJECT?(d.currentNode=b.childNodes.item(h),c=a(d.currentNode),k=0):k=1;c===NodeFilter.FILTER_REJEC [...]
- q)return r.nextPosition();runtime.assert(a(d.currentNode)===q,"PositionIterater.setUnfilteredPosition call resulted in an non-visible node being set");return!0};this.moveToEnd=function(){d.currentNode=g;k=1};this.moveToEndOfNode=function(a){a.nodeType===e?r.setUnfilteredPosition(a,a.length):(d.currentNode=a,k=1)};this.getNodeFilter=function(){return a};a=(c?new n(c):new f).acceptNode;a.acceptNode=a;l=l||4294967295;runtime.assert(g.nodeType!==Node.TEXT_NODE,"Internet Explorer doesn't all [...]
- d=g.ownerDocument.createTreeWalker(g,l,a,m);k=0;null===d.firstChild()&&(k=1)};
++core.UnitTest=function(){};core.UnitTest.prototype.setUp=function(){};core.UnitTest.prototype.tearDown=function(){};core.UnitTest.prototype.description=function(){};core.UnitTest.prototype.tests=function(){};core.UnitTest.prototype.asyncTests=function(){};
++core.UnitTest.provideTestAreaDiv=function(){var g=runtime.getWindow().document,k=g.getElementById("testarea");runtime.assert(!k,'Unclean test environment, found a div with id "testarea".');k=g.createElement("div");k.setAttribute("id","testarea");g.body.appendChild(k);return k};
++core.UnitTest.cleanupTestAreaDiv=function(){var g=runtime.getWindow().document,k=g.getElementById("testarea");runtime.assert(!!k&&k.parentNode===g.body,'Test environment broken, found no div with id "testarea" below body.');g.body.removeChild(k)};core.UnitTest.createOdtDocument=function(g,k){var e="<?xml version='1.0' encoding='UTF-8'?>",e=e+"<office:document";Object.keys(k).forEach(function(g){e+=" xmlns:"+g+'="'+k[g]+'"'});e+=">";e+=g;e+="</office:document>";return runtime.parseXML(e)};
++core.UnitTestRunner=function(){function g(e){b+=1;runtime.log("fail",e)}function k(b,d){var f;try{if(b.length!==d.length)return g("array of length "+b.length+" should be "+d.length+" long"),!1;for(f=0;f<b.length;f+=1)if(b[f]!==d[f])return g(b[f]+" should be "+d[f]+" at array index "+f),!1}catch(a){return!1}return!0}function e(b,d,f){var a=b.attributes,c=a.length,p,l,h;for(p=0;p<c;p+=1)if(l=a.item(p),"xmlns"!==l.prefix&&"urn:webodf:names:steps"!==l.namespaceURI){h=d.getAttributeNS(l.name [...]
++if(!d.hasAttributeNS(l.namespaceURI,l.localName))return g("Attribute "+l.localName+" with value "+l.value+" was not present"),!1;if(h!==l.value)return g("Attribute "+l.localName+" was "+h+" should be "+l.value),!1}return f?!0:e(d,b,!0)}function n(b,d){var f,a;f=b.nodeType;a=d.nodeType;if(f!==a)return g("Nodetype '"+f+"' should be '"+a+"'"),!1;if(f===Node.TEXT_NODE){if(b.data===d.data)return!0;g("Textnode data '"+b.data+"' should be '"+d.data+"'");return!1}runtime.assert(f===Node.ELEMENT [...]
++if(b.namespaceURI!==d.namespaceURI)return g("namespace '"+b.namespaceURI+"' should be '"+d.namespaceURI+"'"),!1;if(b.localName!==d.localName)return g("localName '"+b.localName+"' should be '"+d.localName+"'"),!1;if(!e(b,d,!1))return!1;f=b.firstChild;for(a=d.firstChild;f;){if(!a)return g("Nodetype '"+f.nodeType+"' is unexpected here."),!1;if(!n(f,a))return!1;f=f.nextSibling;a=a.nextSibling}return a?(g("Nodetype '"+a.nodeType+"' is missing here."),!1):!0}function m(b,d){return 0===d?b===d [...]
++d:b===d?!0:"number"===typeof d&&isNaN(d)?"number"===typeof b&&isNaN(b):Object.prototype.toString.call(d)===Object.prototype.toString.call([])?k(b,d):"object"===typeof d&&"object"===typeof b?d.constructor===Element||d.constructor===Node?n(d,b):h(d,b):!1}function q(b,d,f){"string"===typeof d&&"string"===typeof f||runtime.log("WARN: shouldBe() expects string arguments");var a,c;try{c=eval(d)}catch(e){a=e}b=eval(f);a?g(d+" should be "+b+". Threw exception "+a):m(c,b)?runtime.log("pass",d+" [...]
++String(typeof b)?(f=0===c&&0>1/c?"-0":String(c),g(d+" should be "+b+". Was "+f+".")):g(d+" should be "+b+" (of type "+typeof b+"). Was "+c+" (of type "+typeof c+").")}var b=0,h;h=function(b,d){var f=Object.keys(b),a=Object.keys(d);f.sort();a.sort();return k(f,a)&&Object.keys(b).every(function(a){var f=b[a],e=d[a];return m(f,e)?!0:(g(f+" should be "+e+" for key "+a),!1)})};this.areNodesEqual=n;this.shouldBeNull=function(b,d){q(b,d,"null")};this.shouldBeNonNull=function(b,d){var f,a;try{a [...]
++c}f?g(d+" should be non-null. Threw exception "+f):null!==a?runtime.log("pass",d+" is non-null."):g(d+" should be non-null. Was "+a)};this.shouldBe=q;this.countFailedTests=function(){return b};this.name=function(b){var d,f,a=[],c=b.length;a.length=c;for(d=0;d<c;d+=1){f=Runtime.getFunctionName(b[d])||"";if(""===f)throw"Found a function without a name.";a[d]={f:b[d],name:f}}return a}};
++core.UnitTester=function(){function g(e,m){return"<span style='color:blue;cursor:pointer' onclick='"+m+"'>"+e+"</span>"}var k=0,e={};this.runTests=function(n,m,q){function b(a){if(0===a.length)e[h]=f,k+=r.countFailedTests(),m();else{c=a[0].f;var p=a[0].name;runtime.log("Running "+p);l=r.countFailedTests();d.setUp();c(function(){d.tearDown();f[p]=l===r.countFailedTests();b(a.slice(1))})}}var h=Runtime.getFunctionName(n)||"",r=new core.UnitTestRunner,d=new n(r),f={},a,c,p,l,u="BrowserRunt [...]
++if(e.hasOwnProperty(h))runtime.log("Test "+h+" has already run.");else{u?runtime.log("<span>Running "+g(h,'runSuite("'+h+'");')+": "+d.description()+"</span>"):runtime.log("Running "+h+": "+d.description);p=d.tests();for(a=0;a<p.length;a+=1)c=p[a].f,n=p[a].name,q.length&&-1===q.indexOf(n)||(u?runtime.log("<span>Running "+g(n,'runTest("'+h+'","'+n+'")')+"</span>"):runtime.log("Running "+n),l=r.countFailedTests(),d.setUp(),c(),d.tearDown(),f[n]=l===r.countFailedTests());b(d.asyncTests())} [...]
++function(){return k};this.results=function(){return e}};
+// Input 14
- runtime.loadClass("core.PositionIterator");core.PositionFilter=function(){};core.PositionFilter.FilterResult={FILTER_ACCEPT:1,FILTER_REJECT:2,FILTER_SKIP:3};core.PositionFilter.prototype.acceptPosition=function(g){};(function(){return core.PositionFilter})();
++core.Utils=function(){function g(k,e){if(e&&Array.isArray(e)){k=k||[];if(!Array.isArray(k))throw"Destination is not an array.";k=k.concat(e.map(function(e){return g(null,e)}))}else if(e&&"object"===typeof e){k=k||{};if("object"!==typeof k)throw"Destination is not an object.";Object.keys(e).forEach(function(n){k[n]=g(k[n],e[n])})}else k=e;return k}this.hashString=function(g){var e=0,n,m;n=0;for(m=g.length;n<m;n+=1)e=(e<<5)-e+g.charCodeAt(n),e|=0;return e};this.mergeObjects=function(k,e){ [...]
++g(k[n],e[n])});return k}};
+// Input 15
- runtime.loadClass("core.PositionFilter");core.PositionFilterChain=function(){var g={},l=core.PositionFilter.FilterResult.FILTER_ACCEPT,c=core.PositionFilter.FilterResult.FILTER_REJECT;this.acceptPosition=function(m){for(var f in g)if(g.hasOwnProperty(f)&&g[f].acceptPosition(m)===c)return c;return l};this.addFilter=function(c,f){g[c]=f};this.removeFilter=function(c){delete g[c]}};
- // Input 16
- core.ScheduledTask=function(g,l){function c(){g();n=!1}function m(){n&&(runtime.clearTimeout(f),n=!1)}var f,n=!1;this.trigger=function(){n||(f=runtime.setTimeout(c,l))};this.triggerImmediate=function(){m();c()};this.processRequests=function(){n&&(m(),c())};this.cancel=m;this.destroy=function(b){m();b()}};
- // Input 17
- core.Async=function(){this.forEach=function(g,l,c){function m(f){b!==n&&(f?(b=n,c(f)):(b+=1,b===n&&c(null)))}var f,n=g.length,b=0;for(f=0;f<n;f+=1)l(g[f],m)};this.destroyAll=function(g,l){function c(m,f){if(f)l(f);else if(m<g.length)g[m](function(f){c(m+1,f)});else l()}c(0,void 0)}};
- // Input 18
+/*
+
+ WebODF
+ Copyright (c) 2010 Jos van den Oever
+ Licensed under the ... License:
+
+ Project home: http://www.webodf.org/
+*/
+runtime.loadClass("core.RawInflate");runtime.loadClass("core.ByteArray");runtime.loadClass("core.ByteArrayWriter");runtime.loadClass("core.Base64");
- core.Zip=function(g,l){function c(a){var b=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,368 [...]
++core.Zip=function(g,k){function e(a){var c=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,368 [...]
+853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,31404270 [...]
+4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,38149189 [...]
+225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400 [...]
+2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,123163630 [...]
- 2932959818,3654703836,1088359270,936918E3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117],e,h,d=a.length,c=0,c=0;e=-1;for(h=0;h<d;h+=1)c=(e^a[h])&255,c=b[c],e=e>>>8^c;return e^-1}function m(a){return new Date((a>>25&127)+1980,(a>>21&15)-1,a>>16&31,a>>11&15,a>>5&63,(a&31)<<1)}function f(a){var b=a.getFullYear();return 1980 [...]
- 25|a.getMonth()+1<<21|a.getDate()<<16|a.getHours()<<11|a.getMinutes()<<5|a.getSeconds()>>1}function n(a,b){var e,h,d,c,k,f,g,l=this;this.load=function(b){if(void 0!==l.data)b(null,l.data);else{var e=k+34+h+d+256;e+g>q&&(e=q-g);runtime.read(a,g,e,function(e,h){if(e||null===h)b(e,h);else a:{var d=h,g=new core.ByteArray(d),q=g.readUInt32LE(),s;if(67324752!==q)b("File entry signature is wrong."+q.toString()+" "+d.length.toString(),null);else{g.pos+=22;q=g.readUInt16LE();s=g.readUInt16LE();g [...]
- if(c){d=d.subarray(g.pos,g.pos+k);if(k!==d.length){b("The amount of compressed bytes read was "+d.length.toString()+" instead of "+k.toString()+" for "+l.filename+" in "+a+".",null);break a}d=x(d,f)}else d=d.subarray(g.pos,g.pos+f);f!==d.length?b("The amount of bytes read was "+d.length.toString()+" instead of "+f.toString()+" for "+l.filename+" in "+a+".",null):(l.data=d,b(null,d))}}})}};this.set=function(a,b,e,d){l.filename=a;l.data=b;l.compressed=e;l.date=d};this.error=null;b&&(e=b.r [...]
- 33639248!==e?this.error="Central directory entry has wrong signature at position "+(b.pos-4).toString()+' for file "'+a+'": '+b.data.length.toString():(b.pos+=6,c=b.readUInt16LE(),this.date=m(b.readUInt32LE()),b.readUInt32LE(),k=b.readUInt32LE(),f=b.readUInt32LE(),h=b.readUInt16LE(),d=b.readUInt16LE(),e=b.readUInt16LE(),b.pos+=8,g=b.readUInt32LE(),this.filename=runtime.byteArrayToString(b.data.subarray(b.pos,b.pos+h),"utf8"),b.pos+=h+d+e))}function b(a,b){if(22!==a.length)b("Central dir [...]
- v);else{var e=new core.ByteArray(a),d;d=e.readUInt32LE();101010256!==d?b("Central directory signature is wrong: "+d.toString(),v):(d=e.readUInt16LE(),0!==d?b("Zip files with non-zero disk numbers are not supported.",v):(d=e.readUInt16LE(),0!==d?b("Zip files with non-zero disk numbers are not supported.",v):(d=e.readUInt16LE(),u=e.readUInt16LE(),d!==u?b("Number of entries is inconsistent.",v):(d=e.readUInt32LE(),e=e.readUInt16LE(),e=q-22-d,runtime.read(g,e,q-e,function(a,e){if(a||null=== [...]
- new core.ByteArray(e),c,k;h=[];for(c=0;c<u;c+=1){k=new n(g,d);if(k.error){b(k.error,v);break a}h[h.length]=k}b(null,v)}})))))}}function p(a,b){var e=null,d,c;for(c=0;c<h.length;c+=1)if(d=h[c],d.filename===a){e=d;break}e?e.data?b(null,e.data):e.load(b):b(a+" not found.",null)}function r(a){var b=new core.ByteArrayWriter("utf8"),e=0;b.appendArray([80,75,3,4,20,0,0,0,0,0]);a.data&&(e=a.data.length);b.appendUInt32LE(f(a.date));b.appendUInt32LE(c(a.data));b.appendUInt32LE(e);b.appendUInt32LE [...]
- b.appendUInt16LE(0);b.appendString(a.filename);a.data&&b.appendByteArray(a.data);return b}function d(a,b){var e=new core.ByteArrayWriter("utf8"),d=0;e.appendArray([80,75,1,2,20,0,20,0,0,0,0,0]);a.data&&(d=a.data.length);e.appendUInt32LE(f(a.date));e.appendUInt32LE(c(a.data));e.appendUInt32LE(d);e.appendUInt32LE(d);e.appendUInt16LE(a.filename.length);e.appendArray([0,0,0,0,0,0,0,0,0,0,0,0]);e.appendUInt32LE(b);e.appendString(a.filename);return e}function k(a,b){if(a===h.length)b(null);el [...]
- void 0!==e.data?k(a+1,b):e.load(function(e){e?b(e):k(a+1,b)})}}function a(a,b){k(0,function(e){if(e)b(e);else{e=new core.ByteArrayWriter("utf8");var c,k,f,g=[0];for(c=0;c<h.length;c+=1)e.appendByteArrayWriter(r(h[c])),g.push(e.getLength());f=e.getLength();for(c=0;c<h.length;c+=1)k=h[c],e.appendByteArrayWriter(d(k,g[c]));c=e.getLength()-f;e.appendArray([80,75,5,6,0,0,0,0]);e.appendUInt16LE(h.length);e.appendUInt16LE(h.length);e.appendUInt32LE(c);e.appendUInt32LE(f);e.appendArray([0,0]);a [...]
- function e(b,e){a(function(a){runtime.writeFile(b,a,e)},e)}var h,q,u,x=(new core.RawInflate).inflate,v=this,y=new core.Base64;this.load=p;this.save=function(a,b,e,d){var c,k;for(c=0;c<h.length;c+=1)if(k=h[c],k.filename===a){k.set(a,b,e,d);return}k=new n(g);k.set(a,b,e,d);h.push(k)};this.remove=function(a){var b,e;for(b=0;b<h.length;b+=1)if(e=h[b],e.filename===a)return h.splice(b,1),!0;return!1};this.write=function(a){e(g,a)};this.writeAs=e;this.createByteArray=a;this.loadContentXmlAsFra [...]
- b){v.loadAsString(a,function(a,e){if(a)return b.rootElementReady(a);b.rootElementReady(null,e,!0)})};this.loadAsString=function(a,b){p(a,function(a,e){if(a||null===e)return b(a,null);var d=runtime.byteArrayToString(e,"utf8");b(null,d)})};this.loadAsDOM=function(a,b){v.loadAsString(a,function(a,e){if(a||null===e)b(a,null);else{var d=(new DOMParser).parseFromString(e,"text/xml");b(null,d)}})};this.loadAsDataURL=function(a,b,e){p(a,function(a,d){if(a||!d)return e(a,null);var h=0,c;b||(b=80 [...]
- d[2]&&71===d[3]?"image/png":255===d[0]&&216===d[1]&&255===d[2]?"image/jpeg":71===d[0]&&73===d[1]&&70===d[2]?"image/gif":"");for(c="data:"+b+";base64,";h<d.length;)c+=y.convertUTF8ArrayToBase64(d.subarray(h,Math.min(h+45E3,d.length))),h+=45E3;e(null,c)})};this.getEntries=function(){return h.slice()};q=-1;null===l?h=[]:runtime.getFileSize(g,function(a){q=a;0>q?l("File '"+g+"' cannot be read.",v):runtime.read(g,q-22,22,function(a,e){a||null===l||null===e?l(a,v):b(e,l)})})};
- // Input 19
- core.CSSUnits=function(){var g=this,l={"in":1,cm:2.54,mm:25.4,pt:72,pc:12};this.convert=function(c,g,f){return c*l[f]/l[g]};this.convertMeasure=function(c,l){var f,n;c&&l?(f=parseFloat(c),n=c.replace(f.toString(),""),f=g.convert(f,n,l).toString()):f="";return f};this.getUnits=function(c){return c.substr(c.length-2,c.length)}};
- // Input 20
- xmldom.LSSerializerFilter=function(){};
- // Input 21
- "function"!==typeof Object.create&&(Object.create=function(g){var l=function(){};l.prototype=g;return new l});
- xmldom.LSSerializer=function(){function g(c){var g=c||{},b=function(b){var a={},e;for(e in b)b.hasOwnProperty(e)&&(a[b[e]]=e);return a}(c),l=[g],m=[b],d=0;this.push=function(){d+=1;g=l[d]=Object.create(g);b=m[d]=Object.create(b)};this.pop=function(){l[d]=void 0;m[d]=void 0;d-=1;g=l[d];b=m[d]};this.getLocalNamespaceDefinitions=function(){return b};this.getQName=function(d){var a=d.namespaceURI,e=0,h;if(!a)return d.localName;if(h=b[a])return h+":"+d.localName;do{h||!d.prefix?(h="ns"+e,e+= [...]
- if(g[h]===a)break;if(!g[h]){g[h]=a;b[a]=h;break}h=null}while(null===h);return h+":"+d.localName}}function l(c){return c.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/'/g,"'").replace(/"/g,""")}function c(f,g){var b="",p=m.filter?m.filter.acceptNode(g):NodeFilter.FILTER_ACCEPT,r;if(p===NodeFilter.FILTER_ACCEPT&&g.nodeType===Node.ELEMENT_NODE){f.push();r=f.getQName(g);var d,k=g.attributes,a,e,h,q="",u;d="<"+r;a=k.length;for(e=0;e<a;e+=1)h=k.item(e),"ht [...]
- h.namespaceURI&&(u=m.filter?m.filter.acceptNode(h):NodeFilter.FILTER_ACCEPT,u===NodeFilter.FILTER_ACCEPT&&(u=f.getQName(h),h="string"===typeof h.value?l(h.value):h.value,q+=" "+(u+'="'+h+'"')));a=f.getLocalNamespaceDefinitions();for(e in a)a.hasOwnProperty(e)&&((k=a[e])?"xmlns"!==k&&(d+=" xmlns:"+a[e]+'="'+e+'"'):d+=' xmlns="'+e+'"');b+=d+(q+">")}if(p===NodeFilter.FILTER_ACCEPT||p===NodeFilter.FILTER_SKIP){for(p=g.firstChild;p;)b+=c(f,p),p=p.nextSibling;g.nodeValue&&(b+=l(g.nodeValue))} [...]
- r+">",f.pop());return b}var m=this;this.filter=null;this.writeToString=function(f,l){if(!f)return"";var b=new g(l);return c(b,f)}};
- // Input 22
- xmldom.RelaxNGParser=function(){function g(b,c){this.message=function(){c&&(b+=1===c.nodeType?" Element ":" Node ",b+=c.nodeName,c.nodeValue&&(b+=" with value '"+c.nodeValue+"'"),b+=".");return b}}function l(b){if(2>=b.e.length)return b;var c={name:b.name,e:b.e.slice(0,2)};return l({name:b.name,e:[c].concat(b.e.slice(2))})}function c(b){b=b.split(":",2);var c="",a;1===b.length?b=["",b[0]]:c=b[0];for(a in p)p[a]===c&&(b[0]=a);return b}function m(b,k){for(var a=0,e,h,f=b.name;b.e&&a<b.e.l [...]
- b.e[a],"ref"===e.name){h=k[e.a.name];if(!h)throw e.a.name+" was not defined.";e=b.e.slice(a+1);b.e=b.e.slice(0,a);b.e=b.e.concat(h.e);b.e=b.e.concat(e)}else a+=1,m(e,k);e=b.e;"choice"!==f||e&&e[1]&&"empty"!==e[1].name||(e&&e[0]&&"empty"!==e[0].name?(e[1]=e[0],e[0]={name:"empty"}):(delete b.e,b.name="empty"));if("group"===f||"interleave"===f)"empty"===e[0].name?"empty"===e[1].name?(delete b.e,b.name="empty"):(f=b.name=e[1].name,b.names=e[1].names,e=b.e=e[1].e):"empty"===e[1].name&&(f=b.n [...]
- b.names=e[0].names,e=b.e=e[0].e);"oneOrMore"===f&&"empty"===e[0].name&&(delete b.e,b.name="empty");if("attribute"===f){h=b.names?b.names.length:0;for(var g,l=[],p=[],a=0;a<h;a+=1)g=c(b.names[a]),p[a]=g[0],l[a]=g[1];b.localnames=l;b.namespaces=p}"interleave"===f&&("interleave"===e[0].name?b.e="interleave"===e[1].name?e[0].e.concat(e[1].e):[e[1]].concat(e[0].e):"interleave"===e[1].name&&(b.e=[e[0]].concat(e[1].e)))}function f(b,c){for(var a=0,e;b.e&&a<b.e.length;)e=b.e[a],"elementref"===e [...]
- e.id||0,b.e[a]=c[e.id]):"element"!==e.name&&f(e,c),a+=1}var n=this,b,p={"http://www.w3.org/XML/1998/namespace":"xml"},r;r=function(b,k,a){var e=[],h,f,g=b.localName,m=[];h=b.attributes;var n=g,y=m,w={},t,s;for(t=0;t<h.length;t+=1)if(s=h.item(t),s.namespaceURI)"http://www.w3.org/2000/xmlns/"===s.namespaceURI&&(p[s.value]=s.localName);else{"name"!==s.localName||"element"!==n&&"attribute"!==n||y.push(s.value);if("name"===s.localName||"combine"===s.localName||"type"===s.localName){var D=s,A [...]
- A=A.replace(/^\s\s*/,"");for(var B=/\s/,M=A.length-1;B.test(A.charAt(M));)M-=1;A=A.slice(0,M+1);D.value=A}w[s.localName]=s.value}h=w;h.combine=h.combine||void 0;b=b.firstChild;n=e;y=m;for(w="";b;){if(b.nodeType===Node.ELEMENT_NODE&&"http://relaxng.org/ns/structure/1.0"===b.namespaceURI){if(t=r(b,k,n))"name"===t.name?y.push(p[t.a.ns]+":"+t.text):"choice"===t.name&&t.names&&t.names.length&&(y=y.concat(t.names),delete t.names),n.push(t)}else b.nodeType===Node.TEXT_NODE&&(w+=b.nodeValue);b= [...]
- w;"value"!==g&&"param"!==g&&(b=/^\s*([\s\S]*\S)?\s*$/.exec(b)[1]);"value"===g&&void 0===h.type&&(h.type="token",h.datatypeLibrary="");"attribute"!==g&&"element"!==g||void 0===h.name||(f=c(h.name),e=[{name:"name",text:f[1],a:{ns:f[0]}}].concat(e),delete h.name);"name"===g||"nsName"===g||"value"===g?void 0===h.ns&&(h.ns=""):delete h.ns;"name"===g&&(f=c(b),h.ns=f[0],b=f[1]);1<e.length&&("define"===g||"oneOrMore"===g||"zeroOrMore"===g||"optional"===g||"list"===g||"mixed"===g)&&(e=[{name:"gr [...]
- e:e}).e}]);2<e.length&&"element"===g&&(e=[e[0]].concat({name:"group",e:l({name:"group",e:e.slice(1)}).e}));1===e.length&&"attribute"===g&&e.push({name:"text",text:b});1!==e.length||"choice"!==g&&"group"!==g&&"interleave"!==g?2<e.length&&("choice"===g||"group"===g||"interleave"===g)&&(e=l({name:g,e:e}).e):(g=e[0].name,m=e[0].names,h=e[0].a,b=e[0].text,e=e[0].e);"mixed"===g&&(g="interleave",e=[e[0],{name:"text"}]);"optional"===g&&(g="choice",e=[e[0],{name:"empty"}]);"zeroOrMore"===g&&(g=" [...]
- [{name:"oneOrMore",e:[e[0]]},{name:"empty"}]);if("define"===g&&h.combine){a:{n=h.combine;y=h.name;w=e;for(t=0;a&&t<a.length;t+=1)if(s=a[t],"define"===s.name&&s.a&&s.a.name===y){s.e=[{name:n,e:s.e.concat(w)}];a=s;break a}a=null}if(a)return}a={name:g};e&&0<e.length&&(a.e=e);for(f in h)if(h.hasOwnProperty(f)){a.a=h;break}void 0!==b&&(a.text=b);m&&0<m.length&&(a.names=m);"element"===g&&(a.id=k.length,k.push(a),a={name:"elementref",id:a.id});return a};this.parseRelaxNGDOM=function(c,k){var a [...]
- c.documentElement,a,void 0),h,l,u={};for(h=0;h<e.e.length;h+=1)l=e.e[h],"define"===l.name?u[l.a.name]=l:"start"===l.name&&(b=l);if(!b)return[new g("No Relax NG start element was found.")];m(b,u);for(h in u)u.hasOwnProperty(h)&&m(u[h],u);for(h=0;h<a.length;h+=1)m(a[h],u);k&&(n.rootPattern=k(b.e[0],a));f(b,a);for(h=0;h<a.length;h+=1)f(a[h],a);n.start=b;n.elements=a;n.nsmap=p;return null}};
- // Input 23
- runtime.loadClass("xmldom.RelaxNGParser");
- xmldom.RelaxNG=function(){function g(a){return function(){var b;return function(){void 0===b&&(b=a());return b}}()}function l(a,b){return function(){var e={},c=0;return function(h){var d=h.hash||h.toString(),k;k=e[d];if(void 0!==k)return k;e[d]=k=b(h);k.hash=a+c.toString();c+=1;return k}}()}function c(a){return function(){var b={};return function(e){var c,h;h=b[e.localName];if(void 0===h)b[e.localName]=h={};else if(c=h[e.namespaceURI],void 0!==c)return c;return h[e.namespaceURI]=c=a(e)} [...]
- b,e){return function(){var c={},h=0;return function(d,k){var f=b&&b(d,k),g,l;if(void 0!==f)return f;f=d.hash||d.toString();g=k.hash||k.toString();l=c[f];if(void 0===l)c[f]=l={};else if(f=l[g],void 0!==f)return f;l[g]=f=e(d,k);f.hash=a+h.toString();h+=1;return f}}()}function f(a,b){"choice"===b.p1.type?f(a,b.p1):a[b.p1.hash]=b.p1;"choice"===b.p2.type?f(a,b.p2):a[b.p2.hash]=b.p2}function n(a,b){return{type:"element",nc:a,nullable:!1,textDeriv:function(){return t},startTagOpenDeriv:functio [...]
- h(b,s):t},attDeriv:function(){return t},startTagCloseDeriv:function(){return this}}}function b(){return{type:"list",nullable:!1,hash:"list",textDeriv:function(){return s}}}function p(a,b,e,c){if(b===t)return t;if(c>=e.length)return b;0===c&&(c=0);for(var h=e.item(c);h.namespaceURI===d;){c+=1;if(c>=e.length)return b;h=e.item(c)}return h=p(a,b.attDeriv(a,e.item(c)),e,c+1)}function r(a,b,e){e.e[0].a?(a.push(e.e[0].text),b.push(e.e[0].a.ns)):r(a,b,e.e[0]);e.e[1].a?(a.push(e.e[1].text),b.pus [...]
- r(a,b,e.e[1])}var d="http://www.w3.org/2000/xmlns/",k,a,e,h,q,u,x,v,y,w,t={type:"notAllowed",nullable:!1,hash:"notAllowed",textDeriv:function(){return t},startTagOpenDeriv:function(){return t},attDeriv:function(){return t},startTagCloseDeriv:function(){return t},endTagDeriv:function(){return t}},s={type:"empty",nullable:!0,hash:"empty",textDeriv:function(){return t},startTagOpenDeriv:function(){return t},attDeriv:function(){return t},startTagCloseDeriv:function(){return s},endTagDeriv:f [...]
- D={type:"text",nullable:!0,hash:"text",textDeriv:function(){return D},startTagOpenDeriv:function(){return t},attDeriv:function(){return t},startTagCloseDeriv:function(){return D},endTagDeriv:function(){return t}},A,B,M;k=m("choice",function(a,b){if(a===t)return b;if(b===t||a===b)return a},function(a,b){var e={},h;f(e,{p1:a,p2:b});b=a=void 0;for(h in e)e.hasOwnProperty(h)&&(void 0===a?a=e[h]:b=void 0===b?e[h]:k(b,e[h]));return function(a,b){return{type:"choice",p1:a,p2:b,nullable:a.nulla [...]
- textDeriv:function(e,c){return k(a.textDeriv(e,c),b.textDeriv(e,c))},startTagOpenDeriv:c(function(e){return k(a.startTagOpenDeriv(e),b.startTagOpenDeriv(e))}),attDeriv:function(e,c){return k(a.attDeriv(e,c),b.attDeriv(e,c))},startTagCloseDeriv:g(function(){return k(a.startTagCloseDeriv(),b.startTagCloseDeriv())}),endTagDeriv:g(function(){return k(a.endTagDeriv(),b.endTagDeriv())})}}(a,b)});a=function(a,b,e){return function(){var c={},h=0;return function(d,k){var f=b&&b(d,k),g,l;if(void [...]
- f=d.hash||d.toString();g=k.hash||k.toString();f<g&&(l=f,f=g,g=l,l=d,d=k,k=l);l=c[f];if(void 0===l)c[f]=l={};else if(f=l[g],void 0!==f)return f;l[g]=f=e(d,k);f.hash=a+h.toString();h+=1;return f}}()}("interleave",function(a,b){if(a===t||b===t)return t;if(a===s)return b;if(b===s)return a},function(b,e){return{type:"interleave",p1:b,p2:e,nullable:b.nullable&&e.nullable,textDeriv:function(c,h){return k(a(b.textDeriv(c,h),e),a(b,e.textDeriv(c,h)))},startTagOpenDeriv:c(function(c){return k(A(f [...]
- e)},b.startTagOpenDeriv(c)),A(function(e){return a(b,e)},e.startTagOpenDeriv(c)))}),attDeriv:function(c,h){return k(a(b.attDeriv(c,h),e),a(b,e.attDeriv(c,h)))},startTagCloseDeriv:g(function(){return a(b.startTagCloseDeriv(),e.startTagCloseDeriv())})}});e=m("group",function(a,b){if(a===t||b===t)return t;if(a===s)return b;if(b===s)return a},function(a,b){return{type:"group",p1:a,p2:b,nullable:a.nullable&&b.nullable,textDeriv:function(c,h){var d=e(a.textDeriv(c,h),b);return a.nullable?k(d, [...]
- h)):d},startTagOpenDeriv:function(c){var h=A(function(a){return e(a,b)},a.startTagOpenDeriv(c));return a.nullable?k(h,b.startTagOpenDeriv(c)):h},attDeriv:function(c,h){return k(e(a.attDeriv(c,h),b),e(a,b.attDeriv(c,h)))},startTagCloseDeriv:g(function(){return e(a.startTagCloseDeriv(),b.startTagCloseDeriv())})}});h=m("after",function(a,b){if(a===t||b===t)return t},function(a,b){return{type:"after",p1:a,p2:b,nullable:!1,textDeriv:function(e,c){return h(a.textDeriv(e,c),b)},startTagOpenDer [...]
- b)},a.startTagOpenDeriv(e))}),attDeriv:function(e,c){return h(a.attDeriv(e,c),b)},startTagCloseDeriv:g(function(){return h(a.startTagCloseDeriv(),b)}),endTagDeriv:g(function(){return a.nullable?b:t})}});q=l("oneormore",function(a){return a===t?t:{type:"oneOrMore",p:a,nullable:a.nullable,textDeriv:function(b,c){return e(a.textDeriv(b,c),k(this,s))},startTagOpenDeriv:function(b){var c=this;return A(function(a){return e(a,k(c,s))},a.startTagOpenDeriv(b))},attDeriv:function(b,c){return e(a. [...]
- c),k(this,s))},startTagCloseDeriv:g(function(){return q(a.startTagCloseDeriv())})}});x=m("attribute",void 0,function(a,b){return{type:"attribute",nullable:!1,nc:a,p:b,attDeriv:function(e,c){return a.contains(c)&&(b.nullable&&/^\s+$/.test(c.nodeValue)||b.textDeriv(e,c.nodeValue).nullable)?s:t},startTagCloseDeriv:function(){return t}}});u=l("value",function(a){return{type:"value",nullable:!1,value:a,textDeriv:function(b,e){return e===a?s:t},attDeriv:function(){return t},startTagCloseDeriv [...]
- y=l("data",function(a){return{type:"data",nullable:!1,dataType:a,textDeriv:function(){return s},attDeriv:function(){return t},startTagCloseDeriv:function(){return this}}});A=function K(a,b){return"after"===b.type?h(b.p1,a(b.p2)):"choice"===b.type?k(K(a,b.p1),K(a,b.p2)):b};B=function(a,b,e){var c=e.currentNode;b=b.startTagOpenDeriv(c);b=p(a,b,c.attributes,0);var h=b=b.startTagCloseDeriv(),c=e.currentNode;b=e.firstChild();for(var d=[],f;b;)b.nodeType===Node.ELEMENT_NODE?d.push(b):b.nodeTy [...]
- /^\s*$/.test(b.nodeValue)||d.push(b.nodeValue),b=e.nextSibling();0===d.length&&(d=[""]);f=h;for(h=0;f!==t&&h<d.length;h+=1)b=d[h],"string"===typeof b?f=/^\s*$/.test(b)?k(f,f.textDeriv(a,b)):f.textDeriv(a,b):(e.currentNode=b,f=B(a,f,e));e.currentNode=c;return b=f.endTagDeriv()};v=function(a){var b,e,c;if("name"===a.name)b=a.text,e=a.a.ns,a={name:b,ns:e,hash:"{"+e+"}"+b,contains:function(a){return a.namespaceURI===e&&a.localName===b}};else if("choice"===a.name){b=[];e=[];r(b,e,a);a="";for [...]
- 1)a+="{"+e[c]+"}"+b[c]+",";a={hash:a,contains:function(a){var c;for(c=0;c<b.length;c+=1)if(b[c]===a.localName&&e[c]===a.namespaceURI)return!0;return!1}}}else a={hash:"anyName",contains:function(){return!0}};return a};w=function F(c,h){var d,f;if("elementref"===c.name){d=c.id||0;c=h[d];if(void 0!==c.name){var g=c;d=h[g.id]={hash:"element"+g.id.toString()};g=n(v(g.e[0]),w(g.e[1],h));for(f in g)g.hasOwnProperty(f)&&(d[f]=g[f]);return d}return c}switch(c.name){case "empty":return s;case "no [...]
- case "text":return D;case "choice":return k(F(c.e[0],h),F(c.e[1],h));case "interleave":d=F(c.e[0],h);for(f=1;f<c.e.length;f+=1)d=a(d,F(c.e[f],h));return d;case "group":return e(F(c.e[0],h),F(c.e[1],h));case "oneOrMore":return q(F(c.e[0],h));case "attribute":return x(v(c.e[0]),F(c.e[1],h));case "value":return u(c.text);case "data":return d=c.a&&c.a.type,void 0===d&&(d=""),y(d);case "list":return b()}throw"No support for "+c.name;};this.makePattern=function(a,b){var e={},c;for(c in b)b.ha [...]
- (e[c]=b[c]);return c=w(a,e)};this.validate=function(a,b){var e;a.currentNode=a.root;e=B(null,M,a);e.nullable?b(null):(runtime.log("Error in Relax NG validation: "+e),b(["Error in Relax NG validation: "+e]))};this.init=function(a){M=a}};
- // Input 24
- runtime.loadClass("xmldom.RelaxNGParser");
- xmldom.RelaxNG2=function(){function g(b,c){this.message=function(){c&&(b+=c.nodeType===Node.ELEMENT_NODE?" Element ":" Node ",b+=c.nodeName,c.nodeValue&&(b+=" with value '"+c.nodeValue+"'"),b+=".");return b}}function l(b,c,g,d){return"empty"===b.name?null:f(b,c,g,d)}function c(b,c){if(2!==b.e.length)throw"Element with wrong # of elements: "+b.e.length;for(var f=c.currentNode,d=f?f.nodeType:0,k=null;d>Node.ELEMENT_NODE;){if(d!==Node.COMMENT_NODE&&(d!==Node.TEXT_NODE||!/^\s+$/.test(c.curr [...]
- d+".")];d=(f=c.nextSibling())?f.nodeType:0}if(!f)return[new g("Missing element "+b.names)];if(b.names&&-1===b.names.indexOf(n[f.namespaceURI]+":"+f.localName))return[new g("Found "+f.nodeName+" instead of "+b.names+".",f)];if(c.firstChild()){for(k=l(b.e[1],c,f);c.nextSibling();)if(d=c.currentNode.nodeType,!(c.currentNode&&c.currentNode.nodeType===Node.TEXT_NODE&&/^\s+$/.test(c.currentNode.nodeValue)||d===Node.COMMENT_NODE))return[new g("Spurious content.",c.currentNode)];if(c.parentNode [...]
- l(b.e[1],c,f);c.nextSibling();return k}var m,f,n;f=function(b,p,m,d){var k=b.name,a=null;if("text"===k)a:{for(var e=(b=p.currentNode)?b.nodeType:0;b!==m&&3!==e;){if(1===e){a=[new g("Element not allowed here.",b)];break a}e=(b=p.nextSibling())?b.nodeType:0}p.nextSibling();a=null}else if("data"===k)a=null;else if("value"===k)d!==b.text&&(a=[new g("Wrong value, should be '"+b.text+"', not '"+d+"'",m)]);else if("list"===k)a=null;else if("attribute"===k)a:{if(2!==b.e.length)throw"Attribute w [...]
- b.e.length;k=b.localnames.length;for(a=0;a<k;a+=1){d=m.getAttributeNS(b.namespaces[a],b.localnames[a]);""!==d||m.hasAttributeNS(b.namespaces[a],b.localnames[a])||(d=void 0);if(void 0!==e&&void 0!==d){a=[new g("Attribute defined too often.",m)];break a}e=d}a=void 0===e?[new g("Attribute not found: "+b.names,m)]:l(b.e[1],p,m,e)}else if("element"===k)a=c(b,p);else if("oneOrMore"===k){d=0;do e=p.currentNode,k=f(b.e[0],p,m),d+=1;while(!k&&e!==p.currentNode);1<d?(p.currentNode=e,a=null):a=k}e [...]
- k){if(2!==b.e.length)throw"Choice with wrong # of options: "+b.e.length;e=p.currentNode;if("empty"===b.e[0].name){if(k=f(b.e[1],p,m,d))p.currentNode=e;a=null}else{if(k=l(b.e[0],p,m,d))p.currentNode=e,k=f(b.e[1],p,m,d);a=k}}else if("group"===k){if(2!==b.e.length)throw"Group with wrong # of members: "+b.e.length;a=f(b.e[0],p,m)||f(b.e[1],p,m)}else if("interleave"===k)a:{e=b.e.length;d=[e];for(var h=e,q,n,x,v;0<h;){q=0;n=p.currentNode;for(a=0;a<e;a+=1)x=p.currentNode,!0!==d[a]&&d[a]!==x&&( [...]
- f(v,p,m))?(p.currentNode=x,void 0===d[a]&&(d[a]=!1)):x===p.currentNode||"oneOrMore"===v.name||"choice"===v.name&&("oneOrMore"===v.e[0].name||"oneOrMore"===v.e[1].name)?(q+=1,d[a]=x):(q+=1,d[a]=!0));if(n===p.currentNode&&q===h){a=null;break a}if(0===q){for(a=0;a<e;a+=1)if(!1===d[a]){a=[new g("Interleave does not match.",m)];break a}a=null;break a}for(a=h=0;a<e;a+=1)!0!==d[a]&&(h+=1)}a=null}else throw k+" not allowed in nonEmptyPattern.";return a};this.validate=function(b,c){b.currentNode [...]
- l(m.e[0],b,b.root);c(f)};this.init=function(b,c){m=b;n=c}};
- // Input 25
- xmldom.XPathIterator=function(){};
- xmldom.XPath=function(){function g(a,b,c){return-1!==a&&(a<b||-1===b)&&(a<c||-1===c)}function l(a){for(var b=[],c=0,d=a.length,f;c<d;){var l=a,m=d,p=b,n="",r=[],s=l.indexOf("[",c),D=l.indexOf("/",c),A=l.indexOf("=",c);g(D,s,A)?(n=l.substring(c,D),c=D+1):g(s,D,A)?(n=l.substring(c,s),c=k(l,s,r)):g(A,D,s)?(n=l.substring(c,A),c=A):(n=l.substring(c,m),c=m);p.push({location:n,predicates:r});if(c<d&&"="===a[c]){f=a.substring(c+1,d);if(2<f.length&&("'"===f[0]||'"'===f[0]))f=f.slice(1,f.length-1 [...]
- parseInt(f,10)}catch(B){}c=d}}return{steps:b,value:f}}function c(){var a,b=!1;this.setNode=function(b){a=b};this.reset=function(){b=!1};this.next=function(){var c=b?null:a;b=!0;return c}}function m(a,b,c){this.reset=function(){a.reset()};this.next=function(){for(var d=a.next();d&&!(d=d.getAttributeNodeNS(b,c));)d=a.next();return d}}function f(a,b){var c=a.next(),d=null;this.reset=function(){a.reset();c=a.next();d=null};this.next=function(){for(;c;){if(d)if(b&&d.firstChild)d=d.firstChild [...]
- d!==c;)d=d.parentNode;d===c?c=a.next():d=d.nextSibling}else{do(d=c.firstChild)||(c=a.next());while(c&&!d)}if(d&&d.nodeType===Node.ELEMENT_NODE)return d}return null}}function n(a,b){this.reset=function(){a.reset()};this.next=function(){for(var c=a.next();c&&!b(c);)c=a.next();return c}}function b(a,b,c){b=b.split(":",2);var d=c(b[0]),f=b[1];return new n(a,function(a){return a.localName===f&&a.namespaceURI===d})}function p(a,b,h){var f=new c,k=d(f,b,h),g=b.value;return void 0===g?new n(a,f [...]
- k.reset();return k.next()}):new n(a,function(a){f.setNode(a);k.reset();return(a=k.next())&&a.nodeValue===g})}function r(a,b,h){var f=a.ownerDocument,k=[],g=null;if(f&&f.evaluate)for(h=f.evaluate(b,a,h,XPathResult.UNORDERED_NODE_ITERATOR_TYPE,null),g=h.iterateNext();null!==g;)g.nodeType===Node.ELEMENT_NODE&&k.push(g),g=h.iterateNext();else{k=new c;k.setNode(a);a=l(b);k=d(k,a,h);a=[];for(h=k.next();h;)a.push(h),h=k.next();k=a}return k}var d,k;k=function(a,b,c){for(var d=b,f=a.length,k=0;d [...]
- a[d]?(k-=1,0>=k&&c.push(l(a.substring(b,d)))):"["===a[d]&&(0>=k&&(b=d+1),k+=1),d+=1;return d};xmldom.XPathIterator.prototype.next=function(){};xmldom.XPathIterator.prototype.reset=function(){};d=function(a,e,c){var d,k,g,l;for(d=0;d<e.steps.length;d+=1)for(g=e.steps[d],k=g.location,""===k?a=new f(a,!1):"@"===k[0]?(l=k.slice(1).split(":",2),a=new m(a,c(l[0]),l[1])):"."!==k&&(a=new f(a,!1),-1!==k.indexOf(":")&&(a=b(a,k,c))),k=0;k<g.predicates.length;k+=1)l=g.predicates[k],a=p(a,l,c);retur [...]
- function(){this.getODFElementsWithXPath=r};return xmldom.XPath}();
- // Input 26
- /*
-
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- gui.AnnotationViewManager=function(g,l,c){function m(a){var b=a.node,c=a.end;a=r.createRange();c&&(a.setStart(b,b.childNodes.length),a.setEnd(c,0),c=d.getTextNodes(a,!1),c.forEach(function(a){var c=r.createElement("span");c.className="annotationHighlight";c.setAttribute("annotation",b.getAttributeNS(odf.Namespaces.officens,"name"));a.parentNode.insertBefore(c,a);c.appendChild(a)}));a.detach()}function f(a){var b=g.getSizer();a?(c.style.display="inline-block",b.style.paddingRight=k.getCo [...]
- (c.style.display="none",b.style.paddingRight=0);g.refreshSize()}function n(){p.sort(function(a,b){return a.node.compareDocumentPosition(b.node)===Node.DOCUMENT_POSITION_FOLLOWING?-1:1})}function b(){var a;for(a=0;a<p.length;a+=1){var b=p[a],d=b.node.parentNode,f=d.nextSibling,k=f.nextSibling,l=d.parentNode,m=0,m=p[p.indexOf(b)-1],n=void 0,b=g.getZoomLevel();d.style.left=(c.getBoundingClientRect().left-l.getBoundingClientRect().left)/b+"px";d.style.width=c.getBoundingClientRect().width/b [...]
- parseFloat(d.style.left)-30+"px";m&&(n=m.node.parentNode.getBoundingClientRect(),20>=(l.getBoundingClientRect().top-n.bottom)/b?d.style.top=Math.abs(l.getBoundingClientRect().top-n.bottom)/b+20+"px":d.style.top="0px");k.style.left=f.getBoundingClientRect().width/b+"px";var f=k.style,l=k.getBoundingClientRect().left/b,m=k.getBoundingClientRect().top/b,n=d.getBoundingClientRect().left/b,r=d.getBoundingClientRect().top/b,t=0,s=0,t=n-l,t=t*t,s=r-m,s=s*s,l=Math.sqrt(t+s);f.width=l+"px";m=Mat [...]
- k.getBoundingClientRect().top)/(b*parseFloat(k.style.width)));k.style.transform="rotate("+m+"rad)";k.style.MozTransform="rotate("+m+"rad)";k.style.WebkitTransform="rotate("+m+"rad)";k.style.msTransform="rotate("+m+"rad)"}}var p=[],r=l.ownerDocument,d=new odf.OdfUtils,k=runtime.getWindow();runtime.assert(Boolean(k),"Expected to be run in an environment which has a global window, like a browser.");this.rerenderAnnotations=b;this.addAnnotation=function(a){f(!0);p.push({node:a.node,end:a.en [...]
- r.createElement("div"),c=r.createElement("div"),d=r.createElement("div"),k=r.createElement("div"),g=r.createElement("div"),l=a.node;e.className="annotationWrapper";l.parentNode.insertBefore(e,l);c.className="annotationNote";c.appendChild(l);g.className="annotationRemoveButton";c.appendChild(g);d.className="annotationConnector horizontal";k.className="annotationConnector angular";e.appendChild(c);e.appendChild(d);e.appendChild(k);a.end&&m(a);b()};this.forgetAnnotations=function(){for(;p. [...]
- p[0],b=p.indexOf(a),c=a.node,d=c.parentNode.parentNode;"div"===d.localName&&(d.parentNode.insertBefore(c,d),d.parentNode.removeChild(d));a=a.node.getAttributeNS(odf.Namespaces.officens,"name");a=r.querySelectorAll('span.annotationHighlight[annotation="'+a+'"]');d=c=void 0;for(c=0;c<a.length;c+=1){for(d=a[c];d.firstChild;)d.parentNode.insertBefore(d.firstChild,d);d.parentNode.removeChild(d)}-1!==b&&p.splice(b,1);0===p.length&&f(!1)}}};
- // Input 27
- /*
-
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- odf.OdfNodeFilter=function(){this.acceptNode=function(g){return"http://www.w3.org/1999/xhtml"===g.namespaceURI?NodeFilter.FILTER_SKIP:g.namespaceURI&&g.namespaceURI.match(/^urn:webodf:/)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}};
- // Input 28
++2932959818,3654703836,1088359270,936918E3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117],b,d,f=a.length,e=0,e=0;b=-1;for(d=0;d<f;d+=1)e=(b^a[d])&255,e=c[e],b=b>>>8^e;return b^-1}function n(a){return new Date((a>>25&127)+1980,(a>>21&15)-1,a>>16&31,a>>11&15,a>>5&63,(a&31)<<1)}function m(a){var c=a.getFullYear();return 1980 [...]
++25|a.getMonth()+1<<21|a.getDate()<<16|a.getHours()<<11|a.getMinutes()<<5|a.getSeconds()>>1}function q(a,c){var b,d,f,e,p,h,m,g=this;this.load=function(c){if(null!==g.data)c(null,g.data);else{var b=p+34+d+f+256;b+m>l&&(b=l-m);runtime.read(a,m,b,function(b,d){if(b||null===d)c(b,d);else a:{var f=d,l=new core.ByteArray(f),m=l.readUInt32LE(),k;if(67324752!==m)c("File entry signature is wrong."+m.toString()+" "+f.length.toString(),null);else{l.pos+=22;m=l.readUInt16LE();k=l.readUInt16LE();l.p [...]
++f.subarray(l.pos,l.pos+p);if(p!==f.length){c("The amount of compressed bytes read was "+f.length.toString()+" instead of "+p.toString()+" for "+g.filename+" in "+a+".",null);break a}f=B(f,h)}else f=f.subarray(l.pos,l.pos+h);h!==f.length?c("The amount of bytes read was "+f.length.toString()+" instead of "+h.toString()+" for "+g.filename+" in "+a+".",null):(g.data=f,c(null,f))}}})}};this.set=function(a,c,b,d){g.filename=a;g.data=c;g.compressed=b;g.date=d};this.error=null;c&&(b=c.readUInt3 [...]
++b?this.error="Central directory entry has wrong signature at position "+(c.pos-4).toString()+' for file "'+a+'": '+c.data.length.toString():(c.pos+=6,e=c.readUInt16LE(),this.date=n(c.readUInt32LE()),c.readUInt32LE(),p=c.readUInt32LE(),h=c.readUInt32LE(),d=c.readUInt16LE(),f=c.readUInt16LE(),b=c.readUInt16LE(),c.pos+=8,m=c.readUInt32LE(),this.filename=runtime.byteArrayToString(c.data.subarray(c.pos,c.pos+d),"utf8"),this.data=null,c.pos+=d+f+b))}function b(a,c){if(22!==a.length)c("Central [...]
++w);else{var b=new core.ByteArray(a),d;d=b.readUInt32LE();101010256!==d?c("Central directory signature is wrong: "+d.toString(),w):(d=b.readUInt16LE(),0!==d?c("Zip files with non-zero disk numbers are not supported.",w):(d=b.readUInt16LE(),0!==d?c("Zip files with non-zero disk numbers are not supported.",w):(d=b.readUInt16LE(),u=b.readUInt16LE(),d!==u?c("Number of entries is inconsistent.",w):(d=b.readUInt32LE(),b=b.readUInt16LE(),b=l-22-d,runtime.read(g,b,l-b,function(a,b){if(a||null=== [...]
++new core.ByteArray(b),f,e;p=[];for(f=0;f<u;f+=1){e=new q(g,d);if(e.error){c(e.error,w);break a}p[p.length]=e}c(null,w)}})))))}}function h(a,c){var b=null,d,f;for(f=0;f<p.length;f+=1)if(d=p[f],d.filename===a){b=d;break}b?b.data?c(null,b.data):b.load(c):c(a+" not found.",null)}function r(a){var c=new core.ByteArrayWriter("utf8"),b=0;c.appendArray([80,75,3,4,20,0,0,0,0,0]);a.data&&(b=a.data.length);c.appendUInt32LE(m(a.date));c.appendUInt32LE(a.data?e(a.data):0);c.appendUInt32LE(b);c.appen [...]
++c.appendUInt16LE(a.filename.length);c.appendUInt16LE(0);c.appendString(a.filename);a.data&&c.appendByteArray(a.data);return c}function d(a,c){var b=new core.ByteArrayWriter("utf8"),d=0;b.appendArray([80,75,1,2,20,0,20,0,0,0,0,0]);a.data&&(d=a.data.length);b.appendUInt32LE(m(a.date));b.appendUInt32LE(a.data?e(a.data):0);b.appendUInt32LE(d);b.appendUInt32LE(d);b.appendUInt16LE(a.filename.length);b.appendArray([0,0,0,0,0,0,0,0,0,0,0,0]);b.appendUInt32LE(c);b.appendString(a.filename);return [...]
++c){if(a===p.length)c(null);else{var b=p[a];null!==b.data?f(a+1,c):b.load(function(b){b?c(b):f(a+1,c)})}}function a(a,c){f(0,function(b){if(b)c(b);else{var f,e,l=new core.ByteArrayWriter("utf8"),h=[0];for(f=0;f<p.length;f+=1)l.appendByteArrayWriter(r(p[f])),h.push(l.getLength());b=l.getLength();for(f=0;f<p.length;f+=1)e=p[f],l.appendByteArrayWriter(d(e,h[f]));f=l.getLength()-b;l.appendArray([80,75,5,6,0,0,0,0]);l.appendUInt16LE(p.length);l.appendUInt16LE(p.length);l.appendUInt32LE(f);l.a [...]
++l.appendArray([0,0]);a(l.getByteArray())}})}function c(c,b){a(function(a){runtime.writeFile(c,a,b)},b)}var p,l,u,B=(new core.RawInflate).inflate,w=this,y=new core.Base64;this.load=h;this.save=function(a,c,b,d){var f,e;for(f=0;f<p.length;f+=1)if(e=p[f],e.filename===a){e.set(a,c,b,d);return}e=new q(g);e.set(a,c,b,d);p.push(e)};this.remove=function(a){var c,b;for(c=0;c<p.length;c+=1)if(b=p[c],b.filename===a)return p.splice(c,1),!0;return!1};this.write=function(a){c(g,a)};this.writeAs=c;thi [...]
++a;this.loadContentXmlAsFragments=function(a,c){w.loadAsString(a,function(a,b){if(a)return c.rootElementReady(a);c.rootElementReady(null,b,!0)})};this.loadAsString=function(a,c){h(a,function(a,b){if(a||null===b)return c(a,null);var d=runtime.byteArrayToString(b,"utf8");c(null,d)})};this.loadAsDOM=function(a,c){w.loadAsString(a,function(a,b){if(a||null===b)c(a,null);else{var d=(new DOMParser).parseFromString(b,"text/xml");c(null,d)}})};this.loadAsDataURL=function(a,c,b){h(a,function(a,d){ [...]
++null);var f=0,e;c||(c=80===d[1]&&78===d[2]&&71===d[3]?"image/png":255===d[0]&&216===d[1]&&255===d[2]?"image/jpeg":71===d[0]&&73===d[1]&&70===d[2]?"image/gif":"");for(e="data:"+c+";base64,";f<d.length;)e+=y.convertUTF8ArrayToBase64(d.subarray(f,Math.min(f+45E3,d.length))),f+=45E3;b(null,e)})};this.getEntries=function(){return p.slice()};l=-1;null===k?p=[]:runtime.getFileSize(g,function(a){l=a;0>l?k("File '"+g+"' cannot be read.",w):runtime.read(g,l-22,22,function(a,c){a||null===k||null== [...]
++b(c,k)})})};
++// Input 16
++gui.Avatar=function(g,k){var e=this,n,m,q;this.setColor=function(b){m.style.borderColor=b};this.setImageUrl=function(b){e.isVisible()?m.src=b:q=b};this.isVisible=function(){return"block"===n.style.display};this.show=function(){q&&(m.src=q,q=void 0);n.style.display="block"};this.hide=function(){n.style.display="none"};this.markAsFocussed=function(b){n.className=b?"active":""};this.destroy=function(b){g.removeChild(n);b()};(function(){var b=g.ownerDocument,e=b.documentElement.namespaceURI [...]
++"div");m=b.createElementNS(e,"img");m.width=64;m.height=64;n.appendChild(m);n.style.width="64px";n.style.height="70px";n.style.position="absolute";n.style.top="-80px";n.style.left="-34px";n.style.display=k?"block":"none";g.appendChild(n)})()};
++// Input 17
++gui.EditInfoHandle=function(g){var k=[],e,n=g.ownerDocument,m=n.documentElement.namespaceURI;this.setEdits=function(g){k=g;var b,h,r,d;e.innerHTML="";for(g=0;g<k.length;g+=1)b=n.createElementNS(m,"div"),b.className="editInfo",h=n.createElementNS(m,"span"),h.className="editInfoColor",h.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",k[g].memberid),r=n.createElementNS(m,"span"),r.className="editInfoAuthor",r.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",k[g [...]
++d=n.createElementNS(m,"span"),d.className="editInfoTime",d.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",k[g].memberid),d.innerHTML=k[g].time,b.appendChild(h),b.appendChild(r),b.appendChild(d),e.appendChild(b)};this.show=function(){e.style.display="block"};this.hide=function(){e.style.display="none"};this.destroy=function(m){g.removeChild(e);m()};e=n.createElementNS(m,"div");e.setAttribute("class","editInfoHandle");e.style.display="none";g.appendChild(e)};
++// Input 18
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- odf.Namespaces=function(){function g(c){return l[c]||null}var l={db:"urn:oasis:names:tc:opendocument:xmlns:database:1.0",dc:"http://purl.org/dc/elements/1.1/",meta:"urn:oasis:names:tc:opendocument:xmlns:meta:1.0",dr3d:"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0",draw:"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",chart:"urn:oasis:names:tc:opendocument:xmlns:chart:1.0",fo:"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",form:"urn:oasis:names:tc:opendocument:xmlns:fo [...]
- office:"urn:oasis:names:tc:opendocument:xmlns:office:1.0",presentation:"urn:oasis:names:tc:opendocument:xmlns:presentation:1.0",style:"urn:oasis:names:tc:opendocument:xmlns:style:1.0",svg:"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0",table:"urn:oasis:names:tc:opendocument:xmlns:table:1.0",text:"urn:oasis:names:tc:opendocument:xmlns:text:1.0",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace"},c;g.lookupNamespaceURI=g;c=function(){};c.forEachPref [...]
- c(f,l[f])};c.resolvePrefix=g;c.lookupPrefix=function(c){var f,g;for(g in l)if(l.hasOwnProperty(g)&&l[g]===c){f=g;break}return f};c.namespaceMap=l;c.dbns="urn:oasis:names:tc:opendocument:xmlns:database:1.0";c.dcns="http://purl.org/dc/elements/1.1/";c.metans="urn:oasis:names:tc:opendocument:xmlns:meta:1.0";c.dr3dns="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0";c.drawns="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0";c.chartns="urn:oasis:names:tc:opendocument:xmlns:chart:1.0";c.fons [...]
- c.formns="urn:oasis:names:tc:opendocument:xmlns:form:1.0";c.numberns="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0";c.officens="urn:oasis:names:tc:opendocument:xmlns:office:1.0";c.presentationns="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0";c.stylens="urn:oasis:names:tc:opendocument:xmlns:style:1.0";c.svgns="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0";c.tablens="urn:oasis:names:tc:opendocument:xmlns:table:1.0";c.textns="urn:oasis:names:tc:opendocument:xml [...]
- c.xlinkns="http://www.w3.org/1999/xlink";c.xmlns="http://www.w3.org/XML/1998/namespace";return c}();
- // Input 29
++gui.KeyboardHandler=function(){function g(e,g){g||(g=k.None);return e+":"+g}var k=gui.KeyboardHandler.Modifier,e=null,n={};this.setDefault=function(g){e=g};this.bind=function(e,k,b){e=g(e,k);runtime.assert(!1===n.hasOwnProperty(e),"tried to overwrite the callback handler of key combo: "+e);n[e]=b};this.unbind=function(e,k){var b=g(e,k);delete n[b]};this.reset=function(){e=null;n={}};this.handleEvent=function(m){var q=m.keyCode,b=k.None;m.metaKey&&(b|=k.Meta);m.ctrlKey&&(b|=k.Ctrl);m.alt [...]
++m.shiftKey&&(b|=k.Shift);q=g(q,b);q=n[q];b=!1;q?b=q():null!==e&&(b=e(m));b&&(m.preventDefault?m.preventDefault():m.returnValue=!1)}};gui.KeyboardHandler.Modifier={None:0,Meta:1,Ctrl:2,Alt:4,CtrlAlt:6,Shift:8,MetaShift:9,CtrlShift:10,AltShift:12};gui.KeyboardHandler.KeyCode={Backspace:8,Tab:9,Clear:12,Enter:13,End:35,Home:36,Left:37,Up:38,Right:39,Down:40,Delete:46,A:65,B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89 [...]
++// Input 19
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("xmldom.XPath");runtime.loadClass("odf.Namespaces");
- odf.StyleInfo=function(){function g(a,b){for(var c=A[a.localName],e=c&&c[a.namespaceURI],d=e?e.length:0,h,c=0;c<d;c+=1)(h=a.getAttributeNS(e[c].ns,e[c].localname))&&a.setAttributeNS(e[c].ns,D[e[c].ns]+e[c].localname,b+h);for(c=a.firstChild;c;)c.nodeType===Node.ELEMENT_NODE&&(e=c,g(e,b)),c=c.nextSibling}function l(a,b){for(var c=A[a.localName],e=c&&c[a.namespaceURI],d=e?e.length:0,h,c=0;c<d;c+=1)if(h=a.getAttributeNS(e[c].ns,e[c].localname))h=h.replace(b,""),a.setAttributeNS(e[c].ns,D[e[ [...]
- h);for(c=a.firstChild;c;)c.nodeType===Node.ELEMENT_NODE&&(e=c,l(e,b)),c=c.nextSibling}function c(a,b){var c=A[a.localName],e=(c=c&&c[a.namespaceURI])?c.length:0,d,h,f;for(f=0;f<e;f+=1)if(d=a.getAttributeNS(c[f].ns,c[f].localname))b=b||{},h=c[f].keyname,h=b[h]=b[h]||{},h[d]=1;return b}function m(a,b){var e,d;c(a,b);for(e=a.firstChild;e;)e.nodeType===Node.ELEMENT_NODE&&(d=e,m(d,b)),e=e.nextSibling}function f(a,b,c){this.key=a;this.name=b;this.family=c;this.requires={}}function n(a,b,c){va [...]
- b,d=c[e];d||(d=c[e]=new f(e,a,b));return d}function b(a,c,e){var d=A[a.localName],h=(d=d&&d[a.namespaceURI])?d.length:0,f=a.getAttributeNS(w,"name"),k=a.getAttributeNS(w,"family"),g;f&&k&&(c=n(f,k,e));if(c)for(f=0;f<h;f+=1)if(k=a.getAttributeNS(d[f].ns,d[f].localname))g=d[f].keyname,k=n(k,g,e),c.requires[k.key]=k;for(f=a.firstChild;f;)f.nodeType===Node.ELEMENT_NODE&&(a=f,b(a,c,e)),f=f.nextSibling;return e}function p(a,b){var c=b[a.family];c||(c=b[a.family]={});c[a.name]=1;Object.keys(a. [...]
- b)})}function r(a,c){var e=b(a,null,{});Object.keys(e).forEach(function(a){a=e[a];var b=c[a.family];b&&b.hasOwnProperty(a.name)&&p(a,c)})}function d(a,b){function c(b){(b=h.getAttributeNS(w,b))&&(a[b]=!0)}var e=["font-name","font-name-asian","font-name-complex"],h;if(b)for(h=b.firstChild;h;)h.nodeType===Node.ELEMENT_NODE&&(e.forEach(c),d(a,h)),h=h.nextSibling}function k(a,b){function c(a){var e=d.getAttributeNS(w,a);e&&b.hasOwnProperty(e)&&d.setAttributeNS(w,"style:"+a,b[e])}var e=["fon [...]
- "font-name-complex"],d;if(a)for(d=a.firstChild;d;)d.nodeType===Node.ELEMENT_NODE&&(e.forEach(c),k(d,b)),d=d.nextSibling}var a=odf.Namespaces.chartns,e=odf.Namespaces.dbns,h=odf.Namespaces.dr3dns,q=odf.Namespaces.drawns,u=odf.Namespaces.formns,x=odf.Namespaces.numberns,v=odf.Namespaces.officens,y=odf.Namespaces.presentationns,w=odf.Namespaces.stylens,t=odf.Namespaces.tablens,s=odf.Namespaces.textns,D={"urn:oasis:names:tc:opendocument:xmlns:chart:1.0":"chart:","urn:oasis:names:tc:opendocu [...]
- "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0":"dr3d:","urn:oasis:names:tc:opendocument:xmlns:drawing:1.0":"draw:","urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0":"fo:","urn:oasis:names:tc:opendocument:xmlns:form:1.0":"form:","urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0":"number:","urn:oasis:names:tc:opendocument:xmlns:office:1.0":"office:","urn:oasis:names:tc:opendocument:xmlns:presentation:1.0":"presentation:","urn:oasis:names:tc:opendocument:xmlns:style:1.0":" [...]
- "urn:oasis:names:tc:opendocument:xmlns:table:1.0":"table:","urn:oasis:names:tc:opendocument:xmlns:text:1.0":"chart:","http://www.w3.org/XML/1998/namespace":"xml:"},a={text:[{ens:w,en:"tab-stop",ans:w,a:"leader-text-style"},{ens:w,en:"drop-cap",ans:w,a:"style-name"},{ens:s,en:"notes-configuration",ans:s,a:"citation-body-style-name"},{ens:s,en:"notes-configuration",ans:s,a:"citation-style-name"},{ens:s,en:"a",ans:s,a:"style-name"},{ens:s,en:"alphabetical-index",ans:s,a:"style-name"},{ens: [...]
- ans:s,a:"style-name"},{ens:s,en:"list-level-style-number",ans:s,a:"style-name"},{ens:s,en:"ruby-text",ans:s,a:"style-name"},{ens:s,en:"span",ans:s,a:"style-name"},{ens:s,en:"a",ans:s,a:"visited-style-name"},{ens:w,en:"text-properties",ans:w,a:"text-line-through-text-style"},{ens:s,en:"alphabetical-index-source",ans:s,a:"main-entry-style-name"},{ens:s,en:"index-entry-bibliography",ans:s,a:"style-name"},{ens:s,en:"index-entry-chapter",ans:s,a:"style-name"},{ens:s,en:"index-entry-link-end" [...]
- {ens:s,en:"index-entry-link-start",ans:s,a:"style-name"},{ens:s,en:"index-entry-page-number",ans:s,a:"style-name"},{ens:s,en:"index-entry-span",ans:s,a:"style-name"},{ens:s,en:"index-entry-tab-stop",ans:s,a:"style-name"},{ens:s,en:"index-entry-text",ans:s,a:"style-name"},{ens:s,en:"index-title-template",ans:s,a:"style-name"},{ens:s,en:"list-level-style-bullet",ans:s,a:"style-name"},{ens:s,en:"outline-level-style",ans:s,a:"style-name"}],paragraph:[{ens:q,en:"caption",ans:q,a:"text-style- [...]
- en:"circle",ans:q,a:"text-style-name"},{ens:q,en:"connector",ans:q,a:"text-style-name"},{ens:q,en:"control",ans:q,a:"text-style-name"},{ens:q,en:"custom-shape",ans:q,a:"text-style-name"},{ens:q,en:"ellipse",ans:q,a:"text-style-name"},{ens:q,en:"frame",ans:q,a:"text-style-name"},{ens:q,en:"line",ans:q,a:"text-style-name"},{ens:q,en:"measure",ans:q,a:"text-style-name"},{ens:q,en:"path",ans:q,a:"text-style-name"},{ens:q,en:"polygon",ans:q,a:"text-style-name"},{ens:q,en:"polyline",ans:q,a:" [...]
- {ens:q,en:"rect",ans:q,a:"text-style-name"},{ens:q,en:"regular-polygon",ans:q,a:"text-style-name"},{ens:v,en:"annotation",ans:q,a:"text-style-name"},{ens:u,en:"column",ans:u,a:"text-style-name"},{ens:w,en:"style",ans:w,a:"next-style-name"},{ens:t,en:"body",ans:t,a:"paragraph-style-name"},{ens:t,en:"even-columns",ans:t,a:"paragraph-style-name"},{ens:t,en:"even-rows",ans:t,a:"paragraph-style-name"},{ens:t,en:"first-column",ans:t,a:"paragraph-style-name"},{ens:t,en:"first-row",ans:t,a:"par [...]
- {ens:t,en:"last-column",ans:t,a:"paragraph-style-name"},{ens:t,en:"last-row",ans:t,a:"paragraph-style-name"},{ens:t,en:"odd-columns",ans:t,a:"paragraph-style-name"},{ens:t,en:"odd-rows",ans:t,a:"paragraph-style-name"},{ens:s,en:"notes-configuration",ans:s,a:"default-style-name"},{ens:s,en:"alphabetical-index-entry-template",ans:s,a:"style-name"},{ens:s,en:"bibliography-entry-template",ans:s,a:"style-name"},{ens:s,en:"h",ans:s,a:"style-name"},{ens:s,en:"illustration-index-entry-template" [...]
- {ens:s,en:"index-source-style",ans:s,a:"style-name"},{ens:s,en:"object-index-entry-template",ans:s,a:"style-name"},{ens:s,en:"p",ans:s,a:"style-name"},{ens:s,en:"table-index-entry-template",ans:s,a:"style-name"},{ens:s,en:"table-of-content-entry-template",ans:s,a:"style-name"},{ens:s,en:"table-index-entry-template",ans:s,a:"style-name"},{ens:s,en:"user-index-entry-template",ans:s,a:"style-name"},{ens:w,en:"page-layout-properties",ans:w,a:"register-truth-ref-style-name"}],chart:[{ens:a,e [...]
- a:"style-name"},{ens:a,en:"chart",ans:a,a:"style-name"},{ens:a,en:"data-label",ans:a,a:"style-name"},{ens:a,en:"data-point",ans:a,a:"style-name"},{ens:a,en:"equation",ans:a,a:"style-name"},{ens:a,en:"error-indicator",ans:a,a:"style-name"},{ens:a,en:"floor",ans:a,a:"style-name"},{ens:a,en:"footer",ans:a,a:"style-name"},{ens:a,en:"grid",ans:a,a:"style-name"},{ens:a,en:"legend",ans:a,a:"style-name"},{ens:a,en:"mean-value",ans:a,a:"style-name"},{ens:a,en:"plot-area",ans:a,a:"style-name"},{e [...]
- ans:a,a:"style-name"},{ens:a,en:"series",ans:a,a:"style-name"},{ens:a,en:"stock-gain-marker",ans:a,a:"style-name"},{ens:a,en:"stock-loss-marker",ans:a,a:"style-name"},{ens:a,en:"stock-range-line",ans:a,a:"style-name"},{ens:a,en:"subtitle",ans:a,a:"style-name"},{ens:a,en:"title",ans:a,a:"style-name"},{ens:a,en:"wall",ans:a,a:"style-name"}],section:[{ens:s,en:"alphabetical-index",ans:s,a:"style-name"},{ens:s,en:"bibliography",ans:s,a:"style-name"},{ens:s,en:"illustration-index",ans:s,a:"s [...]
- {ens:s,en:"index-title",ans:s,a:"style-name"},{ens:s,en:"object-index",ans:s,a:"style-name"},{ens:s,en:"section",ans:s,a:"style-name"},{ens:s,en:"table-of-content",ans:s,a:"style-name"},{ens:s,en:"table-index",ans:s,a:"style-name"},{ens:s,en:"user-index",ans:s,a:"style-name"}],ruby:[{ens:s,en:"ruby",ans:s,a:"style-name"}],table:[{ens:e,en:"query",ans:e,a:"style-name"},{ens:e,en:"table-representation",ans:e,a:"style-name"},{ens:t,en:"background",ans:t,a:"style-name"},{ens:t,en:"table",an [...]
- "table-column":[{ens:e,en:"column",ans:e,a:"style-name"},{ens:t,en:"table-column",ans:t,a:"style-name"}],"table-row":[{ens:e,en:"query",ans:e,a:"default-row-style-name"},{ens:e,en:"table-representation",ans:e,a:"default-row-style-name"},{ens:t,en:"table-row",ans:t,a:"style-name"}],"table-cell":[{ens:e,en:"column",ans:e,a:"default-cell-style-name"},{ens:t,en:"table-column",ans:t,a:"default-cell-style-name"},{ens:t,en:"table-row",ans:t,a:"default-cell-style-name"},{ens:t,en:"body",ans:t,a [...]
- {ens:t,en:"covered-table-cell",ans:t,a:"style-name"},{ens:t,en:"even-columns",ans:t,a:"style-name"},{ens:t,en:"covered-table-cell",ans:t,a:"style-name"},{ens:t,en:"even-columns",ans:t,a:"style-name"},{ens:t,en:"even-rows",ans:t,a:"style-name"},{ens:t,en:"first-column",ans:t,a:"style-name"},{ens:t,en:"first-row",ans:t,a:"style-name"},{ens:t,en:"last-column",ans:t,a:"style-name"},{ens:t,en:"last-row",ans:t,a:"style-name"},{ens:t,en:"odd-columns",ans:t,a:"style-name"},{ens:t,en:"odd-rows", [...]
- {ens:t,en:"table-cell",ans:t,a:"style-name"}],graphic:[{ens:h,en:"cube",ans:q,a:"style-name"},{ens:h,en:"extrude",ans:q,a:"style-name"},{ens:h,en:"rotate",ans:q,a:"style-name"},{ens:h,en:"scene",ans:q,a:"style-name"},{ens:h,en:"sphere",ans:q,a:"style-name"},{ens:q,en:"caption",ans:q,a:"style-name"},{ens:q,en:"circle",ans:q,a:"style-name"},{ens:q,en:"connector",ans:q,a:"style-name"},{ens:q,en:"control",ans:q,a:"style-name"},{ens:q,en:"custom-shape",ans:q,a:"style-name"},{ens:q,en:"ellips [...]
- {ens:q,en:"frame",ans:q,a:"style-name"},{ens:q,en:"g",ans:q,a:"style-name"},{ens:q,en:"line",ans:q,a:"style-name"},{ens:q,en:"measure",ans:q,a:"style-name"},{ens:q,en:"page-thumbnail",ans:q,a:"style-name"},{ens:q,en:"path",ans:q,a:"style-name"},{ens:q,en:"polygon",ans:q,a:"style-name"},{ens:q,en:"polyline",ans:q,a:"style-name"},{ens:q,en:"rect",ans:q,a:"style-name"},{ens:q,en:"regular-polygon",ans:q,a:"style-name"},{ens:v,en:"annotation",ans:q,a:"style-name"}],presentation:[{ens:h,en:"c [...]
- a:"style-name"},{ens:h,en:"extrude",ans:y,a:"style-name"},{ens:h,en:"rotate",ans:y,a:"style-name"},{ens:h,en:"scene",ans:y,a:"style-name"},{ens:h,en:"sphere",ans:y,a:"style-name"},{ens:q,en:"caption",ans:y,a:"style-name"},{ens:q,en:"circle",ans:y,a:"style-name"},{ens:q,en:"connector",ans:y,a:"style-name"},{ens:q,en:"control",ans:y,a:"style-name"},{ens:q,en:"custom-shape",ans:y,a:"style-name"},{ens:q,en:"ellipse",ans:y,a:"style-name"},{ens:q,en:"frame",ans:y,a:"style-name"},{ens:q,en:"g" [...]
- {ens:q,en:"line",ans:y,a:"style-name"},{ens:q,en:"measure",ans:y,a:"style-name"},{ens:q,en:"page-thumbnail",ans:y,a:"style-name"},{ens:q,en:"path",ans:y,a:"style-name"},{ens:q,en:"polygon",ans:y,a:"style-name"},{ens:q,en:"polyline",ans:y,a:"style-name"},{ens:q,en:"rect",ans:y,a:"style-name"},{ens:q,en:"regular-polygon",ans:y,a:"style-name"},{ens:v,en:"annotation",ans:y,a:"style-name"}],"drawing-page":[{ens:q,en:"page",ans:q,a:"style-name"},{ens:y,en:"notes",ans:q,a:"style-name"},{ens:w, [...]
- ans:q,a:"style-name"},{ens:w,en:"master-page",ans:q,a:"style-name"}],"list-style":[{ens:s,en:"list",ans:s,a:"style-name"},{ens:s,en:"numbered-paragraph",ans:s,a:"style-name"},{ens:s,en:"list-item",ans:s,a:"style-override"},{ens:w,en:"style",ans:w,a:"list-style-name"}],data:[{ens:w,en:"style",ans:w,a:"data-style-name"},{ens:w,en:"style",ans:w,a:"percentage-data-style-name"},{ens:y,en:"date-time-decl",ans:w,a:"data-style-name"},{ens:s,en:"creation-date",ans:w,a:"data-style-name"},{ens:s,e [...]
- ans:w,a:"data-style-name"},{ens:s,en:"database-display",ans:w,a:"data-style-name"},{ens:s,en:"date",ans:w,a:"data-style-name"},{ens:s,en:"editing-duration",ans:w,a:"data-style-name"},{ens:s,en:"expression",ans:w,a:"data-style-name"},{ens:s,en:"meta-field",ans:w,a:"data-style-name"},{ens:s,en:"modification-date",ans:w,a:"data-style-name"},{ens:s,en:"modification-time",ans:w,a:"data-style-name"},{ens:s,en:"print-date",ans:w,a:"data-style-name"},{ens:s,en:"print-time",ans:w,a:"data-style-n [...]
- en:"table-formula",ans:w,a:"data-style-name"},{ens:s,en:"time",ans:w,a:"data-style-name"},{ens:s,en:"user-defined",ans:w,a:"data-style-name"},{ens:s,en:"user-field-get",ans:w,a:"data-style-name"},{ens:s,en:"user-field-input",ans:w,a:"data-style-name"},{ens:s,en:"variable-get",ans:w,a:"data-style-name"},{ens:s,en:"variable-input",ans:w,a:"data-style-name"},{ens:s,en:"variable-set",ans:w,a:"data-style-name"}],"page-layout":[{ens:y,en:"notes",ans:w,a:"page-layout-name"},{ens:w,en:"handout- [...]
- a:"page-layout-name"},{ens:w,en:"master-page",ans:w,a:"page-layout-name"}]},A,B=new xmldom.XPath;this.collectUsedFontFaces=d;this.changeFontFaceNames=k;this.UsedStyleList=function(a,b){var c={};this.uses=function(a){var b=a.localName,e=a.getAttributeNS(q,"name")||a.getAttributeNS(w,"name");a="style"===b?a.getAttributeNS(w,"family"):a.namespaceURI===x?"data":b;return(a=c[a])?0<a[e]:!1};m(a,c);b&&r(b,c)};this.hasDerivedStyles=function(a,b,c){var e=b("style"),d=c.getAttributeNS(e,"name");c [...]
- "family");return B.getODFElementsWithXPath(a,"//style:*[@style:parent-style-name='"+d+"'][@style:family='"+c+"']",b).length?!0:!1};this.prefixStyleNames=function(a,b,c){var e;if(a){for(e=a.firstChild;e;){if(e.nodeType===Node.ELEMENT_NODE){var d=e,h=b,f=d.getAttributeNS(q,"name"),k=void 0;f?k=q:(f=d.getAttributeNS(w,"name"))&&(k=w);k&&d.setAttributeNS(k,D[k]+"name",h+f)}e=e.nextSibling}g(a,b);c&&g(c,b)}};this.removePrefixFromStyleNames=function(a,b,c){var e=RegExp("^"+b);if(a){for(b=a.fi [...]
- Node.ELEMENT_NODE){var d=b,h=e,f=d.getAttributeNS(q,"name"),k=void 0;f?k=q:(f=d.getAttributeNS(w,"name"))&&(k=w);k&&(f=f.replace(h,""),d.setAttributeNS(k,D[k]+"name",f))}b=b.nextSibling}l(a,e);c&&l(c,e)}};this.determineStylesForNode=c;A=function(a){var b,c,e,d,h,f={},k;for(b in a)if(a.hasOwnProperty(b))for(d=a[b],e=d.length,c=0;c<e;c+=1)h=d[c],k=f[h.en]=f[h.en]||{},k=k[h.ens]=k[h.ens]||[],k.push({ns:h.ans,localname:h.a,keyname:b});return f}(a)};
- // Input 30
++odf.Namespaces={namespaceMap:{db:"urn:oasis:names:tc:opendocument:xmlns:database:1.0",dc:"http://purl.org/dc/elements/1.1/",dr3d:"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0",draw:"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",chart:"urn:oasis:names:tc:opendocument:xmlns:chart:1.0",fo:"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",form:"urn:oasis:names:tc:opendocument:xmlns:form:1.0",meta:"urn:oasis:names:tc:opendocument:xmlns:meta:1.0",number:"urn:oasis:names:tc: [...]
++office:"urn:oasis:names:tc:opendocument:xmlns:office:1.0",presentation:"urn:oasis:names:tc:opendocument:xmlns:presentation:1.0",style:"urn:oasis:names:tc:opendocument:xmlns:style:1.0",svg:"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0",table:"urn:oasis:names:tc:opendocument:xmlns:table:1.0",text:"urn:oasis:names:tc:opendocument:xmlns:text:1.0",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace"},prefixMap:{},dbns:"urn:oasis:names:tc:opendocument:xm [...]
++dcns:"http://purl.org/dc/elements/1.1/",dr3dns:"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0",drawns:"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",chartns:"urn:oasis:names:tc:opendocument:xmlns:chart:1.0",fons:"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",formns:"urn:oasis:names:tc:opendocument:xmlns:form:1.0",numberns:"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0",officens:"urn:oasis:names:tc:opendocument:xmlns:office:1.0",presentationns:"urn:oasis:names: [...]
++stylens:"urn:oasis:names:tc:opendocument:xmlns:style:1.0",svgns:"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0",tablens:"urn:oasis:names:tc:opendocument:xmlns:table:1.0",textns:"urn:oasis:names:tc:opendocument:xmlns:text:1.0",xlinkns:"http://www.w3.org/1999/xlink",xmlns:"http://www.w3.org/XML/1998/namespace"};(function(){var g=odf.Namespaces.namespaceMap,k=odf.Namespaces.prefixMap,e;for(e in g)g.hasOwnProperty(e)&&(k[g[e]]=e)})();
++odf.Namespaces.forEachPrefix=function(g){var k=odf.Namespaces.namespaceMap,e;for(e in k)k.hasOwnProperty(e)&&g(e,k[e])};odf.Namespaces.lookupNamespaceURI=function(g){var k=null;odf.Namespaces.namespaceMap.hasOwnProperty(g)&&(k=odf.Namespaces.namespaceMap[g]);return k};odf.Namespaces.lookupPrefix=function(g){var k=odf.Namespaces.prefixMap;return k.hasOwnProperty(g)?k[g]:null};odf.Namespaces.lookupNamespaceURI.lookupNamespaceURI=odf.Namespaces.lookupNamespaceURI;
++// Input 20
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+runtime.loadClass("core.DomUtils");runtime.loadClass("odf.Namespaces");
- odf.OdfUtils=function(){function g(a){return"image"===(a&&a.localName)&&a.namespaceURI===s}function l(a){return"frame"===(a&&a.localName)&&a.namespaceURI===s&&"as-char"===a.getAttributeNS(t,"anchor-type")}function c(a){var b=a&&a.localName;return("p"===b||"h"===b)&&a.namespaceURI===t}function m(a){for(;a&&!c(a);)a=a.parentNode;return a}function f(a){return/^[ \t\r\n]+$/.test(a)}function n(a){var b=a&&a.localName;return/^(span|p|h|a|meta)$/.test(b)&&a.namespaceURI===t||"span"===b&&"annot [...]
- a.className?!0:!1}function b(a){var b=a&&a.localName,c;c=!1;b&&(c=a.namespaceURI,c=c===t?"s"===b||"tab"===b||"line-break"===b:l(a));return c}function p(a){var b=a&&a.localName,c=!1;b&&(a=a.namespaceURI,a===t&&(c="s"===b));return c}function r(a){for(;null!==a.firstChild&&n(a);)a=a.firstChild;return a}function d(a){for(;null!==a.lastChild&&n(a);)a=a.lastChild;return a}function k(a){for(;!c(a)&&null===a.previousSibling;)a=a.parentNode;return c(a)?null:d(a.previousSibling)}function a(a){for [...]
- a.nextSibling;)a=a.parentNode;return c(a)?null:r(a.nextSibling)}function e(a){for(var c=!1;a;)if(a.nodeType===Node.TEXT_NODE)if(0===a.length)a=k(a);else return!f(a.data.substr(a.length-1,1));else b(a)?(c=!1===p(a),a=null):a=k(a);return c}function h(c){var e=!1;for(c=c&&r(c);c;){if(c.nodeType===Node.TEXT_NODE&&0<c.length&&!f(c.data)){e=!0;break}if(b(c)){e=!0;break}c=a(c)}return e}function q(b,c){return f(b.data.substr(c))?!h(a(b)):!1}function u(a,c){var d=a.data,h;if(!f(d[c])||b(a.parent [...]
- 0<c?f(d[c-1])||(h=!0):e(k(a))&&(h=!0);return!0===h?q(a,c)?!1:!0:!1}function x(a){return(a=/(-?[0-9]*[0-9][0-9]*(\.[0-9]*)?|0+\.[0-9]*[1-9][0-9]*|\.[0-9]*[1-9][0-9]*)((cm)|(mm)|(in)|(pt)|(pc)|(px)|(%))/.exec(a))?{value:parseFloat(a[1]),unit:a[3]}:null}function v(a){return(a=x(a))&&(0>a.value||"%"===a.unit)?null:a}function y(a){return(a=x(a))&&"%"!==a.unit?null:a}function w(a){switch(a.namespaceURI){case odf.Namespaces.drawns:case odf.Namespaces.svgns:case odf.Namespaces.dr3dns:return!1;c [...]
- case odf.Namespaces.officens:switch(a.localName){case "annotation":case "binary-data":case "event-listeners":return!1}break;default:switch(a.localName){case "editinfo":return!1}}return!0}var t=odf.Namespaces.textns,s=odf.Namespaces.drawns,D=/^\s*$/,A=new core.DomUtils;this.isImage=g;this.isCharacterFrame=l;this.isTextSpan=function(a){return"span"===(a&&a.localName)&&a.namespaceURI===t};this.isParagraph=c;this.getParagraphElement=m;this.isWithinTrackedChanges=function(a,b){for(;a&&a!==b; [...]
- t&&"tracked-changes"===a.localName)return!0;a=a.parentNode}return!1};this.isListItem=function(a){return"list-item"===(a&&a.localName)&&a.namespaceURI===t};this.isLineBreak=function(a){return"line-break"===(a&&a.localName)&&a.namespaceURI===t};this.isODFWhitespace=f;this.isGroupingElement=n;this.isCharacterElement=b;this.isSpaceElement=p;this.firstChild=r;this.lastChild=d;this.previousNode=k;this.nextNode=a;this.scanLeftForNonSpace=e;this.lookLeftForCharacter=function(a){var c;c=0;a.node [...]
- 0<a.length?(c=a.data,c=f(c.substr(c.length-1,1))?1===c.length?e(k(a))?2:0:f(c.substr(c.length-2,1))?0:2:1):b(a)&&(c=1);return c};this.lookRightForCharacter=function(a){var c=!1;a&&a.nodeType===Node.TEXT_NODE&&0<a.length?c=!f(a.data.substr(0,1)):b(a)&&(c=!0);return c};this.scanLeftForAnyCharacter=function(a){var c=!1;for(a=a&&d(a);a;){if(a.nodeType===Node.TEXT_NODE&&0<a.length&&!f(a.data)){c=!0;break}if(b(a)){c=!0;break}a=k(a)}return c};this.scanRightForAnyCharacter=h;this.isTrailingWhit [...]
- u;this.isDowngradableSpaceElement=function(b){return b.namespaceURI===t&&"s"===b.localName?e(k(b))&&h(a(b)):!1};this.getFirstNonWhitespaceChild=function(a){for(a=a&&a.firstChild;a&&a.nodeType===Node.TEXT_NODE&&D.test(a.nodeValue);)a=a.nextSibling;return a};this.parseLength=x;this.parseNonNegativeLength=v;this.parseFoFontSize=function(a){var b;b=(b=x(a))&&(0>=b.value||"%"===b.unit)?null:b;return b||y(a)};this.parseFoLineHeight=function(a){return v(a)||y(a)};this.getImpactedParagraphs=fun [...]
- a.commonAncestorContainer,e=[];for(b.nodeType===Node.ELEMENT_NODE&&(e=A.getElementsByTagNameNS(b,t,"p").concat(A.getElementsByTagNameNS(b,t,"h")));b&&!c(b);)b=b.parentNode;b&&e.push(b);return e.filter(function(b){return A.rangeIntersectsNode(a,b)})};this.getTextNodes=function(a,b){var c=a.startContainer.ownerDocument.createRange(),e;e=A.getNodesInRange(a,function(e){c.selectNodeContents(e);if(e.nodeType===Node.TEXT_NODE){if(b&&A.rangesIntersect(a,c)||A.containsRange(a,c))return Boolean( [...]
- u(e,0)))?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT}else if(A.rangesIntersect(a,c)&&w(e))return NodeFilter.FILTER_SKIP;return NodeFilter.FILTER_REJECT});c.detach();return e};this.getTextElements=function(a,c,e){var d=a.startContainer.ownerDocument.createRange(),h;h=A.getNodesInRange(a,function(h){d.selectNodeContents(h);if(b(h.parentNode))return NodeFilter.FILTER_REJECT;if(h.nodeType===Node.TEXT_NODE){if(c&&A.rangesIntersect(a,d)||A.containsRange(a,d))if(e||Boolean(m(h)&&(!f(h.te [...]
- u(h,0))))return NodeFilter.FILTER_ACCEPT}else if(b(h)){if(c&&A.rangesIntersect(a,d)||A.containsRange(a,d))return NodeFilter.FILTER_ACCEPT}else if(w(h)||n(h))return NodeFilter.FILTER_SKIP;return NodeFilter.FILTER_REJECT});d.detach();return h};this.getParagraphElements=function(a){var b=a.startContainer.ownerDocument.createRange(),e;e=A.getNodesInRange(a,function(e){b.selectNodeContents(e);if(c(e)){if(A.rangesIntersect(a,b))return NodeFilter.FILTER_ACCEPT}else if(w(e)||n(e))return NodeFil [...]
- return NodeFilter.FILTER_REJECT});b.detach();return e};this.getImageElements=function(a){var b=a.startContainer.ownerDocument.createRange(),c;c=A.getNodesInRange(a,function(c){b.selectNodeContents(c);return g(c)&&A.containsRange(a,b)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP});b.detach();return c}};
- // Input 31
++odf.OdfUtils=function(){function g(a){return"image"===(a&&a.localName)&&a.namespaceURI===s}function k(a){return null!==a&&a.nodeType===Node.ELEMENT_NODE&&"frame"===a.localName&&a.namespaceURI===s&&"as-char"===a.getAttributeNS(t,"anchor-type")}function e(a){var c=a&&a.localName;return("p"===c||"h"===c)&&a.namespaceURI===t}function n(a){for(;a&&!e(a);)a=a.parentNode;return a}function m(a){return/^[ \t\r\n]+$/.test(a)}function q(a){if(null===a||a.nodeType!==Node.ELEMENT_NODE)return!1;var c [...]
++return/^(span|p|h|a|meta)$/.test(c)&&a.namespaceURI===t||"span"===c&&"annotationHighlight"===a.className}function b(a){var c=a&&a.localName,b;b=!1;c&&(b=a.namespaceURI,b=b===t?"s"===c||"tab"===c||"line-break"===c:k(a));return b}function h(a){var c=a&&a.localName,b=!1;c&&(a=a.namespaceURI,a===t&&(b="s"===c));return b}function r(a){for(;null!==a.firstChild&&q(a);)a=a.firstChild;return a}function d(a){for(;null!==a.lastChild&&q(a);)a=a.lastChild;return a}function f(a){for(;!e(a)&&null===a. [...]
++a.parentNode;return e(a)?null:d(a.previousSibling)}function a(a){for(;!e(a)&&null===a.nextSibling;)a=a.parentNode;return e(a)?null:r(a.nextSibling)}function c(a){for(var c=!1;a;)if(a.nodeType===Node.TEXT_NODE)if(0===a.length)a=f(a);else return!m(a.data.substr(a.length-1,1));else b(a)?(c=!1===h(a),a=null):a=f(a);return c}function p(c){var d=!1,f;for(c=c&&r(c);c;){f=c.nodeType===Node.TEXT_NODE?c.length:0;if(0<f&&!m(c.data)){d=!0;break}if(b(c)){d=!0;break}c=a(c)}return d}function l(c,b){re [...]
++!p(a(c)):!1}function u(a,d){var e=a.data,p;if(!m(e[d])||b(a.parentNode))return!1;0<d?m(e[d-1])||(p=!0):c(f(a))&&(p=!0);return!0===p?l(a,d)?!1:!0:!1}function B(a){return(a=/(-?[0-9]*[0-9][0-9]*(\.[0-9]*)?|0+\.[0-9]*[1-9][0-9]*|\.[0-9]*[1-9][0-9]*)((cm)|(mm)|(in)|(pt)|(pc)|(px)|(%))/.exec(a))?{value:parseFloat(a[1]),unit:a[3]}:null}function w(a){return(a=B(a))&&(0>a.value||"%"===a.unit)?null:a}function y(a){return(a=B(a))&&"%"!==a.unit?null:a}function v(a){switch(a.namespaceURI){case odf. [...]
++case odf.Namespaces.textns:switch(a.localName){case "note-body":case "ruby-text":return!1}break;case odf.Namespaces.officens:switch(a.localName){case "annotation":case "binary-data":case "event-listeners":return!1}break;default:switch(a.localName){case "editinfo":return!1}}return!0}var t=odf.Namespaces.textns,s=odf.Namespaces.drawns,N=/^\s*$/,z=new core.DomUtils;this.isImage=g;this.isCharacterFrame=k;this.isTextSpan=function(a){return"span"===(a&&a.localName)&&a.namespaceURI===t};this.i [...]
++e;this.getParagraphElement=n;this.isWithinTrackedChanges=function(a,c){for(;a&&a!==c;){if(a.namespaceURI===t&&"tracked-changes"===a.localName)return!0;a=a.parentNode}return!1};this.isListItem=function(a){return"list-item"===(a&&a.localName)&&a.namespaceURI===t};this.isLineBreak=function(a){return"line-break"===(a&&a.localName)&&a.namespaceURI===t};this.isODFWhitespace=m;this.isGroupingElement=q;this.isCharacterElement=b;this.isSpaceElement=h;this.firstChild=r;this.lastChild=d;this.previ [...]
++this.nextNode=a;this.scanLeftForNonSpace=c;this.lookLeftForCharacter=function(a){var d,e=d=0;a.nodeType===Node.TEXT_NODE&&(e=a.length);0<e?(d=a.data,d=m(d.substr(e-1,1))?1===e?c(f(a))?2:0:m(d.substr(e-2,1))?0:2:1):b(a)&&(d=1);return d};this.lookRightForCharacter=function(a){var c=!1,d=0;a&&a.nodeType===Node.TEXT_NODE&&(d=a.length);0<d?c=!m(a.data.substr(0,1)):b(a)&&(c=!0);return c};this.scanLeftForAnyCharacter=function(a){var c=!1,e;for(a=a&&d(a);a;){e=a.nodeType===Node.TEXT_NODE?a.leng [...]
++e&&!m(a.data)){c=!0;break}if(b(a)){c=!0;break}a=f(a)}return c};this.scanRightForAnyCharacter=p;this.isTrailingWhitespace=l;this.isSignificantWhitespace=u;this.isDowngradableSpaceElement=function(b){return b.namespaceURI===t&&"s"===b.localName?c(f(b))&&p(a(b)):!1};this.getFirstNonWhitespaceChild=function(a){for(a=a&&a.firstChild;a&&a.nodeType===Node.TEXT_NODE&&N.test(a.nodeValue);)a=a.nextSibling;return a};this.parseLength=B;this.parseNonNegativeLength=w;this.parseFoFontSize=function(a){ [...]
++B(a))&&(0>=c.value||"%"===c.unit)?null:c;return c||y(a)};this.parseFoLineHeight=function(a){return w(a)||y(a)};this.getImpactedParagraphs=function(a){var c,b,d;c=a.commonAncestorContainer;var f=[],p=[];for(c.nodeType===Node.ELEMENT_NODE&&(f=z.getElementsByTagNameNS(c,t,"p").concat(z.getElementsByTagNameNS(c,t,"h")));c&&!e(c);)c=c.parentNode;c&&f.push(c);b=f.length;for(c=0;c<b;c+=1)d=f[c],z.rangeIntersectsNode(a,d)&&p.push(d);return p};this.getTextNodes=function(a,c){var b=a.startContain [...]
++d;d=z.getNodesInRange(a,function(d){b.selectNodeContents(d);if(d.nodeType===Node.TEXT_NODE){if(c&&z.rangesIntersect(a,b)||z.containsRange(a,b))return Boolean(n(d)&&(!m(d.textContent)||u(d,0)))?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT}else if(z.rangesIntersect(a,b)&&v(d))return NodeFilter.FILTER_SKIP;return NodeFilter.FILTER_REJECT});b.detach();return d};this.getTextElements=function(a,c,d){var f=a.startContainer.ownerDocument.createRange(),e;e=z.getNodesInRange(a,function(e){f. [...]
++if(b(e.parentNode))return NodeFilter.FILTER_REJECT;if(e.nodeType===Node.TEXT_NODE){if(c&&z.rangesIntersect(a,f)||z.containsRange(a,f))if(d||Boolean(n(e)&&(!m(e.textContent)||u(e,0))))return NodeFilter.FILTER_ACCEPT}else if(b(e)){if(c&&z.rangesIntersect(a,f)||z.containsRange(a,f))return NodeFilter.FILTER_ACCEPT}else if(v(e)||q(e))return NodeFilter.FILTER_SKIP;return NodeFilter.FILTER_REJECT});f.detach();return e};this.getParagraphElements=function(a){var c=a.startContainer.ownerDocument. [...]
++b;b=z.getNodesInRange(a,function(b){c.selectNodeContents(b);if(e(b)){if(z.rangesIntersect(a,c))return NodeFilter.FILTER_ACCEPT}else if(v(b)||q(b))return NodeFilter.FILTER_SKIP;return NodeFilter.FILTER_REJECT});c.detach();return b};this.getImageElements=function(a){var c=a.startContainer.ownerDocument.createRange(),b;b=z.getNodesInRange(a,function(b){c.selectNodeContents(b);return g(b)&&z.containsRange(a,c)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP});c.detach();return b}};
++// Input 21
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("odf.OdfUtils");
- odf.TextSerializer=function(){function g(m){var f="",n=l.filter?l.filter.acceptNode(m):NodeFilter.FILTER_ACCEPT,b=m.nodeType,p;if(n===NodeFilter.FILTER_ACCEPT||n===NodeFilter.FILTER_SKIP)for(p=m.firstChild;p;)f+=g(p),p=p.nextSibling;n===NodeFilter.FILTER_ACCEPT&&(b===Node.ELEMENT_NODE&&c.isParagraph(m)?f+="\n":b===Node.TEXT_NODE&&m.textContent&&(f+=m.textContent));return f}var l=this,c=new odf.OdfUtils;this.filter=null;this.writeToString=function(c){if(!c)return"";c=g(c);"\n"===c[c.leng [...]
- c.substr(0,c.length-1));return c}};
- // Input 32
++ops.Server=function(){};ops.Server.prototype.connect=function(g,k){};ops.Server.prototype.networkStatus=function(){};ops.Server.prototype.login=function(g,k,e,n){};ops.Server.prototype.joinSession=function(g,k,e,n){};ops.Server.prototype.leaveSession=function(g,k,e,n){};ops.Server.prototype.getGenesisUrl=function(g){};
++// Input 22
++xmldom.LSSerializerFilter=function(){};xmldom.LSSerializerFilter.prototype.acceptNode=function(g){};
++// Input 23
++xmldom.XPathIterator=function(){};xmldom.XPathIterator.prototype.next=function(){};xmldom.XPathIterator.prototype.reset=function(){};
++function createXPathSingleton(){function g(b,a,c){return-1!==b&&(b<a||-1===a)&&(b<c||-1===c)}function k(b){for(var a=[],c=0,e=b.length,l;c<e;){var h=b,m=e,k=a,n="",q=[],r=h.indexOf("[",c),s=h.indexOf("/",c),N=h.indexOf("=",c);g(s,r,N)?(n=h.substring(c,s),c=s+1):g(r,s,N)?(n=h.substring(c,r),c=d(h,r,q)):g(N,s,r)?(n=h.substring(c,N),c=N):(n=h.substring(c,m),c=m);k.push({location:n,predicates:q});if(c<e&&"="===b[c]){l=b.substring(c+1,e);if(2<l.length&&("'"===l[0]||'"'===l[0]))l=l.slice(1,l. [...]
++else try{l=parseInt(l,10)}catch(z){}c=e}}return{steps:a,value:l}}function e(){var b=null,a=!1;this.setNode=function(a){b=a};this.reset=function(){a=!1};this.next=function(){var c=a?null:b;a=!0;return c}}function n(b,a,c){this.reset=function(){b.reset()};this.next=function(){for(var d=b.next();d;){d.nodeType===Node.ELEMENT_NODE&&(d=d.getAttributeNodeNS(a,c));if(d)break;d=b.next()}return d}}function m(b,a){var c=b.next(),d=null;this.reset=function(){b.reset();c=b.next();d=null};this.next= [...]
++d.firstChild)d=d.firstChild;else{for(;!d.nextSibling&&d!==c;)d=d.parentNode;d===c?c=b.next():d=d.nextSibling}else{do(d=c.firstChild)||(c=b.next());while(c&&!d)}if(d&&d.nodeType===Node.ELEMENT_NODE)return d}return null}}function q(b,a){this.reset=function(){b.reset()};this.next=function(){for(var c=b.next();c&&!a(c);)c=b.next();return c}}function b(b,a,c){a=a.split(":",2);var d=c(a[0]),e=a[1];return new q(b,function(a){return a.localName===e&&a.namespaceURI===d})}function h(b,a,c){var d= [...]
++a,c),h=a.value;return void 0===h?new q(b,function(a){d.setNode(a);l.reset();return null!==l.next()}):new q(b,function(a){d.setNode(a);l.reset();return(a=l.next())?a.nodeValue===h:!1})}var r,d;d=function(b,a,c){for(var d=a,e=b.length,h=0;d<e;)"]"===b[d]?(h-=1,0>=h&&c.push(k(b.substring(a,d)))):"["===b[d]&&(0>=h&&(a=d+1),h+=1),d+=1;return d};r=function(d,a,c){var e,l,g,k;for(e=0;e<a.steps.length;e+=1){g=a.steps[e];l=g.location;if(""===l)d=new m(d,!1);else if("@"===l[0]){l=l.substr(1).spli [...]
++c(l[0]);if(!k)throw"No namespace associated with the prefix "+l[0];d=new n(d,k,l[1])}else"."!==l&&(d=new m(d,!1),-1!==l.indexOf(":")&&(d=b(d,l,c)));for(l=0;l<g.predicates.length;l+=1)k=g.predicates[l],d=h(d,k,c)}return d};return{getODFElementsWithXPath:function(b,a,c){var d=b.ownerDocument,l=[],h=null;if(d&&"function"===typeof d.evaluate)for(c=d.evaluate(a,b,c,XPathResult.UNORDERED_NODE_ITERATOR_TYPE,null),h=c.iterateNext();null!==h;)h.nodeType===Node.ELEMENT_NODE&&l.push(h),h=c.iterate [...]
++new e;l.setNode(b);b=k(a);l=r(l,b,c);b=[];for(c=l.next();c;)b.push(c),c=l.next();l=b}return l}}}xmldom.XPath=createXPathSingleton();
++// Input 24
++runtime.loadClass("core.DomUtils");
++core.Cursor=function(g,k){function e(a){a.parentNode&&(h.push(a.previousSibling),h.push(a.nextSibling),a.parentNode.removeChild(a))}function n(a,c,b){if(c.nodeType===Node.TEXT_NODE){runtime.assert(Boolean(c),"putCursorIntoTextNode: invalid container");var d=c.parentNode;runtime.assert(Boolean(d),"putCursorIntoTextNode: container without parent");runtime.assert(0<=b&&b<=c.length,"putCursorIntoTextNode: offset is out of bounds");0===b?d.insertBefore(a,c):(b!==c.length&&c.splitText(b),d.in [...]
++c.nextSibling))}else c.nodeType===Node.ELEMENT_NODE&&c.insertBefore(a,c.childNodes.item(b));h.push(a.previousSibling);h.push(a.nextSibling)}var m=g.createElementNS("urn:webodf:names:cursor","cursor"),q=g.createElementNS("urn:webodf:names:cursor","anchor"),b,h=[],r=g.createRange(),d,f=new core.DomUtils;this.getNode=function(){return m};this.getAnchorNode=function(){return q.parentNode?q:m};this.getSelectedRange=function(){d?(r.setStartBefore(m),r.collapse(!0)):(r.setStartAfter(b?q:m),r.s [...]
++m:q));return r};this.setSelectedRange=function(a,c){r&&r!==a&&r.detach();r=a;b=!1!==c;(d=a.collapsed)?(e(q),e(m),n(m,a.startContainer,a.startOffset)):(e(q),e(m),n(b?m:q,a.endContainer,a.endOffset),n(b?q:m,a.startContainer,a.startOffset));h.forEach(f.normalizeTextNodes);h.length=0};this.hasForwardSelection=function(){return b};this.remove=function(){e(m);h.forEach(f.normalizeTextNodes);h.length=0};m.setAttributeNS("urn:webodf:names:cursor","memberId",k);q.setAttributeNS("urn:webodf:names [...]
++k)};
++// Input 25
++runtime.loadClass("core.PositionIterator");core.PositionFilter=function(){};core.PositionFilter.FilterResult={FILTER_ACCEPT:1,FILTER_REJECT:2,FILTER_SKIP:3};core.PositionFilter.prototype.acceptPosition=function(g){};(function(){return core.PositionFilter})();
++// Input 26
++runtime.loadClass("core.PositionFilter");core.PositionFilterChain=function(){var g={},k=core.PositionFilter.FilterResult.FILTER_ACCEPT,e=core.PositionFilter.FilterResult.FILTER_REJECT;this.acceptPosition=function(n){for(var m in g)if(g.hasOwnProperty(m)&&g[m].acceptPosition(n)===e)return e;return k};this.addFilter=function(e,m){g[e]=m};this.removeFilter=function(e){delete g[e]}};
++// Input 27
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.DomUtils");runtime.loadClass("core.LoopWatchDog");runtime.loadClass("odf.Namespaces");
- odf.TextStyleApplicator=function(g,l,c){function m(b){function c(a,b){return"object"===typeof a&&"object"===typeof b?Object.keys(a).every(function(d){return c(a[d],b[d])}):a===b}this.isStyleApplied=function(a){a=l.getAppliedStylesForElement(a);return c(b,a)}}function f(b){var f={};this.applyStyleToContainer=function(a){var e;e=a.getAttributeNS(p,"style-name");var h=a.ownerDocument;e=e||"";if(!f.hasOwnProperty(e)){var m=e,n;n=e?l.createDerivedStyleObject(e,"text",b):b;h=h.createElementNS [...]
- l.updateStyle(h,n);h.setAttributeNS(r,"style:name",g.generateStyleName());h.setAttributeNS(r,"style:family","text");h.setAttributeNS("urn:webodf:names:scope","scope","document-content");c.appendChild(h);f[m]=h}e=f[e].getAttributeNS(r,"name");a.setAttributeNS(p,"text:style-name",e)}}function n(c,f){var a=c.ownerDocument,e=c.parentNode,h,g,l=new core.LoopWatchDog(1E4);g=[];"span"!==e.localName||e.namespaceURI!==p?(h=a.createElementNS(p,"text:span"),e.insertBefore(h,c),e=!1):(c.previousSib [...]
- e.firstChild)?(h=e.cloneNode(!1),e.parentNode.insertBefore(h,e.nextSibling)):h=e,e=!0);g.push(c);for(a=c.nextSibling;a&&b.rangeContainsNode(f,a);)l.check(),g.push(a),a=a.nextSibling;g.forEach(function(a){a.parentNode!==h&&h.appendChild(a)});if(a&&e)for(g=h.cloneNode(!1),h.parentNode.insertBefore(g,h.nextSibling);a;)l.check(),e=a.nextSibling,g.appendChild(a),a=e;return h}var b=new core.DomUtils,p=odf.Namespaces.textns,r=odf.Namespaces.stylens;this.applyStyle=function(b,c,a){var e={},h,g, [...]
- a["style:text-properties"],"applyStyle without any text properties");e["style:text-properties"]=a["style:text-properties"];l=new f(e);p=new m(e);b.forEach(function(a){h=p.isStyleApplied(a);!1===h&&(g=n(a,c),l.applyStyleToContainer(g))})}};
- // Input 33
++gui.AnnotatableCanvas=function(){};gui.AnnotatableCanvas.prototype.refreshSize=function(){};gui.AnnotatableCanvas.prototype.getZoomLevel=function(){};gui.AnnotatableCanvas.prototype.getSizer=function(){};
++gui.AnnotationViewManager=function(g,k,e){function n(a){var c=a.node,b=a.end;a=r.createRange();b&&(a.setStart(c,c.childNodes.length),a.setEnd(b,0),b=d.getTextNodes(a,!1),b.forEach(function(a){var b=r.createElement("span"),d=c.getAttributeNS(odf.Namespaces.officens,"name");b.className="annotationHighlight";b.setAttribute("annotation",d);a.parentNode.insertBefore(b,a);b.appendChild(a)}));a.detach()}function m(a){var c=g.getSizer();a?(e.style.display="inline-block",c.style.paddingRight=f.g [...]
++(e.style.display="none",c.style.paddingRight=0);g.refreshSize()}function q(){h.sort(function(a,c){return a.node.compareDocumentPosition(c.node)===Node.DOCUMENT_POSITION_FOLLOWING?-1:1})}function b(){var a;for(a=0;a<h.length;a+=1){var c=h[a],b=c.node.parentElement,d=b.nextElementSibling,f=d.nextElementSibling,m=b.parentElement,k=0,k=h[h.indexOf(c)-1],n=void 0,c=g.getZoomLevel();b.style.left=(e.getBoundingClientRect().left-m.getBoundingClientRect().left)/c+"px";b.style.width=e.getBounding [...]
++c+"px";d.style.width=parseFloat(b.style.left)-30+"px";k&&(n=k.node.parentElement.getBoundingClientRect(),20>=(m.getBoundingClientRect().top-n.bottom)/c?b.style.top=Math.abs(m.getBoundingClientRect().top-n.bottom)/c+20+"px":b.style.top="0px");f.style.left=d.getBoundingClientRect().width/c+"px";var d=f.style,m=f.getBoundingClientRect().left/c,k=f.getBoundingClientRect().top/c,n=b.getBoundingClientRect().left/c,q=b.getBoundingClientRect().top/c,r=0,s=0,r=n-m,r=r*r,s=q-k,s=s*s,m=Math.sqrt(r [...]
++m+"px";k=Math.asin((b.getBoundingClientRect().top-f.getBoundingClientRect().top)/(c*parseFloat(f.style.width)));f.style.transform="rotate("+k+"rad)";f.style.MozTransform="rotate("+k+"rad)";f.style.WebkitTransform="rotate("+k+"rad)";f.style.msTransform="rotate("+k+"rad)"}}var h=[],r=k.ownerDocument,d=new odf.OdfUtils,f=runtime.getWindow();runtime.assert(Boolean(f),"Expected to be run in an environment which has a global window, like a browser.");this.rerenderAnnotations=b;this.addAnnotat [...]
++h.push({node:a.node,end:a.end});q();var c=r.createElement("div"),d=r.createElement("div"),f=r.createElement("div"),e=r.createElement("div"),g=r.createElement("div"),k=a.node;c.className="annotationWrapper";k.parentNode.insertBefore(c,k);d.className="annotationNote";d.appendChild(k);g.className="annotationRemoveButton";d.appendChild(g);f.className="annotationConnector horizontal";e.className="annotationConnector angular";c.appendChild(d);c.appendChild(f);c.appendChild(e);a.end&&n(a);b()} [...]
++function(){for(;h.length;){var a=h[0],c=h.indexOf(a),b=a.node,d=b.parentNode.parentNode;"div"===d.localName&&(d.parentNode.insertBefore(b,d),d.parentNode.removeChild(d));a=a.node.getAttributeNS(odf.Namespaces.officens,"name");a=r.querySelectorAll('span.annotationHighlight[annotation="'+a+'"]');d=b=void 0;for(b=0;b<a.length;b+=1){for(d=a.item(b);d.firstChild;)d.parentNode.insertBefore(d.firstChild,d);d.parentNode.removeChild(d)}-1!==c&&h.splice(c,1);0===h.length&&m(!1)}}};
++// Input 28
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.OdfUtils");runtime.loadClass("xmldom.XPath");runtime.loadClass("core.CSSUnits");
- odf.Style2CSS=function(){function g(a){var b={},c,e;if(!a)return b;for(a=a.firstChild;a;){if(e=a.namespaceURI!==q||"style"!==a.localName&&"default-style"!==a.localName?a.namespaceURI===v&&"list-style"===a.localName?"list":a.namespaceURI!==q||"page-layout"!==a.localName&&"default-page-layout"!==a.localName?void 0:"page":a.getAttributeNS(q,"family"))(c=a.getAttributeNS&&a.getAttributeNS(q,"name"))||(c=""),e=b[e]=b[e]||{},e[c]=a;a=a.nextSibling}return b}function l(a,b){if(!b||!a)return nul [...]
- var c,e;for(c in a)if(a.hasOwnProperty(c)&&(e=l(a[c].derivedStyles,b)))return e;return null}function c(a,b,e){var d=b[a],h,f;d&&(h=d.getAttributeNS(q,"parent-style-name"),f=null,h&&(f=l(e,h),!f&&b[h]&&(c(h,b,e),f=b[h],b[h]=null)),f?(f.derivedStyles||(f.derivedStyles={}),f.derivedStyles[a]=d):e[a]=d)}function m(a,b){for(var e in a)a.hasOwnProperty(e)&&(c(e,a,b),a[e]=null)}function f(a,b){var c=t[a],e;if(null===c)return null;e=b?"["+c+'|style-name="'+b+'"]':"";"presentation"===c&&(c="draw [...]
- b+'"]':"");return c+"|"+s[a].join(e+","+c+"|")+e}function n(a,b,c){var e=[],d,h;e.push(f(a,b));for(d in c.derivedStyles)if(c.derivedStyles.hasOwnProperty(d))for(h in b=n(a,d,c.derivedStyles[d]),b)b.hasOwnProperty(h)&&e.push(b[h]);return e}function b(a,b,c){if(!a)return null;for(a=a.firstChild;a;){if(a.namespaceURI===b&&a.localName===c)return b=a;a=a.nextSibling}return null}function p(a,b){var c="",e,d;for(e in b)if(b.hasOwnProperty(e)&&(e=b[e],d=a.getAttributeNS(e[0],e[1]))){d=d.trim(); [...]
- d.indexOf(" "),f=void 0,k=void 0;-1!==h?(f=d.substring(0,h),k=d.substring(h)):(f=d,k="");(f=ba.parseLength(f))&&"pt"===f.unit&&0.75>f.value&&(d="0.75pt"+k)}e[2]&&(c+=e[2]+":"+d+";")}return c}function r(a){return(a=b(a,q,"text-properties"))?ba.parseFoFontSize(a.getAttributeNS(h,"font-size")):null}function d(a){a=a.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i,function(a,b,c,e){return b+b+c+c+e+e});return(a=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(a))?{r:parseInt(a[1],16),g:parseInt( [...]
- 16)}:null}function k(a,b,c,e){b='text|list[text|style-name="'+b+'"]';var d=c.getAttributeNS(v,"level"),h;c=ba.getFirstNonWhitespaceChild(c);c=ba.getFirstNonWhitespaceChild(c);var f;c&&(h=c.attributes,f=h["fo:text-indent"]?h["fo:text-indent"].value:void 0,h=h["fo:margin-left"]?h["fo:margin-left"].value:void 0);f||(f="-0.6cm");c="-"===f.charAt(0)?f.substring(1):"-"+f;for(d=d&&parseInt(d,10);1<d;)b+=" > text|list-item > text|list",d-=1;d=b+" > text|list-item > *:not(text|list):first-child" [...]
- h&&(h=d+"{margin-left:"+h+";}",a.insertRule(h,a.cssRules.length));e=b+" > text|list-item > *:not(text|list):first-child:before{"+e+";";e+="counter-increment:list;";e+="margin-left:"+f+";";e+="width:"+c+";";e+="display:inline-block}";try{a.insertRule(e,a.cssRules.length)}catch(k){throw k;}}function a(c,f,g,l){if("list"===f)for(var s=l.firstChild,m,t;s;){if(s.namespaceURI===v)if(m=s,"list-level-style-number"===s.localName){var u=m;t=u.getAttributeNS(q,"num-format");var P=u.getAttributeNS( [...]
- L={1:"decimal",a:"lower-latin",A:"upper-latin",i:"lower-roman",I:"upper-roman"},u=u.getAttributeNS(q,"num-prefix")||"",u=L.hasOwnProperty(t)?u+(" counter(list, "+L[t]+")"):t?u+("'"+t+"';"):u+" ''";P&&(u+=" '"+P+"'");t="content: "+u+";";k(c,g,m,t)}else"list-level-style-image"===s.localName?(t="content: none;",k(c,g,m,t)):"list-level-style-bullet"===s.localName&&(t="content: '"+m.getAttributeNS(v,"bullet-char")+"';",k(c,g,m,t));s=s.nextSibling}else if("page"===f)if(P=m=g="",s=l.getElement [...]
- "page-layout-properties")[0],m=s.parentNode.parentNode.parentNode.masterStyles,P="",g+=p(s,$),t=s.getElementsByTagNameNS(q,"background-image"),0<t.length&&(P=t.item(0).getAttributeNS(y,"href"))&&(g+="background-image: url('odfkit:"+P+"');",t=t.item(0),g+=p(t,A)),"presentation"===ga){if(m)for(t=m.getElementsByTagNameNS(q,"master-page"),L=0;L<t.length;L+=1)if(t[L].getAttributeNS(q,"page-layout-name")===s.parentNode.getAttributeNS(q,"name")){P=t[L].getAttributeNS(q,"name");m="draw|page[dra [...]
- P+"] {"+g+"}";P="office|body, draw|page[draw|master-page-name="+P+"] {"+p(s,ia)+" }";try{c.insertRule(m,c.cssRules.length),c.insertRule(P,c.cssRules.length)}catch(R){throw R;}}}else{if("text"===ga){m="office|text {"+g+"}";P="office|body {width: "+s.getAttributeNS(h,"page-width")+";}";try{c.insertRule(m,c.cssRules.length),c.insertRule(P,c.cssRules.length)}catch(E){throw E;}}}else{g=n(f,g,l).join(",");s="";if(m=b(l,q,"text-properties")){var L=m,U;t=U="";P=1;m=""+p(L,D);u=L.getAttributeNS( [...]
- "solid"===u&&(U+=" underline");u=L.getAttributeNS(q,"text-line-through-style");"solid"===u&&(U+=" line-through");U.length&&(m+="text-decoration:"+U+";");if(U=L.getAttributeNS(q,"font-name")||L.getAttributeNS(h,"font-family"))u=ma[U],m+="font-family: "+(u||U)+";";u=L.parentNode;if(L=r(u)){for(;u;){if(L=r(u)){if("%"!==L.unit){t="font-size: "+L.value*P+L.unit+";";break}P*=L.value/100}L=u;U=u="";u=null;"default-style"===L.localName?u=null:(u=L.getAttributeNS(q,"parent-style-name"),U=L.getAt [...]
- "family"),u=V.getODFElementsWithXPath(S,u?"//style:*[@style:name='"+u+"'][@style:family='"+U+"']":"//style:default-style[@style:family='"+U+"']",odf.Namespaces.resolvePrefix)[0])}t||(t="font-size: "+parseFloat(Y)*P+G.getUnits(Y)+";");m+=t}s+=m}if(m=b(l,q,"paragraph-properties"))t=m,m=""+p(t,B),P=t.getElementsByTagNameNS(q,"background-image"),0<P.length&&(L=P.item(0).getAttributeNS(y,"href"))&&(m+="background-image: url('odfkit:"+L+"');",P=P.item(0),m+=p(P,A)),(t=t.getAttributeNS(h,"line [...]
- "normal"!==t&&(t=ba.parseFoLineHeight(t),m="%"!==t.unit?m+("line-height: "+t.value+t.unit+";"):m+("line-height: "+t.value/100+";")),s+=m;if(m=b(l,q,"graphic-properties"))L=m,m=""+p(L,M),t=L.getAttributeNS(e,"opacity"),P=L.getAttributeNS(e,"fill"),L=L.getAttributeNS(e,"fill-color"),"solid"===P||"hatch"===P?L&&"none"!==L?(t=isNaN(parseFloat(t))?1:parseFloat(t)/100,(L=d(L))&&(m+="background-color: rgba("+L.r+","+L.g+","+L.b+","+t+");")):m+="background: none;":"none"===P&&(m+="background: n [...]
- m;if(m=b(l,q,"drawing-page-properties"))t=""+p(m,M),"true"===m.getAttributeNS(w,"background-visible")&&(t+="background: none;"),s+=t;if(m=b(l,q,"table-cell-properties"))m=""+p(m,z),s+=m;if(m=b(l,q,"table-row-properties"))m=""+p(m,F),s+=m;if(m=b(l,q,"table-column-properties"))m=""+p(m,K),s+=m;if(m=b(l,q,"table-properties"))t=m,m=""+p(t,Q),t=t.getAttributeNS(x,"border-model"),"collapsing"===t?m+="border-collapse:collapse;":"separating"===t&&(m+="border-collapse:separate;"),s+=m;if(0!==s.l [...]
- "{"+s+"}",c.cssRules.length)}catch(H){throw H;}}for(var la in l.derivedStyles)l.derivedStyles.hasOwnProperty(la)&&a(c,f,la,l.derivedStyles[la])}var e=odf.Namespaces.drawns,h=odf.Namespaces.fons,q=odf.Namespaces.stylens,u=odf.Namespaces.svgns,x=odf.Namespaces.tablens,v=odf.Namespaces.textns,y=odf.Namespaces.xlinkns,w=odf.Namespaces.presentationns,t={graphic:"draw","drawing-page":"draw",paragraph:"text",presentation:"presentation",ruby:"text",section:"text",table:"table","table-cell":"tab [...]
- "table-row":"table",text:"text",list:"text",page:"office"},s={graphic:"circle connected control custom-shape ellipse frame g line measure page page-thumbnail path polygon polyline rect regular-polygon".split(" "),paragraph:"alphabetical-index-entry-template h illustration-index-entry-template index-source-style object-index-entry-template p table-index-entry-template table-of-content-entry-template user-index-entry-template".split(" "),presentation:"caption circle connector control cust [...]
- "drawing-page":"caption circle connector control page custom-shape ellipse frame g line measure page-thumbnail path polygon polyline rect regular-polygon".split(" "),ruby:["ruby","ruby-text"],section:"alphabetical-index bibliography illustration-index index-title object-index section table-of-content table-index user-index".split(" "),table:["background","table"],"table-cell":"body covered-table-cell even-columns even-rows first-column first-row last-column last-row odd-columns odd-rows [...]
- "table-column":["table-column"],"table-row":["table-row"],text:"a index-entry-chapter index-entry-link-end index-entry-link-start index-entry-page-number index-entry-span index-entry-tab-stop index-entry-text index-title-template linenumbering-configuration list-level-style-number list-level-style-bullet outline-level-style span".split(" "),list:["list-item"]},D=[[h,"color","color"],[h,"background-color","background-color"],[h,"font-weight","font-weight"],[h,"font-style","font-style"]], [...]
- "background-repeat"]],B=[[h,"background-color","background-color"],[h,"text-align","text-align"],[h,"text-indent","text-indent"],[h,"padding","padding"],[h,"padding-left","padding-left"],[h,"padding-right","padding-right"],[h,"padding-top","padding-top"],[h,"padding-bottom","padding-bottom"],[h,"border-left","border-left"],[h,"border-right","border-right"],[h,"border-top","border-top"],[h,"border-bottom","border-bottom"],[h,"margin","margin"],[h,"margin-left","margin-left"],[h,"margin-r [...]
- [h,"margin-top","margin-top"],[h,"margin-bottom","margin-bottom"],[h,"border","border"]],M=[[h,"background-color","background-color"],[h,"min-height","min-height"],[e,"stroke","border"],[u,"stroke-color","border-color"],[u,"stroke-width","border-width"],[h,"border","border"],[h,"border-left","border-left"],[h,"border-right","border-right"],[h,"border-top","border-top"],[h,"border-bottom","border-bottom"]],z=[[h,"background-color","background-color"],[h,"border-left","border-left"],[h,"b [...]
- "border-right"],[h,"border-top","border-top"],[h,"border-bottom","border-bottom"],[h,"border","border"]],K=[[q,"column-width","width"]],F=[[q,"row-height","height"],[h,"keep-together",null]],Q=[[q,"width","width"],[h,"margin-left","margin-left"],[h,"margin-right","margin-right"],[h,"margin-top","margin-top"],[h,"margin-bottom","margin-bottom"]],$=[[h,"background-color","background-color"],[h,"padding","padding"],[h,"padding-left","padding-left"],[h,"padding-right","padding-right"],[h,"p [...]
- "padding-top"],[h,"padding-bottom","padding-bottom"],[h,"border","border"],[h,"border-left","border-left"],[h,"border-right","border-right"],[h,"border-top","border-top"],[h,"border-bottom","border-bottom"],[h,"margin","margin"],[h,"margin-left","margin-left"],[h,"margin-right","margin-right"],[h,"margin-top","margin-top"],[h,"margin-bottom","margin-bottom"]],ia=[[h,"page-width","width"],[h,"page-height","height"]],R={border:!0,"border-left":!0,"border-right":!0,"border-top":!0,"border- [...]
- "stroke-width":!0},ma={},ba=new odf.OdfUtils,ga,S,Y,V=new xmldom.XPath,G=new core.CSSUnits;this.style2css=function(b,c,e,d,h){for(var f,k,l,s;c.cssRules.length;)c.deleteRule(c.cssRules.length-1);f=null;d&&(f=d.ownerDocument,S=d.parentNode);h&&(f=h.ownerDocument,S=h.parentNode);if(f)for(s in odf.Namespaces.forEachPrefix(function(a,b){l="@namespace "+a+" url("+b+");";try{c.insertRule(l,c.cssRules.length)}catch(e){}}),ma=e,ga=b,Y=runtime.getWindow().getComputedStyle(document.body,null).get [...]
- "12pt",b=g(d),d=g(h),h={},t)if(t.hasOwnProperty(s))for(k in e=h[s]={},m(b[s],e),m(d[s],e),e)e.hasOwnProperty(k)&&a(c,s,k,e[k])}};
- // Input 34
++runtime.loadClass("core.Cursor");runtime.loadClass("core.DomUtils");runtime.loadClass("core.PositionIterator");runtime.loadClass("core.PositionFilter");runtime.loadClass("core.LoopWatchDog");runtime.loadClass("odf.OdfUtils");
++gui.SelectionMover=function(g,k){function e(){w.setUnfilteredPosition(g.getNode(),0);return w}function n(a,c){var b,d=null;a&&0<a.length&&(b=c?a.item(a.length-1):a.item(0));b&&(d={top:b.top,left:c?b.right:b.left,bottom:b.bottom});return d}function m(a,c,b,d){var f=a.nodeType;b.setStart(a,c);b.collapse(!d);d=n(b.getClientRects(),!0===d);!d&&0<c&&(b.setStart(a,c-1),b.setEnd(a,c),d=n(b.getClientRects(),!0));d||(f===Node.ELEMENT_NODE&&0<c&&a.childNodes.length>=c?d=m(a,c-1,b,!0):a.nodeType== [...]
++0<c?d=m(a,c-1,b,!0):a.previousSibling?d=m(a.previousSibling,a.previousSibling.nodeType===Node.TEXT_NODE?a.previousSibling.textContent.length:a.previousSibling.childNodes.length,b,!0):a.parentNode&&a.parentNode!==k?d=m(a.parentNode,0,b,!1):(b.selectNode(k),d=n(b.getClientRects(),!1)));runtime.assert(Boolean(d),"No visible rectangle found");return d}function q(a,c,b){var d=a,f=e(),l,h=k.ownerDocument.createRange(),p=g.getSelectedRange().cloneRange(),n;for(l=m(f.container(),f.unfilteredDom [...]
++d&&b();)d-=1;c?(c=f.container(),f=f.unfilteredDomOffset(),-1===B.comparePoints(p.startContainer,p.startOffset,c,f)?(p.setStart(c,f),n=!1):p.setEnd(c,f)):(p.setStart(f.container(),f.unfilteredDomOffset()),p.collapse(!0));g.setSelectedRange(p,n);f=e();p=m(f.container(),f.unfilteredDomOffset(),h);if(p.top===l.top||void 0===y)y=p.left;runtime.clearTimeout(v);v=runtime.setTimeout(function(){y=void 0},2E3);h.detach();return a-d}function b(a){var c=e();return a.acceptPosition(c)===t&&(c.setUnf [...]
++0),a.acceptPosition(c)===t)?!0:!1}function h(a,c,b){for(var d=new core.LoopWatchDog(1E4),f=0,e=0,l=0<=c?1:-1,h=0<=c?a.nextPosition:a.previousPosition;0!==c&&h();)d.check(),e+=l,b.acceptPosition(a)===t&&(c-=l,f+=e,e=0);return f}function r(a,c,b){for(var d=e(),f=new core.LoopWatchDog(1E4),l=0,h=0;0<a&&d.nextPosition();)f.check(),b.acceptPosition(d)===t&&(l+=1,c.acceptPosition(d)===t&&(h+=l,l=0,a-=1));return h}function d(a,c,b){for(var d=e(),f=new core.LoopWatchDog(1E4),l=0,h=0;0<a&&d.prev [...]
++b.acceptPosition(d)===t&&(l+=1,c.acceptPosition(d)===t&&(h+=l,l=0,a-=1));return h}function f(a,c){var b=e();return h(b,a,c)}function a(a,c,b){var d=e(),f=u.getParagraphElement(d.getCurrentNode()),l=0;d.setUnfilteredPosition(a,c);b.acceptPosition(d)!==t&&(l=h(d,-1,b),0===l||f&&f!==u.getParagraphElement(d.getCurrentNode()))&&(d.setUnfilteredPosition(a,c),l=h(d,1,b));return l}function c(a,c){var b=e(),d=0,f=0,l=0>a?-1:1;for(a=Math.abs(a);0<a;){for(var h=c,p=l,g=b,n=g.container(),q=0,r=null [...]
++u=10,w=void 0,B=0,I=void 0,C=void 0,Y=void 0,w=void 0,H=k.ownerDocument.createRange(),X=new core.LoopWatchDog(1E4),w=m(n,g.unfilteredDomOffset(),H),I=w.top,C=void 0===y?w.left:y,Y=I;!0===(0>p?g.previousPosition():g.nextPosition());)if(X.check(),h.acceptPosition(g)===t&&(q+=1,n=g.container(),w=m(n,g.unfilteredDomOffset(),H),w.top!==I)){if(w.top!==Y&&Y!==I)break;Y=w.top;w=Math.abs(C-w.left);if(null===r||w<u)r=n,v=g.unfilteredDomOffset(),u=w,B=q}null!==r?(g.setUnfilteredPosition(r,v),q=B): [...]
++d+=q;if(0===d)break;f+=d;a-=1}return f*l}function p(a,c){var b,d,f,l,h=e(),p=u.getParagraphElement(h.getCurrentNode()),g=0,n=k.ownerDocument.createRange();0>a?(b=h.previousPosition,d=-1):(b=h.nextPosition,d=1);for(f=m(h.container(),h.unfilteredDomOffset(),n);b.call(h);)if(c.acceptPosition(h)===t){if(u.getParagraphElement(h.getCurrentNode())!==p)break;l=m(h.container(),h.unfilteredDomOffset(),n);if(l.bottom!==f.bottom&&(f=l.top>=f.top&&l.bottom<f.bottom||l.top<=f.top&&l.bottom>f.bottom,! [...]
++d;f=l}n.detach();return g}function l(a,c,b){runtime.assert(null!==a,"SelectionMover.countStepsToPosition called with element===null");var d=e(),f=d.container(),l=d.unfilteredDomOffset(),h=0,p=new core.LoopWatchDog(1E4);for(d.setUnfilteredPosition(a,c);b.acceptPosition(d)!==t&&d.previousPosition();)p.check();a=d.container();runtime.assert(Boolean(a),"SelectionMover.countStepsToPosition: positionIterator.container() returned null");c=d.unfilteredDomOffset();for(d.setUnfilteredPosition(f,l [...]
++t&&d.previousPosition();)p.check();f=B.comparePoints(a,c,d.container(),d.unfilteredDomOffset());if(0>f)for(;d.nextPosition()&&(p.check(),b.acceptPosition(d)===t&&(h+=1),d.container()!==a||d.unfilteredDomOffset()!==c););else if(0<f)for(;d.previousPosition()&&(p.check(),b.acceptPosition(d)!==t||(h-=1,d.container()!==a||d.unfilteredDomOffset()!==c)););return h}var u=new odf.OdfUtils,B=new core.DomUtils,w,y,v,t=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.movePointForward=function(a, [...]
++c||!1,w.nextPosition)};this.movePointBackward=function(a,c){return q(a,c||!1,w.previousPosition)};this.getStepCounter=function(){return{countSteps:f,convertForwardStepsBetweenFilters:r,convertBackwardStepsBetweenFilters:d,countLinesSteps:c,countStepsToLineBoundary:p,countStepsToPosition:l,isPositionWalkable:b,countPositionsToNearestStep:a}};(function(){w=gui.SelectionMover.createPositionIterator(k);var a=k.ownerDocument.createRange();a.setStart(w.container(),w.unfilteredDomOffset());a.c [...]
++g.setSelectedRange(a)})()};gui.SelectionMover.createPositionIterator=function(g){var k=new function(){this.acceptNode=function(e){return e&&"urn:webodf:names:cursor"!==e.namespaceURI&&"urn:webodf:names:editinfo"!==e.namespaceURI?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT}};return new core.PositionIterator(g,5,k,!1)};(function(){return gui.SelectionMover})();
++// Input 29
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ This file is part of WebODF.
+
+ WebODF is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License (GNU AGPL)
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ WebODF is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ @licend
+
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+runtime.loadClass("odf.Namespaces");runtime.loadClass("core.DomUtils");
- odf.MetadataManager=function(g){function l(f,l){f&&(Object.keys(f).forEach(function(b){m[b]=f[b]}),c.mapKeyValObjOntoNode(g,f,odf.Namespaces.resolvePrefix));l&&(l.forEach(function(b){delete m[b]}),c.removeKeyElementsFromNode(g,l,odf.Namespaces.resolvePrefix))}var c=new core.DomUtils,m={};this.setMetadata=l;this.incrementEditingCycles=function(){var c=parseInt(m["meta:editing-cycles"]||0,10)+1;l({"meta:editing-cycles":c},null)};m=c.getKeyValRepresentationOfNode(g,odf.Namespaces.lookupPrefix)};
- // Input 35
++odf.MetadataManager=function(g){function k(m,k){m&&(Object.keys(m).forEach(function(b){n[b]=m[b]}),e.mapKeyValObjOntoNode(g,m,odf.Namespaces.lookupNamespaceURI));k&&(k.forEach(function(b){delete n[b]}),e.removeKeyElementsFromNode(g,k,odf.Namespaces.lookupNamespaceURI))}var e=new core.DomUtils,n={};this.setMetadata=k;this.incrementEditingCycles=function(){var e=parseInt(n["meta:editing-cycles"]||0,10)+1;k({"meta:editing-cycles":e},null)};n=e.getKeyValRepresentationOfNode(g,odf.Namespaces [...]
++// Input 30
+/*
+
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.Base64");runtime.loadClass("core.Zip");runtime.loadClass("xmldom.LSSerializer");runtime.loadClass("odf.StyleInfo");runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.OdfNodeFilter");runtime.loadClass("odf.MetadataManager");
- odf.OdfContainer=function(){function g(a,b,c){for(a=a?a.firstChild:null;a;){if(a.localName===c&&a.namespaceURI===b)return a;a=a.nextSibling}return null}function l(a){var b,c=k.length;for(b=0;b<c;b+=1)if("urn:oasis:names:tc:opendocument:xmlns:office:1.0"===a.namespaceURI&&a.localName===k[b])return b;return-1}function c(a,b){var c=new p.UsedStyleList(a,b),e=new odf.OdfNodeFilter;this.acceptNode=function(a){var d=e.acceptNode(a);d===NodeFilter.FILTER_ACCEPT&&a.parentNode===b&&a.nodeType=== [...]
- (d=c.uses(a)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT);return d}}function m(a,b){var e=new c(a,b);this.acceptNode=function(a){var b=e.acceptNode(a);b!==NodeFilter.FILTER_ACCEPT||!a.parentNode||a.parentNode.namespaceURI!==odf.Namespaces.textns||"s"!==a.parentNode.localName&&"tab"!==a.parentNode.localName||(b=NodeFilter.FILTER_REJECT);return b}}function f(a,b){if(b){var c=l(b),e,d=a.firstChild;if(-1!==c){for(;d;){e=l(d);if(-1!==e&&e>c)break;d=d.nextSibling}a.insertBefore(b,d)}}}f [...]
- a}function b(a,b,c,e){var d=this;this.size=0;this.type=null;this.name=a;this.container=c;this.onchange=this.onreadystatechange=this.document=this.mimetype=this.url=null;this.EMPTY=0;this.LOADING=1;this.DONE=2;this.state=this.EMPTY;this.load=function(){null!==e&&(this.mimetype=b,e.loadAsDataURL(a,b,function(a,b){a&&runtime.log(a);d.url=b;if(d.onchange)d.onchange(d);if(d.onstatereadychange)d.onstatereadychange(d)}))}}var p=new odf.StyleInfo,r,d=odf.Namespaces.stylens,k="meta settings scri [...]
- a=(new Date).getTime()+"_webodf_",e=new core.Base64;n.prototype=new function(){};n.prototype.constructor=n;n.namespaceURI="urn:oasis:names:tc:opendocument:xmlns:office:1.0";n.localName="document";b.prototype.load=function(){};b.prototype.getUrl=function(){return this.data?"data:;base64,"+e.toBase64(this.data):null};odf.OdfContainer=function q(k,l){function v(a){for(var b=a.firstChild,c;b;)c=b.nextSibling,b.nodeType===Node.ELEMENT_NODE?v(b):b.nodeType===Node.PROCESSING_INSTRUCTION_NODE&& [...]
- b=c}function y(a,b){for(var c=a&&a.firstChild;c;)c.nodeType===Node.ELEMENT_NODE&&c.setAttributeNS("urn:webodf:names:scope","scope",b),c=c.nextSibling}function w(a,b){function c(a,b,e){var d=0,f;for(f=a=a.replace(/\d+$/,"");b.hasOwnProperty(f)||e.hasOwnProperty(f);)d+=1,f=a+d;return f}function e(a){var b={};for(a=a.firstChild;a;)a.nodeType===Node.ELEMENT_NODE&&a.namespaceURI===d&&"font-face"===a.localName&&(g=a.getAttributeNS(d,"name"),b[g]=a),a=a.nextSibling;return b}var f,k,g,l,m,s,p={ [...]
- e(b);for(f=b.firstChild;f;)k=f.nextSibling,f.nodeType===Node.ELEMENT_NODE&&f.namespaceURI===d&&"font-face"===f.localName&&(g=f.getAttributeNS(d,"name"),m.hasOwnProperty(g)?f.isEqualNode(m[g])||(l=c(g,m,s),f.setAttributeNS(d,"style:name",l),a.appendChild(f),m[l]=f,delete s[g],p[g]=l):(a.appendChild(f),m[g]=f,delete s[g])),f=k;return p}function t(a,b){var c=null,e,d,f;if(a)for(c=a.cloneNode(!0),e=c.firstChild;e;)d=e.nextSibling,e.nodeType===Node.ELEMENT_NODE&&(f=e.getAttributeNS("urn:webo [...]
- "scope"))&&f!==b&&c.removeChild(e),e=d;return c}function s(a,b){var c=null,e,f,k,g={};if(a)for(b.forEach(function(a){p.collectUsedFontFaces(g,a)}),c=a.cloneNode(!0),e=c.firstChild;e;)f=e.nextSibling,e.nodeType===Node.ELEMENT_NODE&&(k=e.getAttributeNS(d,"name"),g[k]||c.removeChild(e)),e=f;return c}function D(a){var b=N.rootElement.ownerDocument,c;if(a){v(a.documentElement);try{c=b.importNode(a.documentElement,!0)}catch(e){}}return c}function A(a){N.state=a;if(N.onchange)N.onchange(N);if( [...]
- function B(a){ka=null;N.rootElement=a;a.fontFaceDecls=g(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls");a.styles=g(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles");a.automaticStyles=g(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles");a.masterStyles=g(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles");a.body=g(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","body");a.meta=g(a,"urn:oasis:names:tc:opendocu [...]
- "meta")}function M(b){b=D(b);var c=N.rootElement;b&&"document-styles"===b.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===b.namespaceURI?(c.fontFaceDecls=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls"),f(c,c.fontFaceDecls),c.styles=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles"),f(c,c.styles),c.automaticStyles=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles"),y(c.automaticStyles,"document-styles"),f(c,c. [...]
- c.masterStyles=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles"),f(c,c.masterStyles),p.prefixStyleNames(c.automaticStyles,a,c.masterStyles)):A(q.INVALID)}function z(a){a=D(a);var b,c,e;if(a&&"document-content"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===a.namespaceURI){b=N.rootElement;c=g(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls");b.fontFaceDecls&&c?e=w(b.fontFaceDecls,c):c&&(b.fontFaceDecls=c,f(b,c));c=g(a,"urn: [...]
- "automatic-styles");y(c,"document-content");e&&p.changeFontFaceNames(c,e);if(b.automaticStyles&&c)for(e=c.firstChild;e;)b.automaticStyles.appendChild(e),e=c.firstChild;else c&&(b.automaticStyles=c,f(b,c));b.body=g(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","body");f(b,b.body)}else A(q.INVALID)}function K(a){a=D(a);var b;a&&"document-meta"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===a.namespaceURI&&(b=N.rootElement,b.meta=g(a,"urn:oasis:names:tc:opendocu [...]
- "meta"),f(b,b.meta),r=new odf.MetadataManager(b.meta))}function F(a){a=D(a);var b;a&&"document-settings"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===a.namespaceURI&&(b=N.rootElement,b.settings=g(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","settings"),f(b,b.settings))}function Q(a){a=D(a);var b;if(a&&"manifest"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"===a.namespaceURI)for(b=N.rootElement,b.manifest=a,a=b.manifest.firstChild;a;)a [...]
- Node.ELEMENT_NODE&&"file-entry"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"===a.namespaceURI&&(Z[a.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","full-path")]=a.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","media-type")),a=a.nextSibling}function $(a){var b=a.shift(),c,e;b?(c=b[0],e=b[1],O.loadAsDOM(c,function(b,c){e(c);b||N.state===q.INVALID||$(a)})):A(q.DONE)}function ia(a){var b="";odf.Namespaces.forEachPrefix(functi [...]
- " xmlns:"+a+'="'+c+'"'});return'<?xml version="1.0" encoding="UTF-8"?><office:'+a+" "+b+' office:version="1.2">'}function R(){var a=new xmldom.LSSerializer,b=ia("document-meta");a.filter=new odf.OdfNodeFilter;b+=a.writeToString(N.rootElement.meta,odf.Namespaces.namespaceMap);return b+"</office:document-meta>"}function ma(a,b){var c=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest:file-entry");c.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns: [...]
- "manifest:full-path",a);c.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest:media-type",b);return c}function ba(){var a=runtime.parseXML('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2"></manifest:manifest>'),b=g(a,"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest"),c=new xmldom.LSSerializer,e;for(e in Z)Z.hasOwnProperty(e)&&b.appendChild(ma(e,Z[e]));c.filter=new odf.OdfNodeFilter;retu [...]
- c.writeToString(a,odf.Namespaces.namespaceMap)}function ga(){var a=new xmldom.LSSerializer,b=ia("document-settings");a.filter=new odf.OdfNodeFilter;b+=a.writeToString(N.rootElement.settings,odf.Namespaces.namespaceMap);return b+"</office:document-settings>"}function S(){var b=odf.Namespaces.namespaceMap,e=new xmldom.LSSerializer,d,f,k,g=ia("document-styles");f=t(N.rootElement.automaticStyles,"document-styles");k=N.rootElement.masterStyles&&N.rootElement.masterStyles.cloneNode(!0);d=s(N. [...]
- [k,N.rootElement.styles,f]);p.removePrefixFromStyleNames(f,a,k);e.filter=new c(k,f);g+=e.writeToString(d,b);g+=e.writeToString(N.rootElement.styles,b);g+=e.writeToString(f,b);g+=e.writeToString(k,b);return g+"</office:document-styles>"}function Y(){var a=odf.Namespaces.namespaceMap,b=new xmldom.LSSerializer,c,e,d=ia("document-content");e=t(N.rootElement.automaticStyles,"document-content");c=s(N.rootElement.fontFaceDecls,[e]);b.filter=new m(N.rootElement.body,e);d+=b.writeToString(c,a);d [...]
- a);d+=b.writeToString(N.rootElement.body,a);return d+"</office:document-content>"}function V(a,b){runtime.loadXML(a,function(a,c){if(a)b(a);else{var e=D(c);e&&"document"===e.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===e.namespaceURI?(B(e),A(q.DONE)):A(q.INVALID)}})}function G(){function a(b,c){var d;c||(c=b);d=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0",c);e[b]=d;e.appendChild(d)}var b=new core.Zip("",null),c=runtime.byteArrayFromStrin [...]
- "utf8"),e=N.rootElement,d=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","text");b.save("mimetype",c,!1,new Date);a("meta");a("settings");a("scripts");a("fontFaceDecls","font-face-decls");a("styles");a("automaticStyles","automatic-styles");a("masterStyles","master-styles");a("body");e.body.appendChild(d);r=new odf.MetadataManager(e.meta);A(q.DONE);return b}function I(){var a,b=new Date,c=runtime.getWindow();a="WebODF/"+("undefined"!==String(typeof webodf_ver [...]
- "FromSource");c&&(a=a+" "+c.navigator.userAgent);r.setMetadata({"meta:generator":a});a=runtime.byteArrayFromString(ga(),"utf8");O.save("settings.xml",a,!0,b);a=runtime.byteArrayFromString(R(),"utf8");O.save("meta.xml",a,!0,b);a=runtime.byteArrayFromString(S(),"utf8");O.save("styles.xml",a,!0,b);a=runtime.byteArrayFromString(Y(),"utf8");O.save("content.xml",a,!0,b);a=runtime.byteArrayFromString(ba(),"utf8");O.save("META-INF/manifest.xml",a,!0,b)}function ha(a,b){I();O.writeAs(a,function( [...]
- var N=this,O,Z={},ka;this.onstatereadychange=l;this.rootElement=this.state=this.onchange=null;this.setRootElement=B;this.getContentElement=function(){var a;ka||(a=N.rootElement.body,ka=a.getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","text")[0]||a.getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","presentation")[0]||a.getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","spreadsheet")[0]);return ka};this.getDocument [...]
- N.getContentElement();return a&&a.localName};this.getMetadataManager=function(){return r};this.getPart=function(a){return new b(a,Z[a],N,O)};this.getPartData=function(a,b){O.load(a,b)};this.createByteArray=function(a,b){I();O.createByteArray(a,b)};this.saveAs=ha;this.save=function(a){ha(k,a)};this.getUrl=function(){return k};this.setBlob=function(a,b,c){c=e.convertBase64ToByteArray(c);O.save(a,c,!1,new Date);Z.hasOwnProperty(a)&&runtime.log(a+" has been overwritten.");Z[a]=b};this.remov [...]
- O.remove(a);runtime.assert(b,"file is not found: "+a);delete Z[a]};this.state=q.LOADING;this.rootElement=function(a){var b=document.createElementNS(a.namespaceURI,a.localName),c;a=new a;for(c in a)a.hasOwnProperty(c)&&(b[c]=a[c]);return b}(n);O=k?new core.Zip(k,function(a,b){O=b;a?V(k,function(b){a&&(O.error=a+"\n"+b,A(q.INVALID))}):$([["styles.xml",M],["content.xml",z],["meta.xml",K],["settings.xml",F],["META-INF/manifest.xml",Q]])}):G()};odf.OdfContainer.EMPTY=0;odf.OdfContainer.LOADI [...]
- 2;odf.OdfContainer.INVALID=3;odf.OdfContainer.SAVING=4;odf.OdfContainer.MODIFIED=5;odf.OdfContainer.getContainer=function(a){return new odf.OdfContainer(a,null)};return odf.OdfContainer}();
- // Input 36
++odf.OdfNodeFilter=function(){this.acceptNode=function(g){return"http://www.w3.org/1999/xhtml"===g.namespaceURI?NodeFilter.FILTER_SKIP:g.namespaceURI&&g.namespaceURI.match(/^urn:webodf:/)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}};
++// Input 31
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.Base64");runtime.loadClass("xmldom.XPath");runtime.loadClass("odf.OdfContainer");
- odf.FontLoader=function(){function g(l,f,n,b,p){var r,d=0,k;for(k in l)if(l.hasOwnProperty(k)){if(d===n){r=k;break}d+=1}r?f.getPartData(l[r].href,function(a,e){if(a)runtime.log(a);else if(e){var d="@font-face { font-family: '"+(l[r].family||r)+"'; src: url(data:application/x-font-ttf;charset=binary;base64,"+c.convertUTF8ArrayToBase64(e)+') format("truetype"); }';try{b.insertRule(d,b.cssRules.length)}catch(k){runtime.log("Problem inserting rule in CSS: "+runtime.toJson(k)+"\nRule: "+d)}} [...]
- l[r].href);g(l,f,n+1,b,p)}):p&&p()}var l=new xmldom.XPath,c=new core.Base64;odf.FontLoader=function(){this.loadFonts=function(c,f){for(var n=c.rootElement.fontFaceDecls;f.cssRules.length;)f.deleteRule(f.cssRules.length-1);if(n){var b={},p,r,d,k;if(n)for(n=l.getODFElementsWithXPath(n,"style:font-face[svg:font-face-src]",odf.Namespaces.resolvePrefix),p=0;p<n.length;p+=1)r=n[p],d=r.getAttributeNS(odf.Namespaces.stylens,"name"),k=r.getAttributeNS(odf.Namespaces.svgns,"font-family"),r=l.getO [...]
- "svg:font-face-src/svg:font-face-uri",odf.Namespaces.resolvePrefix),0<r.length&&(r=r[0].getAttributeNS(odf.Namespaces.xlinkns,"href"),b[d]={href:r,family:k});g(b,c,0,f)}}};return odf.FontLoader}();
- // Input 37
++runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.OdfUtils");runtime.loadClass("xmldom.XPath");runtime.loadClass("core.CSSUnits");odf.StyleTreeNode=function(g){this.derivedStyles={};this.element=g};
++odf.Style2CSS=function(){function g(a){var c,b,d,f={};if(!a)return f;for(a=a.firstElementChild;a;){if(b=a.namespaceURI!==l||"style"!==a.localName&&"default-style"!==a.localName?a.namespaceURI===w&&"list-style"===a.localName?"list":a.namespaceURI!==l||"page-layout"!==a.localName&&"default-page-layout"!==a.localName?void 0:"page":a.getAttributeNS(l,"family"))(c=a.getAttributeNS(l,"name"))||(c=""),f.hasOwnProperty(b)?d=f[b]:f[b]=d={},d[c]=a;a=a.nextElementSibling}return f}function k(a,c){i [...]
++var b,d=null;for(b in a)if(a.hasOwnProperty(b)&&(d=k(a[b].derivedStyles,c)))break;return d}function e(a,c,b){var d,f,h;if(!c.hasOwnProperty(a))return null;d=new odf.StyleTreeNode(c[a]);f=d.element.getAttributeNS(l,"parent-style-name");h=null;f&&(h=k(b,f)||e(f,c,b));h?h.derivedStyles[a]=d:b[a]=d;delete c[a];return d}function n(a,c){for(var b in a)a.hasOwnProperty(b)&&e(b,a,c)}function m(a,c,b){var d=[];b=b.derivedStyles;var f;var e=t[a],l;void 0===e?c=null:(l=c?"["+e+'|style-name="'+c+'" [...]
++e&&(e="draw",l=c?'[presentation|style-name="'+c+'"]':""),c=e+"|"+s[a].join(l+","+e+"|")+l);null!==c&&d.push(c);for(f in b)b.hasOwnProperty(f)&&(c=m(a,f,b[f]),d=d.concat(c));return d}function q(a,c,b){for(a=a&&a.firstElementChild;a&&(a.namespaceURI!==c||a.localName!==b);)a=a.nextElementSibling;return a}function b(a,c){var b="",d,f,e;for(d=0;d<c.length;d+=1)if(f=c[d],e=a.getAttributeNS(f[0],f[1])){e=e.trim();if(G.hasOwnProperty(f[1])){var l=e.indexOf(" "),h=void 0,p=void 0;-1!==l?(h=e.sub [...]
++p=e.substring(l)):(h=e,p="");(h=O.parseLength(h))&&"pt"===h.unit&&0.75>h.value&&(e="0.75pt"+p)}f[2]&&(b+=f[2]+":"+e+";")}return b}function h(a){return(a=q(a,l,"text-properties"))?O.parseFoFontSize(a.getAttributeNS(c,"font-size")):null}function r(a,c,b,d){return c+c+b+b+d+d}function d(a,b,d,f){b='text|list[text|style-name="'+b+'"]';var e=d.getAttributeNS(w,"level");d=q(d,l,"list-level-properties");d=q(d,l,"list-level-label-alignment");var h,p;d&&(h=d.getAttributeNS(c,"text-indent"),p=d.g [...]
++"margin-left"));h||(h="-0.6cm");d="-"===h.charAt(0)?h.substring(1):"-"+h;for(e=e&&parseInt(e,10);1<e;)b+=" > text|list-item > text|list",e-=1;if(p){e=b+" > text|list-item > *:not(text|list):first-child";e+="{";e=e+("margin-left:"+p+";")+"}";try{a.insertRule(e,a.cssRules.length)}catch(g){runtime.log("cannot load rule: "+e)}}f=b+" > text|list-item > *:not(text|list):first-child:before{"+f+";";f=f+"counter-increment:list;"+("margin-left:"+h+";");f+="width:"+d+";";f+="display:inline-block}" [...]
++a.cssRules.length)}catch(m){runtime.log("cannot load rule: "+f)}}function f(e,g,k,n){if("list"===g)for(var u=n.element.firstChild,s,t;u;){if(u.namespaceURI===w)if(s=u,"list-level-style-number"===u.localName){var G=s;t=G.getAttributeNS(l,"num-format");var T=G.getAttributeNS(l,"num-suffix")||"",G=G.getAttributeNS(l,"num-prefix")||"",$={1:"decimal",a:"lower-latin",A:"upper-latin",i:"lower-roman",I:"upper-roman"},W="";G&&(W+=' "'+G+'"');W=$.hasOwnProperty(t)?W+(" counter(list, "+$[t]+")"):t [...]
++'"'):W+" ''";t="content:"+W+' "'+T+'"';d(e,k,s,t)}else"list-level-style-image"===u.localName?(t="content: none;",d(e,k,s,t)):"list-level-style-bullet"===u.localName&&(t="content: '"+s.getAttributeNS(w,"bullet-char")+"';",d(e,k,s,t));u=u.nextSibling}else if("page"===g){if(t=n.element,G=T=k="",u=q(t,l,"page-layout-properties"))if(s=t.getAttributeNS(l,"name"),k+=b(u,ja),(T=q(u,l,"background-image"))&&(G=T.getAttributeNS(y,"href"))&&(k=k+("background-image: url('odfkit:"+G+"');")+b(T,z)),"p [...]
++ba)for(t=(t=q(t.parentNode.parentElement,p,"master-styles"))&&t.firstElementChild;t;){if(t.namespaceURI===l&&"master-page"===t.localName&&t.getAttributeNS(l,"page-layout-name")===s){G=t.getAttributeNS(l,"name");T="draw|page[draw|master-page-name="+G+"] {"+k+"}";G="office|body, draw|page[draw|master-page-name="+G+"] {"+b(u,ka)+" }";try{e.insertRule(T,e.cssRules.length),e.insertRule(G,e.cssRules.length)}catch(da){throw da;}}t=t.nextElementSibling}else if("text"===ba){T="office|text {"+k+" [...]
++u.getAttributeNS(c,"page-width")+";}";try{e.insertRule(T,e.cssRules.length),e.insertRule(G,e.cssRules.length)}catch(S){throw S;}}}else{k=m(g,k,n).join(",");u="";if(s=q(n.element,l,"text-properties")){G=s;t=W="";T=1;s=""+b(G,N);$=G.getAttributeNS(l,"text-underline-style");"solid"===$&&(W+=" underline");$=G.getAttributeNS(l,"text-line-through-style");"solid"===$&&(W+=" line-through");W.length&&(s+="text-decoration:"+W+";");if(W=G.getAttributeNS(l,"font-name")||G.getAttributeNS(c,"font-fam [...]
++s+="font-family: "+($||W)+";";$=G.parentElement;if(G=h($)){for(;$;){if(G=h($)){if("%"!==G.unit){t="font-size: "+G.value*T+G.unit+";";break}T*=G.value/100}G=$;W=$="";$=null;"default-style"===G.localName?$=null:($=G.getAttributeNS(l,"parent-style-name"),W=G.getAttributeNS(l,"family"),$=C.getODFElementsWithXPath(K,$?"//style:*[@style:name='"+$+"'][@style:family='"+W+"']":"//style:default-style[@style:family='"+W+"']",odf.Namespaces.lookupNamespaceURI)[0])}t||(t="font-size: "+parseFloat(I)* [...]
++";");s+=t}u+=s}if(s=q(n.element,l,"paragraph-properties"))t=s,s=""+b(t,x),(T=q(t,l,"background-image"))&&(G=T.getAttributeNS(y,"href"))&&(s=s+("background-image: url('odfkit:"+G+"');")+b(T,z)),(t=t.getAttributeNS(c,"line-height"))&&"normal"!==t&&(t=O.parseFoLineHeight(t),s="%"!==t.unit?s+("line-height: "+t.value+t.unit+";"):s+("line-height: "+t.value/100+";")),u+=s;if(s=q(n.element,l,"graphic-properties"))G=s,s=""+b(G,R),t=G.getAttributeNS(a,"opacity"),T=G.getAttributeNS(a,"fill"),G=G.g [...]
++"fill-color"),"solid"===T||"hatch"===T?G&&"none"!==G?(t=isNaN(parseFloat(t))?1:parseFloat(t)/100,T=G.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i,r),(G=(T=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(T))?{r:parseInt(T[1],16),g:parseInt(T[2],16),b:parseInt(T[3],16)}:null)&&(s+="background-color: rgba("+G.r+","+G.g+","+G.b+","+t+");")):s+="background: none;":"none"===T&&(s+="background: none;"),u+=s;if(s=q(n.element,l,"drawing-page-properties"))t=""+b(s,R),"true"===s.getAttributeNS(v,"b [...]
++(t+="background: none;"),u+=t;if(s=q(n.element,l,"table-cell-properties"))s=""+b(s,F),u+=s;if(s=q(n.element,l,"table-row-properties"))s=""+b(s,P),u+=s;if(s=q(n.element,l,"table-column-properties"))s=""+b(s,U),u+=s;if(s=q(n.element,l,"table-properties"))t=s,s=""+b(t,A),t=t.getAttributeNS(B,"border-model"),"collapsing"===t?s+="border-collapse:collapse;":"separating"===t&&(s+="border-collapse:separate;"),u+=s;if(0!==u.length)try{e.insertRule(k+"{"+u+"}",e.cssRules.length)}catch(ga){throw g [...]
++f(e,g,D,n.derivedStyles[D])}var a=odf.Namespaces.drawns,c=odf.Namespaces.fons,p=odf.Namespaces.officens,l=odf.Namespaces.stylens,u=odf.Namespaces.svgns,B=odf.Namespaces.tablens,w=odf.Namespaces.textns,y=odf.Namespaces.xlinkns,v=odf.Namespaces.presentationns,t={graphic:"draw","drawing-page":"draw",paragraph:"text",presentation:"presentation",ruby:"text",section:"text",table:"table","table-cell":"table","table-column":"table","table-row":"table",text:"text",list:"text",page:"office"},s={g [...]
++paragraph:"alphabetical-index-entry-template h illustration-index-entry-template index-source-style object-index-entry-template p table-index-entry-template table-of-content-entry-template user-index-entry-template".split(" "),presentation:"caption circle connector control custom-shape ellipse frame g line measure page-thumbnail path polygon polyline rect regular-polygon".split(" "),"drawing-page":"caption circle connector control page custom-shape ellipse frame g line measure page-thum [...]
++ruby:["ruby","ruby-text"],section:"alphabetical-index bibliography illustration-index index-title object-index section table-of-content table-index user-index".split(" "),table:["background","table"],"table-cell":"body covered-table-cell even-columns even-rows first-column first-row last-column last-row odd-columns odd-rows table-cell".split(" "),"table-column":["table-column"],"table-row":["table-row"],text:"a index-entry-chapter index-entry-link-end index-entry-link-start index-entry- [...]
++list:["list-item"]},N=[[c,"color","color"],[c,"background-color","background-color"],[c,"font-weight","font-weight"],[c,"font-style","font-style"]],z=[[l,"repeat","background-repeat"]],x=[[c,"background-color","background-color"],[c,"text-align","text-align"],[c,"text-indent","text-indent"],[c,"padding","padding"],[c,"padding-left","padding-left"],[c,"padding-right","padding-right"],[c,"padding-top","padding-top"],[c,"padding-bottom","padding-bottom"],[c,"border-left","border-left"],[c, [...]
++"border-right"],[c,"border-top","border-top"],[c,"border-bottom","border-bottom"],[c,"margin","margin"],[c,"margin-left","margin-left"],[c,"margin-right","margin-right"],[c,"margin-top","margin-top"],[c,"margin-bottom","margin-bottom"],[c,"border","border"]],R=[[c,"background-color","background-color"],[c,"min-height","min-height"],[a,"stroke","border"],[u,"stroke-color","border-color"],[u,"stroke-width","border-width"],[c,"border","border"],[c,"border-left","border-left"],[c,"border-ri [...]
++[c,"border-top","border-top"],[c,"border-bottom","border-bottom"]],F=[[c,"background-color","background-color"],[c,"border-left","border-left"],[c,"border-right","border-right"],[c,"border-top","border-top"],[c,"border-bottom","border-bottom"],[c,"border","border"]],U=[[l,"column-width","width"]],P=[[l,"row-height","height"],[c,"keep-together",null]],A=[[l,"width","width"],[c,"margin-left","margin-left"],[c,"margin-right","margin-right"],[c,"margin-top","margin-top"],[c,"margin-bottom", [...]
++ja=[[c,"background-color","background-color"],[c,"padding","padding"],[c,"padding-left","padding-left"],[c,"padding-right","padding-right"],[c,"padding-top","padding-top"],[c,"padding-bottom","padding-bottom"],[c,"border","border"],[c,"border-left","border-left"],[c,"border-right","border-right"],[c,"border-top","border-top"],[c,"border-bottom","border-bottom"],[c,"margin","margin"],[c,"margin-left","margin-left"],[c,"margin-right","margin-right"],[c,"margin-top","margin-top"],[c,"margi [...]
++"margin-bottom"]],ka=[[c,"page-width","width"],[c,"page-height","height"]],G={border:!0,"border-left":!0,"border-right":!0,"border-top":!0,"border-bottom":!0,"stroke-width":!0},Z={},O=new odf.OdfUtils,ba,K,I,C=xmldom.XPath,Y=new core.CSSUnits;this.style2css=function(a,c,b,d,e){for(var l,h,p,k;c.cssRules.length;)c.deleteRule(c.cssRules.length-1);l=null;d&&(l=d.ownerDocument,K=d.parentNode);e&&(l=e.ownerDocument,K=e.parentNode);if(l)for(k in odf.Namespaces.forEachPrefix(function(a,b){h="@ [...]
++a+" url("+b+");";try{c.insertRule(h,c.cssRules.length)}catch(d){}}),Z=b,ba=a,I=runtime.getWindow().getComputedStyle(document.body,null).getPropertyValue("font-size")||"12pt",a=g(d),d=g(e),e={},t)if(t.hasOwnProperty(k))for(p in b=e[k]={},n(a[k],b),n(d[k],b),b)b.hasOwnProperty(p)&&f(c,k,p,b[p])}};
++// Input 32
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.DomUtils");runtime.loadClass("core.Utils");
- odf.ObjectNameGenerator=function(g,l){function c(a,b){var c={};this.generateName=function(){var e=b(),d=0,h;do h=a+d,d+=1;while(c[h]||e[h]);c[h]=!0;return h}}function m(){var a,b={};[g.rootElement.automaticStyles,g.rootElement.styles].forEach(function(c){for(a=c.firstChild;a;)a.nodeType===Node.ELEMENT_NODE&&a.namespaceURI===f&&"style"===a.localName&&(b[a.getAttributeNS(f,"name")]=!0),a=a.nextSibling});return b}var f=odf.Namespaces.stylens,n=odf.Namespaces.drawns,b=odf.Namespaces.xlinkns [...]
- r=(new core.Utils).hashString(l),d=null,k=null,a=null,e={},h={};this.generateStyleName=function(){null===d&&(d=new c("auto"+r+"_",function(){return m()}));return d.generateName()};this.generateFrameName=function(){null===k&&(p.getElementsByTagNameNS(g.rootElement.body,n,"frame").forEach(function(a){e[a.getAttributeNS(n,"name")]=!0}),k=new c("fr"+r+"_",function(){return e}));return k.generateName()};this.generateImageName=function(){null===a&&(p.getElementsByTagNameNS(g.rootElement.body, [...]
- a.getAttributeNS(b,"href");a=a.substring(9,a.lastIndexOf("."));h[a]=!0}),a=new c("img"+r+"_",function(){return h}));return a.generateName()}};
- // Input 38
++runtime.loadClass("xmldom.XPath");runtime.loadClass("odf.Namespaces");
++odf.StyleInfo=function(){function g(a,c){var b,d,f,e,l,h=0;if(b=x[a.localName])if(f=b[a.namespaceURI])h=f.length;for(b=0;b<h;b+=1)d=f[b],e=d.ns,l=d.localname,(d=a.getAttributeNS(e,l))&&a.setAttributeNS(e,N[e]+l,c+d);for(f=a.firstElementChild;f;)g(f,c),f=f.nextElementSibling}function k(a,c){var b,d,f,e,l,h=0;if(b=x[a.localName])if(f=b[a.namespaceURI])h=f.length;for(b=0;b<h;b+=1)if(d=f[b],e=d.ns,l=d.localname,d=a.getAttributeNS(e,l))d=d.replace(c,""),a.setAttributeNS(e,N[e]+l,d);for(f=a.f [...]
++c),f=f.nextElementSibling}function e(a,c){var b,d,f,e,l,h=0;if(b=x[a.localName])if(f=b[a.namespaceURI])h=f.length;for(b=0;b<h;b+=1)if(e=f[b],d=e.ns,l=e.localname,d=a.getAttributeNS(d,l))c=c||{},e=e.keyname,c.hasOwnProperty(e)?c[e][d]=1:(l={},l[d]=1,c[e]=l);return c}function n(a,c){var b,d;e(a,c);for(b=a.firstChild;b;)b.nodeType===Node.ELEMENT_NODE&&(d=b,n(d,c)),b=b.nextSibling}function m(a,c,b){this.key=a;this.name=c;this.family=b;this.requires={}}function q(a,c,b){var d=a+'"'+c,f=b[d]; [...]
++new m(d,a,c));return f}function b(a,c,d){var f,e,l,h,p,g=0;f=a.getAttributeNS(v,"name");h=a.getAttributeNS(v,"family");f&&h&&(c=q(f,h,d));if(c){if(f=x[a.localName])if(l=f[a.namespaceURI])g=l.length;for(f=0;f<g;f+=1)if(h=l[f],e=h.ns,p=h.localname,e=a.getAttributeNS(e,p))h=h.keyname,h=q(e,h,d),c.requires[h.key]=h}for(a=a.firstElementChild;a;)b(a,c,d),a=a.nextElementSibling;return d}function h(a,c){var b=c[a.family];b||(b=c[a.family]={});b[a.name]=1;Object.keys(a.requires).forEach(function [...]
++c)})}function r(a,c){var d=b(a,null,{});Object.keys(d).forEach(function(a){a=d[a];var b=c[a.family];b&&b.hasOwnProperty(a.name)&&h(a,c)})}function d(a,c){function b(c){(c=h.getAttributeNS(v,c))&&(a[c]=!0)}var f=["font-name","font-name-asian","font-name-complex"],e,h;for(e=c&&c.firstElementChild;e;)h=e,f.forEach(b),d(a,h),e=e.nextElementSibling}function f(a,c){function b(a){var d=h.getAttributeNS(v,a);d&&c.hasOwnProperty(d)&&h.setAttributeNS(v,"style:"+a,c[d])}var d=["font-name","font-na [...]
++"font-name-complex"],e,h;for(e=a&&a.firstElementChild;e;)h=e,d.forEach(b),f(h,c),e=e.nextElementSibling}var a=odf.Namespaces.chartns,c=odf.Namespaces.dbns,p=odf.Namespaces.dr3dns,l=odf.Namespaces.drawns,u=odf.Namespaces.formns,B=odf.Namespaces.numberns,w=odf.Namespaces.officens,y=odf.Namespaces.presentationns,v=odf.Namespaces.stylens,t=odf.Namespaces.tablens,s=odf.Namespaces.textns,N={"urn:oasis:names:tc:opendocument:xmlns:chart:1.0":"chart:","urn:oasis:names:tc:opendocument:xmlns:datab [...]
++"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0":"dr3d:","urn:oasis:names:tc:opendocument:xmlns:drawing:1.0":"draw:","urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0":"fo:","urn:oasis:names:tc:opendocument:xmlns:form:1.0":"form:","urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0":"number:","urn:oasis:names:tc:opendocument:xmlns:office:1.0":"office:","urn:oasis:names:tc:opendocument:xmlns:presentation:1.0":"presentation:","urn:oasis:names:tc:opendocument:xmlns:style:1.0":" [...]
++"urn:oasis:names:tc:opendocument:xmlns:table:1.0":"table:","urn:oasis:names:tc:opendocument:xmlns:text:1.0":"chart:","http://www.w3.org/XML/1998/namespace":"xml:"},z={text:[{ens:v,en:"tab-stop",ans:v,a:"leader-text-style"},{ens:v,en:"drop-cap",ans:v,a:"style-name"},{ens:s,en:"notes-configuration",ans:s,a:"citation-body-style-name"},{ens:s,en:"notes-configuration",ans:s,a:"citation-style-name"},{ens:s,en:"a",ans:s,a:"style-name"},{ens:s,en:"alphabetical-index",ans:s,a:"style-name"},{ens: [...]
++ans:s,a:"style-name"},{ens:s,en:"list-level-style-number",ans:s,a:"style-name"},{ens:s,en:"ruby-text",ans:s,a:"style-name"},{ens:s,en:"span",ans:s,a:"style-name"},{ens:s,en:"a",ans:s,a:"visited-style-name"},{ens:v,en:"text-properties",ans:v,a:"text-line-through-text-style"},{ens:s,en:"alphabetical-index-source",ans:s,a:"main-entry-style-name"},{ens:s,en:"index-entry-bibliography",ans:s,a:"style-name"},{ens:s,en:"index-entry-chapter",ans:s,a:"style-name"},{ens:s,en:"index-entry-link-end" [...]
++{ens:s,en:"index-entry-link-start",ans:s,a:"style-name"},{ens:s,en:"index-entry-page-number",ans:s,a:"style-name"},{ens:s,en:"index-entry-span",ans:s,a:"style-name"},{ens:s,en:"index-entry-tab-stop",ans:s,a:"style-name"},{ens:s,en:"index-entry-text",ans:s,a:"style-name"},{ens:s,en:"index-title-template",ans:s,a:"style-name"},{ens:s,en:"list-level-style-bullet",ans:s,a:"style-name"},{ens:s,en:"outline-level-style",ans:s,a:"style-name"}],paragraph:[{ens:l,en:"caption",ans:l,a:"text-style- [...]
++en:"circle",ans:l,a:"text-style-name"},{ens:l,en:"connector",ans:l,a:"text-style-name"},{ens:l,en:"control",ans:l,a:"text-style-name"},{ens:l,en:"custom-shape",ans:l,a:"text-style-name"},{ens:l,en:"ellipse",ans:l,a:"text-style-name"},{ens:l,en:"frame",ans:l,a:"text-style-name"},{ens:l,en:"line",ans:l,a:"text-style-name"},{ens:l,en:"measure",ans:l,a:"text-style-name"},{ens:l,en:"path",ans:l,a:"text-style-name"},{ens:l,en:"polygon",ans:l,a:"text-style-name"},{ens:l,en:"polyline",ans:l,a:" [...]
++{ens:l,en:"rect",ans:l,a:"text-style-name"},{ens:l,en:"regular-polygon",ans:l,a:"text-style-name"},{ens:w,en:"annotation",ans:l,a:"text-style-name"},{ens:u,en:"column",ans:u,a:"text-style-name"},{ens:v,en:"style",ans:v,a:"next-style-name"},{ens:t,en:"body",ans:t,a:"paragraph-style-name"},{ens:t,en:"even-columns",ans:t,a:"paragraph-style-name"},{ens:t,en:"even-rows",ans:t,a:"paragraph-style-name"},{ens:t,en:"first-column",ans:t,a:"paragraph-style-name"},{ens:t,en:"first-row",ans:t,a:"par [...]
++{ens:t,en:"last-column",ans:t,a:"paragraph-style-name"},{ens:t,en:"last-row",ans:t,a:"paragraph-style-name"},{ens:t,en:"odd-columns",ans:t,a:"paragraph-style-name"},{ens:t,en:"odd-rows",ans:t,a:"paragraph-style-name"},{ens:s,en:"notes-configuration",ans:s,a:"default-style-name"},{ens:s,en:"alphabetical-index-entry-template",ans:s,a:"style-name"},{ens:s,en:"bibliography-entry-template",ans:s,a:"style-name"},{ens:s,en:"h",ans:s,a:"style-name"},{ens:s,en:"illustration-index-entry-template" [...]
++{ens:s,en:"index-source-style",ans:s,a:"style-name"},{ens:s,en:"object-index-entry-template",ans:s,a:"style-name"},{ens:s,en:"p",ans:s,a:"style-name"},{ens:s,en:"table-index-entry-template",ans:s,a:"style-name"},{ens:s,en:"table-of-content-entry-template",ans:s,a:"style-name"},{ens:s,en:"table-index-entry-template",ans:s,a:"style-name"},{ens:s,en:"user-index-entry-template",ans:s,a:"style-name"},{ens:v,en:"page-layout-properties",ans:v,a:"register-truth-ref-style-name"}],chart:[{ens:a,e [...]
++a:"style-name"},{ens:a,en:"chart",ans:a,a:"style-name"},{ens:a,en:"data-label",ans:a,a:"style-name"},{ens:a,en:"data-point",ans:a,a:"style-name"},{ens:a,en:"equation",ans:a,a:"style-name"},{ens:a,en:"error-indicator",ans:a,a:"style-name"},{ens:a,en:"floor",ans:a,a:"style-name"},{ens:a,en:"footer",ans:a,a:"style-name"},{ens:a,en:"grid",ans:a,a:"style-name"},{ens:a,en:"legend",ans:a,a:"style-name"},{ens:a,en:"mean-value",ans:a,a:"style-name"},{ens:a,en:"plot-area",ans:a,a:"style-name"},{e [...]
++ans:a,a:"style-name"},{ens:a,en:"series",ans:a,a:"style-name"},{ens:a,en:"stock-gain-marker",ans:a,a:"style-name"},{ens:a,en:"stock-loss-marker",ans:a,a:"style-name"},{ens:a,en:"stock-range-line",ans:a,a:"style-name"},{ens:a,en:"subtitle",ans:a,a:"style-name"},{ens:a,en:"title",ans:a,a:"style-name"},{ens:a,en:"wall",ans:a,a:"style-name"}],section:[{ens:s,en:"alphabetical-index",ans:s,a:"style-name"},{ens:s,en:"bibliography",ans:s,a:"style-name"},{ens:s,en:"illustration-index",ans:s,a:"s [...]
++{ens:s,en:"index-title",ans:s,a:"style-name"},{ens:s,en:"object-index",ans:s,a:"style-name"},{ens:s,en:"section",ans:s,a:"style-name"},{ens:s,en:"table-of-content",ans:s,a:"style-name"},{ens:s,en:"table-index",ans:s,a:"style-name"},{ens:s,en:"user-index",ans:s,a:"style-name"}],ruby:[{ens:s,en:"ruby",ans:s,a:"style-name"}],table:[{ens:c,en:"query",ans:c,a:"style-name"},{ens:c,en:"table-representation",ans:c,a:"style-name"},{ens:t,en:"background",ans:t,a:"style-name"},{ens:t,en:"table",an [...]
++"table-column":[{ens:c,en:"column",ans:c,a:"style-name"},{ens:t,en:"table-column",ans:t,a:"style-name"}],"table-row":[{ens:c,en:"query",ans:c,a:"default-row-style-name"},{ens:c,en:"table-representation",ans:c,a:"default-row-style-name"},{ens:t,en:"table-row",ans:t,a:"style-name"}],"table-cell":[{ens:c,en:"column",ans:c,a:"default-cell-style-name"},{ens:t,en:"table-column",ans:t,a:"default-cell-style-name"},{ens:t,en:"table-row",ans:t,a:"default-cell-style-name"},{ens:t,en:"body",ans:t,a [...]
++{ens:t,en:"covered-table-cell",ans:t,a:"style-name"},{ens:t,en:"even-columns",ans:t,a:"style-name"},{ens:t,en:"covered-table-cell",ans:t,a:"style-name"},{ens:t,en:"even-columns",ans:t,a:"style-name"},{ens:t,en:"even-rows",ans:t,a:"style-name"},{ens:t,en:"first-column",ans:t,a:"style-name"},{ens:t,en:"first-row",ans:t,a:"style-name"},{ens:t,en:"last-column",ans:t,a:"style-name"},{ens:t,en:"last-row",ans:t,a:"style-name"},{ens:t,en:"odd-columns",ans:t,a:"style-name"},{ens:t,en:"odd-rows", [...]
++{ens:t,en:"table-cell",ans:t,a:"style-name"}],graphic:[{ens:p,en:"cube",ans:l,a:"style-name"},{ens:p,en:"extrude",ans:l,a:"style-name"},{ens:p,en:"rotate",ans:l,a:"style-name"},{ens:p,en:"scene",ans:l,a:"style-name"},{ens:p,en:"sphere",ans:l,a:"style-name"},{ens:l,en:"caption",ans:l,a:"style-name"},{ens:l,en:"circle",ans:l,a:"style-name"},{ens:l,en:"connector",ans:l,a:"style-name"},{ens:l,en:"control",ans:l,a:"style-name"},{ens:l,en:"custom-shape",ans:l,a:"style-name"},{ens:l,en:"ellips [...]
++{ens:l,en:"frame",ans:l,a:"style-name"},{ens:l,en:"g",ans:l,a:"style-name"},{ens:l,en:"line",ans:l,a:"style-name"},{ens:l,en:"measure",ans:l,a:"style-name"},{ens:l,en:"page-thumbnail",ans:l,a:"style-name"},{ens:l,en:"path",ans:l,a:"style-name"},{ens:l,en:"polygon",ans:l,a:"style-name"},{ens:l,en:"polyline",ans:l,a:"style-name"},{ens:l,en:"rect",ans:l,a:"style-name"},{ens:l,en:"regular-polygon",ans:l,a:"style-name"},{ens:w,en:"annotation",ans:l,a:"style-name"}],presentation:[{ens:p,en:"c [...]
++a:"style-name"},{ens:p,en:"extrude",ans:y,a:"style-name"},{ens:p,en:"rotate",ans:y,a:"style-name"},{ens:p,en:"scene",ans:y,a:"style-name"},{ens:p,en:"sphere",ans:y,a:"style-name"},{ens:l,en:"caption",ans:y,a:"style-name"},{ens:l,en:"circle",ans:y,a:"style-name"},{ens:l,en:"connector",ans:y,a:"style-name"},{ens:l,en:"control",ans:y,a:"style-name"},{ens:l,en:"custom-shape",ans:y,a:"style-name"},{ens:l,en:"ellipse",ans:y,a:"style-name"},{ens:l,en:"frame",ans:y,a:"style-name"},{ens:l,en:"g" [...]
++{ens:l,en:"line",ans:y,a:"style-name"},{ens:l,en:"measure",ans:y,a:"style-name"},{ens:l,en:"page-thumbnail",ans:y,a:"style-name"},{ens:l,en:"path",ans:y,a:"style-name"},{ens:l,en:"polygon",ans:y,a:"style-name"},{ens:l,en:"polyline",ans:y,a:"style-name"},{ens:l,en:"rect",ans:y,a:"style-name"},{ens:l,en:"regular-polygon",ans:y,a:"style-name"},{ens:w,en:"annotation",ans:y,a:"style-name"}],"drawing-page":[{ens:l,en:"page",ans:l,a:"style-name"},{ens:y,en:"notes",ans:l,a:"style-name"},{ens:v, [...]
++ans:l,a:"style-name"},{ens:v,en:"master-page",ans:l,a:"style-name"}],"list-style":[{ens:s,en:"list",ans:s,a:"style-name"},{ens:s,en:"numbered-paragraph",ans:s,a:"style-name"},{ens:s,en:"list-item",ans:s,a:"style-override"},{ens:v,en:"style",ans:v,a:"list-style-name"}],data:[{ens:v,en:"style",ans:v,a:"data-style-name"},{ens:v,en:"style",ans:v,a:"percentage-data-style-name"},{ens:y,en:"date-time-decl",ans:v,a:"data-style-name"},{ens:s,en:"creation-date",ans:v,a:"data-style-name"},{ens:s,e [...]
++ans:v,a:"data-style-name"},{ens:s,en:"database-display",ans:v,a:"data-style-name"},{ens:s,en:"date",ans:v,a:"data-style-name"},{ens:s,en:"editing-duration",ans:v,a:"data-style-name"},{ens:s,en:"expression",ans:v,a:"data-style-name"},{ens:s,en:"meta-field",ans:v,a:"data-style-name"},{ens:s,en:"modification-date",ans:v,a:"data-style-name"},{ens:s,en:"modification-time",ans:v,a:"data-style-name"},{ens:s,en:"print-date",ans:v,a:"data-style-name"},{ens:s,en:"print-time",ans:v,a:"data-style-n [...]
++en:"table-formula",ans:v,a:"data-style-name"},{ens:s,en:"time",ans:v,a:"data-style-name"},{ens:s,en:"user-defined",ans:v,a:"data-style-name"},{ens:s,en:"user-field-get",ans:v,a:"data-style-name"},{ens:s,en:"user-field-input",ans:v,a:"data-style-name"},{ens:s,en:"variable-get",ans:v,a:"data-style-name"},{ens:s,en:"variable-input",ans:v,a:"data-style-name"},{ens:s,en:"variable-set",ans:v,a:"data-style-name"}],"page-layout":[{ens:y,en:"notes",ans:v,a:"page-layout-name"},{ens:v,en:"handout- [...]
++a:"page-layout-name"},{ens:v,en:"master-page",ans:v,a:"page-layout-name"}]},x,R=xmldom.XPath;this.collectUsedFontFaces=d;this.changeFontFaceNames=f;this.UsedStyleList=function(a,c){var b={};this.uses=function(a){var c=a.localName,d=a.getAttributeNS(l,"name")||a.getAttributeNS(v,"name");a="style"===c?a.getAttributeNS(v,"family"):a.namespaceURI===B?"data":c;return(a=b[a])?0<a[d]:!1};n(a,b);c&&r(c,b)};this.hasDerivedStyles=function(a,c,b){var d=b.getAttributeNS(v,"name");b=b.getAttributeNS [...]
++return R.getODFElementsWithXPath(a,"//style:*[@style:parent-style-name='"+d+"'][@style:family='"+b+"']",c).length?!0:!1};this.prefixStyleNames=function(a,c,b){var d;if(a){for(d=a.firstChild;d;){if(d.nodeType===Node.ELEMENT_NODE){var f=d,e=c,h=f.getAttributeNS(l,"name"),p=void 0;h?p=l:(h=f.getAttributeNS(v,"name"))&&(p=v);p&&f.setAttributeNS(p,N[p]+"name",e+h)}d=d.nextSibling}g(a,c);b&&g(b,c)}};this.removePrefixFromStyleNames=function(a,c,b){var d=RegExp("^"+c);if(a){for(c=a.firstChild;c [...]
++Node.ELEMENT_NODE){var f=c,e=d,h=f.getAttributeNS(l,"name"),p=void 0;h?p=l:(h=f.getAttributeNS(v,"name"))&&(p=v);p&&(h=h.replace(e,""),f.setAttributeNS(p,N[p]+"name",h))}c=c.nextSibling}k(a,d);b&&k(b,d)}};this.determineStylesForNode=e;x=function(){var a,c,b,d,f,e={},h,l,p,g;for(b in z)if(z.hasOwnProperty(b))for(d=z[b],c=d.length,a=0;a<c;a+=1)f=d[a],p=f.en,g=f.ens,e.hasOwnProperty(p)?h=e[p]:e[p]=h={},h.hasOwnProperty(g)?l=h[g]:h[g]=l=[],l.push({ns:f.ans,localname:f.a,keyname:b});return e}()};
++// Input 33
+/*
+
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.Utils");runtime.loadClass("odf.ObjectNameGenerator");runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.OdfContainer");runtime.loadClass("odf.StyleInfo");runtime.loadClass("odf.OdfUtils");runtime.loadClass("odf.TextStyleApplicator");
- odf.Formatting=function(){function g(a){return(a=t[a])?w.mergeObjects({},a):null}function l(){for(var a=k.rootElement.fontFaceDecls,b={},c,d,a=a&&a.firstChild;a;)a.nodeType===Node.ELEMENT_NODE&&(c=a.getAttributeNS(h,"name"))&&((d=a.getAttributeNS(e,"font-family"))||a.getElementsByTagNameNS(e,"font-face-uri")[0])&&(b[c]=d),a=a.nextSibling;return b}function c(a){for(var b=k.rootElement.styles.firstChild;b;){if(b.nodeType===Node.ELEMENT_NODE&&b.namespaceURI===h&&"default-style"===b.localNa [...]
- "family")===a)return b;b=b.nextSibling}return null}function m(a,b,c){var e,d;c=c||[k.rootElement.automaticStyles,k.rootElement.styles];for(e=c.shift();e;){for(e=e.firstChild;e;){if(e.nodeType===Node.ELEMENT_NODE&&(d=e.getAttributeNS(h,"name"),e.namespaceURI===h&&"style"===e.localName&&e.getAttributeNS(h,"family")===b&&d===a||"list-style"===b&&e.namespaceURI===q&&"list-style"===e.localName&&d===a||"data"===b&&e.namespaceURI===u&&d===a))return e;e=e.nextSibling}e=c.shift()}return null}fun [...]
- c={},e=a.firstChild;e;){if(e.nodeType===Node.ELEMENT_NODE&&e.namespaceURI===h)for(c[e.nodeName]={},b=0;b<e.attributes.length;b+=1)c[e.nodeName][e.attributes[b].name]=e.attributes[b].value;e=e.nextSibling}for(b=0;b<a.attributes.length;b+=1)c[a.attributes[b].name]=a.attributes[b].value;return c}function n(a,b){for(var e=k.rootElement.styles,d,l={},p=a.getAttributeNS(h,"family"),n=a;n;)d=f(n),l=w.mergeObjects(d,l),n=(d=n.getAttributeNS(h,"parent-style-name"))?m(d,p,[e]):null;if(n=c(p))d=f( [...]
- l);b&&(d=g(p))&&(l=w.mergeObjects(d,l));return l}function b(b,c){for(var e=b.nodeType===Node.TEXT_NODE?b.parentNode:b,d,h=[],f="",k=!1;e;)!k&&v.isGroupingElement(e)&&(k=!0),(d=a.determineStylesForNode(e))&&h.push(d),e=e.parentNode;k&&(h.forEach(function(a){Object.keys(a).forEach(function(b){Object.keys(a[b]).forEach(function(a){f+="|"+b+":"+a+"|"})})}),c&&(c[f]=h));return k?h:void 0}function p(a){var b={orderedStyles:[]};a.forEach(function(a){Object.keys(a).forEach(function(c){var e=Obj [...]
- d,f;(d=m(e,c))?(f=n(d),b=w.mergeObjects(f,b),f=d.getAttributeNS(h,"display-name")):runtime.log("No style element found for '"+e+"' of family '"+c+"'");b.orderedStyles.push({name:e,family:c,displayName:f})})});return b}function r(a,b){var c=v.parseLength(a),e=b;if(c)switch(c.unit){case "cm":e=c.value;break;case "mm":e=0.1*c.value;break;case "in":e=2.54*c.value;break;case "pt":e=0.035277778*c.value;break;case "pc":case "px":case "em":break;default:runtime.log("Unit identifier: "+c.unit+" [...]
- var d=this,k,a=new odf.StyleInfo,e=odf.Namespaces.svgns,h=odf.Namespaces.stylens,q=odf.Namespaces.textns,u=odf.Namespaces.numberns,x=odf.Namespaces.fons,v=new odf.OdfUtils,y=new core.DomUtils,w=new core.Utils,t={paragraph:{"style:paragraph-properties":{"fo:text-align":"left"}}};this.getSystemDefaultStyleAttributes=g;this.setOdfContainer=function(a){k=a};this.getFontMap=l;this.getAvailableParagraphStyles=function(){for(var a=k.rootElement.styles&&k.rootElement.styles.firstChild,b,c,e=[]; [...]
- Node.ELEMENT_NODE&&"style"===a.localName&&a.namespaceURI===h&&(c=a,b=c.getAttributeNS(h,"family"),"paragraph"===b&&(b=c.getAttributeNS(h,"name"),c=c.getAttributeNS(h,"display-name")||b,b&&c&&e.push({name:b,displayName:c}))),a=a.nextSibling;return e};this.isStyleUsed=function(b){var c;c=a.hasDerivedStyles(k.rootElement,odf.Namespaces.resolvePrefix,b);b=(new a.UsedStyleList(k.rootElement.styles)).uses(b)||(new a.UsedStyleList(k.rootElement.automaticStyles)).uses(b)||(new a.UsedStyleList(k [...]
- return c||b};this.getDefaultStyleElement=c;this.getStyleElement=m;this.getStyleAttributes=f;this.getInheritedStyleAttributes=n;this.getFirstCommonParentStyleNameOrSelf=function(a){var b=k.rootElement.automaticStyles,c=k.rootElement.styles,e;for(e=m(a,"paragraph",[b]);e;)a=e.getAttributeNS(h,"parent-style-name"),e=m(a,"paragraph",[b]);return(e=m(a,"paragraph",[c]))?a:null};this.hasParagraphStyle=function(a){return Boolean(m(a,"paragraph"))};this.getAppliedStyles=function(a){var c={},e=[] [...]
- c)});Object.keys(c).forEach(function(a){e.push(p(c[a]))});return e};this.getAppliedStylesForElement=function(a){return(a=b(a))?p(a):void 0};this.applyStyle=function(a,b,c,e){(new odf.TextStyleApplicator(new odf.ObjectNameGenerator(k,a),d,k.rootElement.automaticStyles)).applyStyle(b,c,e)};this.updateStyle=function(a,b){var c,d;y.mapObjOntoNode(a,b,odf.Namespaces.resolvePrefix);(c=b["style:text-properties"]&&b["style:text-properties"]["style:font-name"])&&!l().hasOwnProperty(c)&&(d=a.owne [...]
- "style:font-face"),d.setAttributeNS(h,"style:name",c),d.setAttributeNS(e,"svg:font-family",c),k.rootElement.fontFaceDecls.appendChild(d))};this.createDerivedStyleObject=function(a,b,c){var e=m(a,b);runtime.assert(Boolean(e),"No style element found for '"+a+"' of family '"+b+"'");a=e.parentNode===k.rootElement.automaticStyles?f(e):{"style:parent-style-name":a};a["style:family"]=b;w.mergeObjects(a,c);return a};this.getDefaultTabStopDistance=function(){var a=c("paragraph");(a=(a=a&&a.getAt [...]
- "paragraph-properties"))&&a.getAttributeNS(h,"tab-stop-distance"))||(a="1.25cm");return v.parseNonNegativeLength(a)};this.getContentSize=function(a,b){var c,e,d,f,g,l,p,n,q,t,w,u;a:{c=m(a,b);var v,S,Y;runtime.assert("paragraph"===b||"table"===b,"styleFamily has to be either paragraph or table");if(c){v=c.getAttributeNS(h,"master-page-name")||"Standard";for(c=k.rootElement.masterStyles.lastChild;c&&c.previousSibling&&c.getAttributeNS(h,"name")!==v;)c=c.previousSibling;v=c.getAttributeNS( [...]
- S=y.getElementsByTagNameNS(k.rootElement.automaticStyles,h,"page-layout");for(Y=0;Y<S.length;Y+=1)if(c=S[Y],c.getAttributeNS(h,"name")===v)break a}c=null}c||(c=k.rootElement.styles.getElementsByTagNameNS(h,"default-page-layout")[0]);c&&(e=c.getElementsByTagNameNS(h,"page-layout-properties")[0]);e&&(d=e.getAttributeNS(h,"print-orientation")||"portrait","portrait"===d?(d=21.001,f=29.7):(d=29.7,f=21.001),d=r(e.getAttributeNS(x,"page-width"),d),f=r(e.getAttributeNS(x,"page-height"),f),g=r(e [...]
- "margin"),null),null===g?(g=r(e.getAttributeNS(x,"margin-left"),2),l=r(e.getAttributeNS(x,"margin-right"),2),p=r(e.getAttributeNS(x,"margin-top"),2),n=r(e.getAttributeNS(x,"margin-bottom"),2)):g=l=p=n=g,q=r(e.getAttributeNS(x,"padding"),null),null===q?(q=r(e.getAttributeNS(x,"padding-left"),0),t=r(e.getAttributeNS(x,"padding-right"),0),w=r(e.getAttributeNS(x,"padding-top"),0),u=r(e.getAttributeNS(x,"padding-bottom"),0)):q=t=w=u=q);return{width:d-g-l-q-t,height:f-p-n-w-u}}};
- // Input 39
++runtime.loadClass("odf.OdfUtils");
++odf.TextSerializer=function(){function g(n){var m="",q=k.filter?k.filter.acceptNode(n):NodeFilter.FILTER_ACCEPT,b=n.nodeType,h;if(q===NodeFilter.FILTER_ACCEPT||q===NodeFilter.FILTER_SKIP)for(h=n.firstChild;h;)m+=g(h),h=h.nextSibling;q===NodeFilter.FILTER_ACCEPT&&(b===Node.ELEMENT_NODE&&e.isParagraph(n)?m+="\n":b===Node.TEXT_NODE&&n.textContent&&(m+=n.textContent));return m}var k=this,e=new odf.OdfUtils;this.filter=null;this.writeToString=function(e){if(!e)return"";e=g(e);"\n"===e[e.leng [...]
++e.substr(0,e.length-1));return e}};
++// Input 34
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.DomUtils");runtime.loadClass("odf.OdfContainer");runtime.loadClass("odf.Formatting");runtime.loadClass("xmldom.XPath");runtime.loadClass("odf.FontLoader");runtime.loadClass("odf.Style2CSS");runtime.loadClass("odf.OdfUtils");runtime.loadClass("gui.AnnotationViewManager");
- odf.OdfCanvas=function(){function g(){function a(e){c=!0;runtime.setTimeout(function(){try{e()}catch(d){runtime.log(d)}c=!1;0<b.length&&a(b.pop())},10)}var b=[],c=!1;this.clearQueue=function(){b.length=0};this.addToQueue=function(e){if(0===b.length&&!c)return a(e);b.push(e)}}function l(a){function b(){for(;0<c.cssRules.length;)c.deleteRule(0);c.insertRule("#shadowContent draw|page {display:none;}",0);c.insertRule("office|presentation draw|page {display:none;}",1);c.insertRule("#shadowCo [...]
- e+") {display:block;}",2);c.insertRule("office|presentation draw|page:nth-of-type("+e+") {display:block;}",3)}var c=a.sheet,e=1;this.showFirstPage=function(){e=1;b()};this.showNextPage=function(){e+=1;b()};this.showPreviousPage=function(){1<e&&(e-=1,b())};this.showPage=function(a){0<a&&(e=a,b())};this.css=a;this.destroy=function(b){a.parentNode.removeChild(a);b()}}function c(a,b,c){a.addEventListener?a.addEventListener(b,c,!1):a.attachEvent?a.attachEvent("on"+b,c):a["on"+b]=c}function m [...]
- "on"+b;a.removeEventListener?a.removeEventListener(b,c,!1):a.detachEvent?a.detachEvent(e,c):a[e]===c&&(a[e]=null)}function f(a){function b(a,c){for(;c;){if(c===a)return!0;c=c.parentNode}return!1}function e(){var c=[],f=runtime.getWindow().getSelection(),k,g;for(k=0;k<f.rangeCount;k+=1)g=f.getRangeAt(k),null!==g&&b(a,g.startContainer)&&b(a,g.endContainer)&&c.push(g);if(c.length===d.length){for(f=0;f<c.length&&(k=c[f],g=d[f],k=k===g?!1:null===k||null===g?!0:k.startContainer!==g.startConta [...]
- g.startOffset||k.endContainer!==g.endContainer||k.endOffset!==g.endOffset,!k);f+=1);if(f===c.length)return}d=c;var f=[c.length],l,m=a.ownerDocument;for(k=0;k<c.length;k+=1)g=c[k],l=m.createRange(),l.setStart(g.startContainer,g.startOffset),l.setEnd(g.endContainer,g.endOffset),f[k]=l;d=f;f=h.length;for(c=0;c<f;c+=1)h[c](a,d)}var d=[],h=[];this.addListener=function(a,b){var c,e=h.length;for(c=0;c<e;c+=1)if(h[c]===b)return;h.push(b)};this.destroy=function(b){m(a,"mouseup",e);m(a,"keyup",e) [...]
- e);b()};c(a,"mouseup",e);c(a,"keyup",e);c(a,"keydown",e)}function n(a){for(;a.firstChild;)a.removeChild(a.firstChild)}function b(a,b,c){(new odf.Style2CSS).style2css(a.getDocumentType(),c.sheet,b.getFontMap(),a.rootElement.styles,a.rootElement.automaticStyles)}function p(a,b,c){var e=null;a=a.rootElement.body.getElementsByTagNameNS(F,c+"-decl");if((c=b.getAttributeNS(F,"use-"+c+"-name"))&&0<a.length)for(b=0;b<a.length;b+=1)if(a[b].getAttributeNS(F,"name")===c){e=a[b].textContent;break}r [...]
- b,c,e){var d=a.ownerDocument;b=a.getElementsByTagNameNS(b,c);for(a=0;a<b.length;a+=1)n(b[a]),e&&b[a].appendChild(d.createTextNode(e))}function d(a,b,c){b.setAttributeNS("urn:webodf:names:helper","styleid",a);var e,d=b.getAttributeNS(M,"anchor-type"),h=b.getAttributeNS(A,"x"),f=b.getAttributeNS(A,"y"),k=b.getAttributeNS(A,"width"),g=b.getAttributeNS(A,"height"),l=b.getAttributeNS(t,"min-height"),m=b.getAttributeNS(t,"min-width");if("as-char"===d)e="display: inline-block;";else if(d||h||f [...]
- else if(k||g||l||m)e="display: block;";h&&(e+="left: "+h+";");f&&(e+="top: "+f+";");k&&(e+="width: "+k+";");g&&(e+="height: "+g+";");l&&(e+="min-height: "+l+";");m&&(e+="min-width: "+m+";");e&&(e="draw|"+b.localName+'[webodfhelper|styleid="'+a+'"] {'+e+"}",c.insertRule(e,c.cssRules.length))}function k(a){for(a=a.firstChild;a;){if(a.namespaceURI===s&&"binary-data"===a.localName)return"data:image/png;base64,"+a.textContent.replace(/[\r\n\s]/g,"");a=a.nextSibling}return""}function a(a,b,c, [...]
- (b='draw|image[webodfhelper|styleid="'+a+'"] {'+("background-image: url("+b+");")+"}",e.insertRule(b,e.cssRules.length))}c.setAttributeNS("urn:webodf:names:helper","styleid",a);var h=c.getAttributeNS(z,"href"),f;if(h)try{f=b.getPart(h),f.onchange=function(a){d(a.url)},f.load()}catch(g){runtime.log("slight problem: "+g)}else h=k(c),d(h)}function e(a){function b(c){var e,d;c.hasAttributeNS(z,"href")&&(e=c.getAttributeNS(z,"href"),"#"===e[0]?(e=e.substring(1),d=function(){var b=$.getODFEle [...]
- "//text:bookmark-start[@text:name='"+e+"']",odf.Namespaces.resolvePrefix);0===b.length&&(b=$.getODFElementsWithXPath(a,"//text:bookmark[@text:name='"+e+"']",odf.Namespaces.resolvePrefix));0<b.length&&b[0].scrollIntoView(!0);return!1}):d=function(){Q.open(e)},c.onclick=d)}var c,e,d;e=a.getElementsByTagNameNS(M,"a");for(c=0;c<e.length;c+=1)d=e.item(c),b(d)}function h(a){var b=a.ownerDocument;R.getElementsByTagNameNS(a,M,"line-break").forEach(function(a){a.hasChildNodes()||a.appendChild(b. [...]
- function q(a){var b=a.ownerDocument;R.getElementsByTagNameNS(a,M,"s").forEach(function(a){for(var c,e;a.firstChild;)a.removeChild(a.firstChild);a.appendChild(b.createTextNode(" "));e=parseInt(a.getAttributeNS(M,"c"),10);if(1<e)for(a.removeAttributeNS(M,"c"),c=1;c<e;c+=1)a.parentNode.insertBefore(a.cloneNode(!0),a)})}function u(a){R.getElementsByTagNameNS(a,M,"tab").forEach(function(a){a.textContent="\t"})}function x(a,b){function c(a,h){var k=f.documentElement.namespaceURI;"video/"===h. [...]
- (e=f.createElementNS(k,"video"),e.setAttribute("controls","controls"),d=f.createElementNS(k,"source"),d.setAttribute("src",a),d.setAttribute("type",h),e.appendChild(d),b.parentNode.appendChild(e)):b.innerHtml="Unrecognised Plugin"}var e,d,h,f=b.ownerDocument,g;if(h=b.getAttributeNS(z,"href"))try{g=a.getPart(h),g.onchange=function(a){c(a.url,a.mimetype)},g.load()}catch(l){runtime.log("slight problem: "+l)}else runtime.log("using MP4 data fallback"),h=k(b),c(h,"video/mp4")}function v(a){v [...]
- c;"undefined"!==String(typeof webodf_css)?(c=a.createElementNS(b.namespaceURI,"style"),c.setAttribute("media","screen, print, handheld, projection"),c.appendChild(a.createTextNode(webodf_css))):(c=a.createElementNS(b.namespaceURI,"link"),a="webodf.css",runtime.currentDirectory&&(a=runtime.currentDirectory()+"/../"+a),c.setAttribute("href",a),c.setAttribute("rel","stylesheet"));c.setAttribute("type","text/css");b.appendChild(c);return c}function y(a){var b=a.getElementsByTagName("head")[ [...]
- "style"),e="";c.setAttribute("type","text/css");c.setAttribute("media","screen, print, handheld, projection");odf.Namespaces.forEachPrefix(function(a,b){e+="@namespace "+a+" url("+b+");\n"});e+="@namespace webodfhelper url(urn:webodf:names:helper);\n";c.appendChild(a.createTextNode(e));b.appendChild(c);return c}var w=odf.Namespaces.drawns,t=odf.Namespaces.fons,s=odf.Namespaces.officens,D=odf.Namespaces.stylens,A=odf.Namespaces.svgns,B=odf.Namespaces.tablens,M=odf.Namespaces.textns,z=odf [...]
- K=odf.Namespaces.xmlns,F=odf.Namespaces.presentationns,Q=runtime.getWindow(),$=new xmldom.XPath,ia=new odf.OdfUtils,R=new core.DomUtils;odf.OdfCanvas=function(k){function m(b,c,e){function d(b,c,e,h){C.addToQueue(function(){a(b,c,e,h)})}var h,f;h=c.getElementsByTagNameNS(w,"image");for(c=0;c<h.length;c+=1)f=h.item(c),d("image"+String(c),b,f,e)}function t(a,b){function c(a,b){C.addToQueue(function(){x(a,b)})}var e,d,h;d=b.getElementsByTagNameNS(w,"plugin");for(e=0;e<d.length;e+=1)h=d.ite [...]
- function A(){T.firstChild&&(1<W?(T.style.MozTransformOrigin="center top",T.style.WebkitTransformOrigin="center top",T.style.OTransformOrigin="center top",T.style.msTransformOrigin="center top"):(T.style.MozTransformOrigin="left top",T.style.WebkitTransformOrigin="left top",T.style.OTransformOrigin="left top",T.style.msTransformOrigin="left top"),T.style.WebkitTransform="scale("+W+")",T.style.MozTransform="scale("+W+")",T.style.OTransform="scale("+W+")",T.style.msTransform="scale("+W+")" [...]
- Math.round(W*T.offsetWidth)+"px",k.style.height=Math.round(W*T.offsetHeight)+"px")}function z(a){function b(a){return e===a.getAttributeNS(s,"name")}var c=R.getElementsByTagNameNS(a,s,"annotation");a=R.getElementsByTagNameNS(a,s,"annotation-end");var e,d;for(d=0;d<c.length;d+=1)e=c[d].getAttributeNS(s,"name"),ea.addAnnotation({node:c[d],end:a.filter(b)[0]||null});ea.rerenderAnnotations()}function V(a){L?(P.parentNode||(T.appendChild(P),A()),ea&&ea.forgetAnnotations(),ea=new gui.Annotati [...]
- a.body,P),z(a.body)):P.parentNode&&(T.removeChild(P),ea.forgetAnnotations(),A())}function G(a){function c(){n(k);k.style.display="inline-block";var f=O.rootElement;k.ownerDocument.importNode(f,!0);Z.setOdfContainer(O);var g=O,l=U;(new odf.FontLoader).loadFonts(g,l.sheet);b(O,Z,H);l=O;g=la.sheet;n(k);T=N.createElementNS(k.namespaceURI,"div");T.style.display="inline-block";T.style.background="white";T.appendChild(f);k.appendChild(T);P=N.createElementNS(k.namespaceURI,"div");P.id="annotati [...]
- N.createElementNS(k.namespaceURI,"div");fa.id="shadowContent";fa.style.position="absolute";fa.style.top=0;fa.style.left=0;l.getContentElement().appendChild(fa);var v=f.body,x,y,z;y=[];for(x=v.firstChild;x&&x!==v;)if(x.namespaceURI===w&&(y[y.length]=x),x.firstChild)x=x.firstChild;else{for(;x&&x!==v&&!x.nextSibling;)x=x.parentNode;x&&x.nextSibling&&(x=x.nextSibling)}for(z=0;z<y.length;z+=1)x=y[z],d("frame"+String(z),x,g);y=$.getODFElementsWithXPath(v,".//*[*[@text:anchor-type='paragraph'] [...]
- for(x=0;x<y.length;x+=1)v=y[x],v.setAttributeNS&&v.setAttributeNS("urn:webodf:names:helper","containsparagraphanchor",!0);var v=fa,R,C,J;J=0;var E,I;y=l.rootElement.ownerDocument;if((x=f.body.firstElementChild)&&x.namespaceURI===s&&("presentation"===x.localName||"drawing"===x.localName))for(x=x.firstElementChild;x;){z=x.getAttributeNS(w,"master-page-name");if(z){R=l.rootElement.masterStyles.getElementsByTagNameNS(D,"master-page");C=null;J=void 0;for(J=0;J<R.length;J+=1)if(R[J].getAttrib [...]
- z){C=R[J];break}z=C}else z=null;if(z){R=x.getAttributeNS("urn:webodf:names:helper","styleid");C=y.createElementNS(w,"draw:page");I=z.firstElementChild;for(E=0;I;)"true"!==I.getAttributeNS(F,"placeholder")&&(J=I.cloneNode(!0),C.appendChild(J),d(R+"_"+E,J,g)),I=I.nextElementSibling,E+=1;I=E=J=void 0;var L=C.getElementsByTagNameNS(w,"frame");for(J=0;J<L.length;J+=1)E=L[J],(I=E.getAttributeNS(F,"class"))&&!/^(date-time|footer|header|page-number')$/.test(I)&&E.parentNode.removeChild(E);v.app [...]
- J=String(v.getElementsByTagNameNS(w,"page").length);r(C,M,"page-number",J);r(C,F,"header",p(l,x,"header"));r(C,F,"footer",p(l,x,"footer"));d(R,C,g);C.setAttributeNS(w,"draw:master-page-name",z.getAttributeNS(D,"name"))}x=x.nextElementSibling}x=f.body.getElementsByTagNameNS(B,"table-cell");for(v=0;v<x.length;v+=1)y=x.item(v),y.hasAttributeNS(B,"number-columns-spanned")&&y.setAttribute("colspan",y.getAttributeNS(B,"number-columns-spanned")),y.hasAttributeNS(B,"number-rows-spanned")&&y.set [...]
- y.getAttributeNS(B,"number-rows-spanned"));e(f.body);h(f.body);q(f.body);u(f.body);m(l,f.body,g);t(l,f.body);y=f.body;v={};x={};var G;z=Q.document.getElementsByTagNameNS(M,"list-style");for(l=0;l<z.length;l+=1)J=z.item(l),(E=J.getAttributeNS(D,"name"))&&(x[E]=J);y=y.getElementsByTagNameNS(M,"list");for(l=0;l<y.length;l+=1)if(J=y.item(l),z=J.getAttributeNS(K,"id")){R=J.getAttributeNS(M,"continue-list");J.setAttribute("id",z);C="text|list#"+z+" > text|list-item > *:first-child:before {";i [...]
- "style-name"))J=x[E],G=ia.getFirstNonWhitespaceChild(J),J=void 0,G&&("list-level-style-number"===G.localName?(J=G.getAttributeNS(D,"num-format"),E=G.getAttributeNS(D,"num-suffix"),I="",I={1:"decimal",a:"lower-latin",A:"upper-latin",i:"lower-roman",I:"upper-roman"},L=void 0,L=G.getAttributeNS(D,"num-prefix")||"",L=I.hasOwnProperty(J)?L+(" counter(list, "+I[J]+")"):J?L+("'"+J+"';"):L+" ''",E&&(L+=" '"+E+"'"),J=I="content: "+L+";"):"list-level-style-image"===G.localName?J="content: none;": [...]
- G.localName&&(J="content: '"+G.getAttributeNS(M,"bullet-char")+"';")),G=J;if(R){for(J=v[R];J;)R=J,J=v[R];C+="counter-increment:"+R+";";G?(G=G.replace("list",R),C+=G):C+="content:counter("+R+");"}else R="",G?(G=G.replace("list",z),C+=G):C+="content: counter("+z+");",C+="counter-increment:"+z+";",g.insertRule("text|list#"+z+" {counter-reset:"+z+"}",g.cssRules.length);C+="}";v[z]=R;C&&g.insertRule(C,g.cssRules.length)}T.insertBefore(fa,T.firstChild);A();V(f);if(!a&&(f=[O],ja.hasOwnProperty [...]
- ja.statereadychange,G=0;G<g.length;G+=1)g[G].apply(null,f)}O.state===odf.OdfContainer.DONE?c():(runtime.log("WARNING: refreshOdf called but ODF was not DONE."),runtime.setTimeout(function oa(){O.state===odf.OdfContainer.DONE?c():(runtime.log("will be back later..."),runtime.setTimeout(oa,500))},100))}function I(a){C.clearQueue();k.innerHTML=runtime.tr("Loading")+" "+a+"...";k.removeAttribute("style");O=new odf.OdfContainer(a,function(a){O=a;G(!1)})}runtime.assert(null!==k&&void 0!==k,"o [...]
- runtime.assert(null!==k.ownerDocument&&void 0!==k.ownerDocument,"odf.OdfCanvas constructor needs DOM");var ha=this,N=k.ownerDocument,O,Z=new odf.Formatting,ka=new f(k),ca,T,P,L=!1,ea,E,U,H,la,fa,W=1,ja={},C=new g;this.refreshCSS=function(){b(O,Z,H);A()};this.refreshSize=function(){A()};this.odfContainer=function(){return O};this.slidevisibilitycss=function(){return ca.css};this.setOdfContainer=function(a,b){O=a;G(!0===b)};this.load=this.load=I;this.save=function(a){O.save(a)};this.addLi [...]
- b){switch(a){case "selectionchange":ka.addListener(a,b);break;case "click":c(k,a,b);break;default:var e=ja[a];void 0===e&&(e=ja[a]=[]);b&&-1===e.indexOf(b)&&e.push(b)}};this.getFormatting=function(){return Z};this.getAnnotationViewManager=function(){return ea};this.refreshAnnotations=function(){V(O.rootElement)};this.rerenderAnnotations=function(){ea&&ea.rerenderAnnotations()};this.getSizer=function(){return T};this.enableAnnotations=function(a){a!==L&&(L=a,O&&V(O.rootElement))};this.ad [...]
- function(a){ea&&ea.addAnnotation(a)};this.forgetAnnotations=function(){ea&&ea.forgetAnnotations()};this.setZoomLevel=function(a){W=a;A()};this.getZoomLevel=function(){return W};this.fitToContainingElement=function(a,b){var c=k.offsetHeight/W;W=a/(k.offsetWidth/W);b/c<W&&(W=b/c);A()};this.fitToWidth=function(a){W=a/(k.offsetWidth/W);A()};this.fitSmart=function(a,b){var c,e;c=k.offsetWidth/W;e=k.offsetHeight/W;c=a/c;void 0!==b&&b/e<c&&(c=b/e);W=Math.min(1,c);A()};this.fitToHeight=function [...]
- W);A()};this.showFirstPage=function(){ca.showFirstPage()};this.showNextPage=function(){ca.showNextPage()};this.showPreviousPage=function(){ca.showPreviousPage()};this.showPage=function(a){ca.showPage(a);A()};this.getElement=function(){return k};this.addCssForFrameWithImage=function(b){var c=b.getAttributeNS(w,"name");d(c,b,la.sheet);a(c+"img",O,b.firstChild,la.sheet)};this.destroy=function(a){var b=N.getElementsByTagName("head")[0];P&&P.parentNode&&P.parentNode.removeChild(P);T&&k.remov [...]
- b.removeChild(E);b.removeChild(U);b.removeChild(H);b.removeChild(la);ka.destroy(function(b){b?a(b):ca.destroy(a)})};E=v(N);ca=new l(y(N));U=y(N);H=y(N);la=y(N)};return odf.OdfCanvas}();
- // Input 40
- runtime.loadClass("odf.OdfCanvas");
- odf.CommandLineTools=function(){this.roundTrip=function(g,l,c){return new odf.OdfContainer(g,function(m){if(m.state===odf.OdfContainer.INVALID)return c("Document "+g+" is invalid.");m.state===odf.OdfContainer.DONE?m.saveAs(l,function(f){c(f)}):c("Document was not completely loaded.")})};this.render=function(g,l,c){for(l=l.getElementsByTagName("body")[0];l.firstChild;)l.removeChild(l.firstChild);l=new odf.OdfCanvas(l);l.addListener("statereadychange",function(g){c(g)});l.load(g)}};
- // Input 41
- /*
-
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- This file is part of WebODF.
-
- WebODF is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License (GNU AGPL)
- as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version.
-
- WebODF is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with WebODF. If not, see <http://www.gnu.org/licenses/>.
- @licend
-
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- ops.Member=function(g,l){var c={};this.getMemberId=function(){return g};this.getProperties=function(){return c};this.setProperties=function(g){Object.keys(g).forEach(function(f){c[f]=g[f]})};this.removeProperties=function(g){delete g.fullName;delete g.color;delete g.imageUrl;Object.keys(g).forEach(function(f){c.hasOwnProperty(f)&&delete c[f]})};runtime.assert(Boolean(g),"No memberId was supplied!");l.fullName||(l.fullName=runtime.tr("Unknown Author"));l.color||(l.color="black");l.imageU [...]
- "avatar-joe.png");c=l};
- // Input 42
++runtime.loadClass("core.PositionFilter");runtime.loadClass("odf.OdfUtils");
++ops.TextPositionFilter=function(g){function k(h,g,d){var f,a;if(g&&(f=e.lookLeftForCharacter(g),1===f||2===f&&(e.scanRightForAnyCharacter(d)||e.scanRightForAnyCharacter(e.nextNode(h)))))return q;f=null===g&&e.isParagraph(h);a=e.lookRightForCharacter(d);if(f)return a?q:e.scanRightForAnyCharacter(d)?b:q;if(!a)return b;g=g||e.previousNode(h);return e.scanLeftForAnyCharacter(g)?b:q}var e=new odf.OdfUtils,n=Node.ELEMENT_NODE,m=Node.TEXT_NODE,q=core.PositionFilter.FilterResult.FILTER_ACCEPT,b [...]
++this.acceptPosition=function(h){var r=h.container(),d=r.nodeType,f,a,c;if(d!==n&&d!==m)return b;if(d===m){if(!e.isGroupingElement(r.parentNode)||e.isWithinTrackedChanges(r.parentNode,g()))return b;d=h.unfilteredDomOffset();f=r.data;runtime.assert(d!==f.length,"Unexpected offset.");if(0<d){h=f[d-1];if(!e.isODFWhitespace(h))return q;if(1<d)if(h=f[d-2],!e.isODFWhitespace(h))a=q;else{if(!e.isODFWhitespace(f.substr(0,d)))return b}else c=e.previousNode(r),e.scanLeftForNonSpace(c)&&(a=q);if(a= [...]
++d)?b:q;a=f[d];return e.isODFWhitespace(a)?b:e.scanLeftForAnyCharacter(e.previousNode(r))?b:q}c=h.leftNode();a=r;r=r.parentNode;a=k(r,c,a)}else!e.isGroupingElement(r)||e.isWithinTrackedChanges(r,g())?a=b:(c=h.leftNode(),a=h.rightNode(),a=k(r,c,a));return a}};
++// Input 35
++"function"!==typeof Object.create&&(Object.create=function(g){var k=function(){};k.prototype=g;return new k});
++xmldom.LSSerializer=function(){function g(e){var g=e||{},b=function(b){var a={},c;for(c in b)b.hasOwnProperty(c)&&(a[b[c]]=c);return a}(e),h=[g],k=[b],d=0;this.push=function(){d+=1;g=h[d]=Object.create(g);b=k[d]=Object.create(b)};this.pop=function(){h.pop();k.pop();d-=1;g=h[d];b=k[d]};this.getLocalNamespaceDefinitions=function(){return b};this.getQName=function(d){var a=d.namespaceURI,c=0,e;if(!a)return d.localName;if(e=b[a])return e+":"+d.localName;do{e||!d.prefix?(e="ns"+c,c+=1):e=d.p [...]
++a)break;if(!g[e]){g[e]=a;b[a]=e;break}e=null}while(null===e);return e+":"+d.localName}}function k(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/'/g,"'").replace(/"/g,""")}function e(g,q){var b="",h=n.filter?n.filter.acceptNode(q):NodeFilter.FILTER_ACCEPT,r;if(h===NodeFilter.FILTER_ACCEPT&&q.nodeType===Node.ELEMENT_NODE){g.push();r=g.getQName(q);var d,f=q.attributes,a,c,p,l="",u;d="<"+r;a=f.length;for(c=0;c<a;c+=1)p=f.item(c),"http://www.w [...]
++p.namespaceURI&&(u=n.filter?n.filter.acceptNode(p):NodeFilter.FILTER_ACCEPT,u===NodeFilter.FILTER_ACCEPT&&(u=g.getQName(p),p="string"===typeof p.value?k(p.value):p.value,l+=" "+(u+'="'+p+'"')));a=g.getLocalNamespaceDefinitions();for(c in a)a.hasOwnProperty(c)&&((f=a[c])?"xmlns"!==f&&(d+=" xmlns:"+a[c]+'="'+c+'"'):d+=' xmlns="'+c+'"');b+=d+(l+">")}if(h===NodeFilter.FILTER_ACCEPT||h===NodeFilter.FILTER_SKIP){for(h=q.firstChild;h;)b+=e(g,h),h=h.nextSibling;q.nodeValue&&(b+=k(q.nodeValue))} [...]
++r+">",g.pop());return b}var n=this;this.filter=null;this.writeToString=function(k,n){if(!k)return"";var b=new g(n);return e(b,k)}};
++// Input 36
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.Server=function(){};ops.Server.prototype.connect=function(g,l){};ops.Server.prototype.networkStatus=function(){};ops.Server.prototype.login=function(g,l,c,m){};ops.Server.prototype.joinSession=function(g,l,c,m){};ops.Server.prototype.leaveSession=function(g,l,c,m){};ops.Server.prototype.getGenesisUrl=function(g){};
- // Input 43
++runtime.loadClass("odf.Namespaces");runtime.loadClass("xmldom.LSSerializer");runtime.loadClass("odf.OdfNodeFilter");runtime.loadClass("odf.TextSerializer");
++gui.Clipboard=function(){var g,k,e;this.setDataFromRange=function(e,m){var q=!0,b,h=e.clipboardData;b=runtime.getWindow();var r=m.startContainer.ownerDocument;!h&&b&&(h=b.clipboardData);h?(r=r.createElement("span"),r.appendChild(m.cloneContents()),b=h.setData("text/plain",k.writeToString(r)),q=q&&b,b=h.setData("text/html",g.writeToString(r,odf.Namespaces.namespaceMap)),q=q&&b,e.preventDefault()):q=!1;return q};g=new xmldom.LSSerializer;k=new odf.TextSerializer;e=new odf.OdfNodeFilter;g. [...]
++e};
++// Input 37
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.Operation=function(){};ops.Operation.prototype.init=function(g){};ops.Operation.prototype.execute=function(g){};ops.Operation.prototype.spec=function(){};
- // Input 44
++runtime.loadClass("core.Base64");runtime.loadClass("core.Zip");runtime.loadClass("xmldom.LSSerializer");runtime.loadClass("odf.StyleInfo");runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.OdfNodeFilter");runtime.loadClass("odf.MetadataManager");
++(function(){function g(a,c,b){for(a=a?a.firstChild:null;a;){if(a.localName===b&&a.namespaceURI===c)return a;a=a.nextSibling}return null}function k(a){var c,b=r.length;for(c=0;c<b;c+=1)if("urn:oasis:names:tc:opendocument:xmlns:office:1.0"===a.namespaceURI&&a.localName===r[c])return c;return-1}function e(a,c){var b=new q.UsedStyleList(a,c),d=new odf.OdfNodeFilter;this.acceptNode=function(a){var f=d.acceptNode(a);f===NodeFilter.FILTER_ACCEPT&&a.parentNode===c&&a.nodeType===Node.ELEMENT_NOD [...]
++NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT);return f}}function n(a,c){var b=new e(a,c);this.acceptNode=function(a){var c=b.acceptNode(a);c!==NodeFilter.FILTER_ACCEPT||!a.parentNode||a.parentNode.namespaceURI!==odf.Namespaces.textns||"s"!==a.parentNode.localName&&"tab"!==a.parentNode.localName||(c=NodeFilter.FILTER_REJECT);return c}}function m(a,c){if(c){var b=k(c),d,f=a.firstChild;if(-1!==b){for(;f;){d=k(f);if(-1!==d&&d>b)break;f=f.nextSibling}a.insertBefore(c,f)}}}var q=new odf. [...]
++b,h=odf.Namespaces.stylens,r="meta settings scripts font-face-decls styles automatic-styles master-styles body".split(" "),d=(new Date).getTime()+"_webodf_",f=new core.Base64;odf.ODFElement=function(){};odf.ODFDocumentElement=function(){};odf.ODFDocumentElement.prototype=new odf.ODFElement;odf.ODFDocumentElement.prototype.constructor=odf.ODFDocumentElement;odf.ODFDocumentElement.prototype.fontFaceDecls=null;odf.ODFDocumentElement.prototype.manifest=null;odf.ODFDocumentElement.prototype. [...]
++odf.ODFDocumentElement.namespaceURI="urn:oasis:names:tc:opendocument:xmlns:office:1.0";odf.ODFDocumentElement.localName="document";odf.OdfPart=function(a,c,b,d){var f=this;this.size=0;this.type=null;this.name=a;this.container=b;this.url=null;this.mimetype=c;this.onstatereadychange=this.document=null;this.EMPTY=0;this.LOADING=1;this.DONE=2;this.state=this.EMPTY;this.data="";this.load=function(){null!==d&&(this.mimetype=c,d.loadAsDataURL(a,c,function(a,c){a&&runtime.log(a);f.url=c;if(f.on [...]
++if(f.onstatereadychange)f.onstatereadychange(f)}))}};odf.OdfPart.prototype.load=function(){};odf.OdfPart.prototype.getUrl=function(){return this.data?"data:;base64,"+f.toBase64(this.data):null};odf.OdfContainer=function c(p,l){function k(c){for(var b=c.firstChild,d;b;)d=b.nextSibling,b.nodeType===Node.ELEMENT_NODE?k(b):b.nodeType===Node.PROCESSING_INSTRUCTION_NODE&&c.removeChild(b),b=d}function r(c,b){for(var d=c&&c.firstChild;d;)d.nodeType===Node.ELEMENT_NODE&&d.setAttributeNS("urn:web [...]
++"scope",b),d=d.nextSibling}function w(c){var b={},d;for(c=c.firstChild;c;)c.nodeType===Node.ELEMENT_NODE&&c.namespaceURI===h&&"font-face"===c.localName&&(d=c.getAttributeNS(h,"name"),b[d]=c),c=c.nextSibling;return b}function y(c,b){var d=null,f,e,h;if(c)for(d=c.cloneNode(!0),f=d.firstElementChild;f;)e=f.nextElementSibling,(h=f.getAttributeNS("urn:webodf:names:scope","scope"))&&h!==b&&d.removeChild(f),f=e;return d}function v(c,b){var d,f,e,l=null,g={};if(c)for(b.forEach(function(c){q.col [...]
++c)}),l=c.cloneNode(!0),d=l.firstElementChild;d;)f=d.nextElementSibling,e=d.getAttributeNS(h,"name"),g[e]||l.removeChild(d),d=f;return l}function t(c){var b=H.rootElement.ownerDocument,d;if(c){k(c.documentElement);try{d=b.importNode(c.documentElement,!0)}catch(f){}}return d}function s(c){H.state=c;if(H.onchange)H.onchange(H);if(H.onstatereadychange)H.onstatereadychange(H)}function N(c){L=null;H.rootElement=c;c.fontFaceDecls=g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-fac [...]
++c.styles=g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles");c.automaticStyles=g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles");c.masterStyles=g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles");c.body=g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","body");c.meta=g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta")}function z(b){var f=t(b),e=H.rootElement,h;f&&"document-styles"===f.localName&&"urn:oasis:names:t [...]
++f.namespaceURI?(e.fontFaceDecls=g(f,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls"),m(e,e.fontFaceDecls),h=g(f,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles"),e.styles=h||b.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles"),m(e,e.styles),h=g(f,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles"),e.automaticStyles=h||b.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles"),r(e.a [...]
++"document-styles"),m(e,e.automaticStyles),f=g(f,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles"),e.masterStyles=f||b.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles"),m(e,e.masterStyles),q.prefixStyleNames(e.automaticStyles,d,e.masterStyles)):s(c.INVALID)}function x(b){b=t(b);var d,f,e,l;if(b&&"document-content"===b.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===b.namespaceURI){d=H.rootElement;e=g(b,"urn:oasis:names:t [...]
++"font-face-decls");if(d.fontFaceDecls&&e){l=d.fontFaceDecls;var p,k,n,v,u={};f=w(l);v=w(e);for(e=e.firstElementChild;e;){p=e.nextElementSibling;if(e.namespaceURI===h&&"font-face"===e.localName)if(k=e.getAttributeNS(h,"name"),f.hasOwnProperty(k)){if(!e.isEqualNode(f[k])){n=k;for(var z=f,F=v,x=0,A=void 0,A=n=n.replace(/\d+$/,"");z.hasOwnProperty(A)||F.hasOwnProperty(A);)x+=1,A=n+x;n=A;e.setAttributeNS(h,"style:name",n);l.appendChild(e);f[n]=e;delete v[k];u[k]=n}}else l.appendChild(e),f[k] [...]
++e=p}l=u}else e&&(d.fontFaceDecls=e,m(d,e));f=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles");r(f,"document-content");l&&q.changeFontFaceNames(f,l);if(d.automaticStyles&&f)for(l=f.firstChild;l;)d.automaticStyles.appendChild(l),l=f.firstChild;else f&&(d.automaticStyles=f,m(d,f));b=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","body");if(null===b)throw"<office:body/> tag is mising.";d.body=b;m(d,d.body)}else s(c.INVALID)}function R(c){var d=t(c),f;d&&"do [...]
++d.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===d.namespaceURI&&(f=H.rootElement,d=g(d,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta"),f.meta=d||c.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta"),m(f,f.meta),b=new odf.MetadataManager(f.meta))}function F(c){c=t(c);var b;c&&"document-settings"===c.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===c.namespaceURI&&(b=H.rootElement,b.settings=g(c,"urn:oasis:names:tc:opendoc [...]
++"settings"),m(b,b.settings))}function U(c){c=t(c);var b;if(c&&"manifest"===c.localName&&"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"===c.namespaceURI)for(b=H.rootElement,b.manifest=c,c=b.manifest.firstElementChild;c;)"file-entry"===c.localName&&"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"===c.namespaceURI&&(Q[c.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","full-path")]=c.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","media-typ [...]
++function P(b){var d=b.shift();d?X.loadAsDOM(d.path,function(f,e){d.handler(e);f||H.state===c.INVALID||P(b)}):s(c.DONE)}function A(c){var b="";odf.Namespaces.forEachPrefix(function(c,d){b+=" xmlns:"+c+'="'+d+'"'});return'<?xml version="1.0" encoding="UTF-8"?><office:'+c+" "+b+' office:version="1.2">'}function ja(){var c=new xmldom.LSSerializer,b=A("document-meta");c.filter=new odf.OdfNodeFilter;b+=c.writeToString(H.rootElement.meta,odf.Namespaces.namespaceMap);return b+"</office:document [...]
++b){var d=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest:file-entry");d.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest:full-path",c);d.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest:media-type",b);return d}function G(){var c=runtime.parseXML('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2"></manifest:manifest>'),b=g(c,"urn:oa [...]
++"manifest"),d=new xmldom.LSSerializer,f;for(f in Q)Q.hasOwnProperty(f)&&b.appendChild(ka(f,Q[f]));d.filter=new odf.OdfNodeFilter;return'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n'+d.writeToString(c,odf.Namespaces.namespaceMap)}function Z(){var c=new xmldom.LSSerializer,b=A("document-settings");c.filter=new odf.OdfNodeFilter;b+=c.writeToString(H.rootElement.settings,odf.Namespaces.namespaceMap);return b+"</office:document-settings>"}function O(){var c,b,f,h=odf.Namespaces. [...]
++l=new xmldom.LSSerializer,g=A("document-styles");b=y(H.rootElement.automaticStyles,"document-styles");f=H.rootElement.masterStyles.cloneNode(!0);c=v(H.rootElement.fontFaceDecls,[f,H.rootElement.styles,b]);q.removePrefixFromStyleNames(b,d,f);l.filter=new e(f,b);g+=l.writeToString(c,h);g+=l.writeToString(H.rootElement.styles,h);g+=l.writeToString(b,h);g+=l.writeToString(f,h);return g+"</office:document-styles>"}function ba(){var c,b,d=odf.Namespaces.namespaceMap,f=new xmldom.LSSerializer, [...]
++b=y(H.rootElement.automaticStyles,"document-content");c=v(H.rootElement.fontFaceDecls,[b]);f.filter=new n(H.rootElement.body,b);e+=f.writeToString(c,d);e+=f.writeToString(b,d);e+=f.writeToString(H.rootElement.body,d);return e+"</office:document-content>"}function K(b,d){runtime.loadXML(b,function(b,f){if(b)d(b);else{var e=t(f);e&&"document"===e.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===e.namespaceURI?(N(e),s(c.DONE)):s(c.INVALID)}})}function I(){function d(c,b){var [...]
++f=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0",b);h[c]=f;h.appendChild(f)}var f=new core.Zip("",null),e=runtime.byteArrayFromString("application/vnd.oasis.opendocument.text","utf8"),h=H.rootElement,l=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","text");f.save("mimetype",e,!1,new Date);d("meta");d("settings");d("scripts");d("fontFaceDecls","font-face-decls");d("styles");d("automaticStyles","automatic-styles");d("masterStyles", [...]
++d("body");h.body.appendChild(l);b=new odf.MetadataManager(h.meta);s(c.DONE);return f}function C(){var c,d=new Date,f=runtime.getWindow();c="WebODF/"+("undefined"!==String(typeof webodf_version)?webodf_version:"FromSource");f&&(c=c+" "+f.navigator.userAgent);b.setMetadata({"meta:generator":c},null);c=runtime.byteArrayFromString(Z(),"utf8");X.save("settings.xml",c,!0,d);c=runtime.byteArrayFromString(ja(),"utf8");X.save("meta.xml",c,!0,d);c=runtime.byteArrayFromString(O(),"utf8");X.save("s [...]
++c,!0,d);c=runtime.byteArrayFromString(ba(),"utf8");X.save("content.xml",c,!0,d);c=runtime.byteArrayFromString(G(),"utf8");X.save("META-INF/manifest.xml",c,!0,d)}function Y(c,b){C();X.writeAs(c,function(c){b(c)})}var H=this,X,Q={},L;this.onstatereadychange=l;this.state=this.onchange=null;this.setRootElement=N;this.getContentElement=function(){var c;L||(c=H.rootElement.body,L=g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","text")||g(c,"urn:oasis:names:tc:opendocument:xmlns:office: [...]
++g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","spreadsheet"));if(!L)throw"Could not find content element in <office:body/>.";return L};this.getDocumentType=function(){var c=H.getContentElement();return c&&c.localName};this.getMetadataManager=function(){return b};this.getPart=function(c){return new odf.OdfPart(c,Q[c],H,X)};this.getPartData=function(c,b){X.load(c,b)};this.createByteArray=function(c,b){C();X.createByteArray(c,b)};this.saveAs=Y;this.save=function(c){Y(p,c)};this.ge [...]
++this.setBlob=function(c,b,d){d=f.convertBase64ToByteArray(d);X.save(c,d,!1,new Date);Q.hasOwnProperty(c)&&runtime.log(c+" has been overwritten.");Q[c]=b};this.removeBlob=function(c){var b=X.remove(c);runtime.assert(b,"file is not found: "+c);delete Q[c]};this.state=c.LOADING;this.rootElement=function(c){var b=document.createElementNS(c.namespaceURI,c.localName),d;c=new c.Type;for(d in c)c.hasOwnProperty(d)&&(b[d]=c[d]);return b}({Type:odf.ODFDocumentElement,namespaceURI:odf.ODFDocumentE [...]
++localName:odf.ODFDocumentElement.localName});X=p?new core.Zip(p,function(b,d){X=d;b?K(p,function(d){b&&(X.error=b+"\n"+d,s(c.INVALID))}):P([{path:"styles.xml",handler:z},{path:"content.xml",handler:x},{path:"meta.xml",handler:R},{path:"settings.xml",handler:F},{path:"META-INF/manifest.xml",handler:U}])}):I()};odf.OdfContainer.EMPTY=0;odf.OdfContainer.LOADING=1;odf.OdfContainer.DONE=2;odf.OdfContainer.INVALID=3;odf.OdfContainer.SAVING=4;odf.OdfContainer.MODIFIED=5;odf.OdfContainer.getCon [...]
++null)};return odf.OdfContainer})();
++// Input 38
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.OpAddCursor=function(){var g,l;this.init=function(c){g=c.memberid;l=c.timestamp};this.isEdit=!1;this.execute=function(c){var l=c.getCursor(g);if(l)return!1;l=new ops.OdtCursor(g,c);c.addCursor(l);c.emit(ops.OdtDocument.signalCursorAdded,l);return!0};this.spec=function(){return{optype:"AddCursor",memberid:g,timestamp:l}}};
- // Input 45
++runtime.loadClass("core.Base64");runtime.loadClass("xmldom.XPath");runtime.loadClass("odf.OdfContainer");
++(function(){function g(k,m,q,b,h){var r,d=0,f;for(f in k)if(k.hasOwnProperty(f)){if(d===q){r=f;break}d+=1}r?m.getPartData(k[r].href,function(a,c){if(a)runtime.log(a);else if(c){var d="@font-face { font-family: '"+(k[r].family||r)+"'; src: url(data:application/x-font-ttf;charset=binary;base64,"+e.convertUTF8ArrayToBase64(c)+') format("truetype"); }';try{b.insertRule(d,b.cssRules.length)}catch(f){runtime.log("Problem inserting rule in CSS: "+runtime.toJson(f)+"\nRule: "+d)}}else runtime.l [...]
++k[r].href);g(k,m,q+1,b,h)}):h&&h()}var k=xmldom.XPath,e=new core.Base64;odf.FontLoader=function(){this.loadFonts=function(e,m){for(var q=e.rootElement.fontFaceDecls;m.cssRules.length;)m.deleteRule(m.cssRules.length-1);if(q){var b={},h,r,d,f;if(q)for(q=k.getODFElementsWithXPath(q,"style:font-face[svg:font-face-src]",odf.Namespaces.lookupNamespaceURI),h=0;h<q.length;h+=1)r=q[h],d=r.getAttributeNS(odf.Namespaces.stylens,"name"),f=r.getAttributeNS(odf.Namespaces.svgns,"font-family"),r=k.get [...]
++"svg:font-face-src/svg:font-face-uri",odf.Namespaces.lookupNamespaceURI),0<r.length&&(r=r[0].getAttributeNS(odf.Namespaces.xlinkns,"href"),b[d]={href:r,family:f});g(b,e,0,m)}}};return odf.FontLoader})();
++// Input 39
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.DomUtils");runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.OdfUtils");
- gui.StyleHelper=function(g){function l(b,c,f){var d=!0,k;for(k=0;k<b.length&&!(d=b[k]["style:text-properties"],d=!d||d[c]!==f);k+=1);return!d}function c(b,c,l){function d(){a=!0;(h=g.getDefaultStyleElement("paragraph"))||(h=null)}b=f.getParagraphElements(b);for(var k={},a=!1,e,h;0<b.length;){(e=b[0].getAttributeNS(n,"style-name"))?k[e]||(h=g.getStyleElement(e,"paragraph"),k[e]=!0,h||a||d()):a?h=void 0:d();if(void 0!==h&&(e=null===h?g.getSystemDefaultStyleAttributes("paragraph"):g.getInh [...]
- !0),(e=e["style:paragraph-properties"])&&-1===l.indexOf(e[c])))return!1;b.pop()}return!0}var m=new core.DomUtils,f=new odf.OdfUtils,n=odf.Namespaces.textns;this.getAppliedStyles=function(b){var c;b.collapsed?(c=b.startContainer,c.hasChildNodes()&&b.startOffset<c.childNodes.length&&(c=c.childNodes[b.startOffset]),b=[c]):b=f.getTextNodes(b,!0);return g.getAppliedStyles(b)};this.applyStyle=function(b,c,l){var d=m.splitBoundaries(c),k=f.getTextNodes(c,!1);g.applyStyle(b,k,{startContainer:c. [...]
- startOffset:c.startOffset,endContainer:c.endContainer,endOffset:c.endOffset},l);d.forEach(m.normalizeTextNodes)};this.isBold=function(b){return l(b,"fo:font-weight","bold")};this.isItalic=function(b){return l(b,"fo:font-style","italic")};this.hasUnderline=function(b){return l(b,"style:text-underline-style","solid")};this.hasStrikeThrough=function(b){return l(b,"style:text-line-through-style","solid")};this.isAlignedLeft=function(b){return c(b,"fo:text-align",["left","start"])};this.isAl [...]
- function(b){return c(b,"fo:text-align",["center"])};this.isAlignedRight=function(b){return c(b,"fo:text-align",["right","end"])};this.isAlignedJustified=function(b){return c(b,"fo:text-align",["justify"])}};
- // Input 46
++runtime.loadClass("core.DomUtils");runtime.loadClass("core.Utils");
++odf.ObjectNameGenerator=function(g,k){function e(a,c){var b={};this.generateName=function(){var d=c(),f=0,e;do e=a+f,f+=1;while(b[e]||d[e]);b[e]=!0;return e}}function n(){var a={};[g.rootElement.automaticStyles,g.rootElement.styles].forEach(function(c){for(c=c.firstElementChild;c;)c.namespaceURI===m&&"style"===c.localName&&(a[c.getAttributeNS(m,"name")]=!0),c=c.nextElementSibling});return a}var m=odf.Namespaces.stylens,q=odf.Namespaces.drawns,b=odf.Namespaces.xlinkns,h=new core.DomUtils [...]
++d=null,f=null,a=null,c={},p={};this.generateStyleName=function(){null===d&&(d=new e("auto"+r+"_",function(){return n()}));return d.generateName()};this.generateFrameName=function(){null===f&&(h.getElementsByTagNameNS(g.rootElement.body,q,"frame").forEach(function(a){c[a.getAttributeNS(q,"name")]=!0}),f=new e("fr"+r+"_",function(){return c}));return f.generateName()};this.generateImageName=function(){null===a&&(h.getElementsByTagNameNS(g.rootElement.body,q,"image").forEach(function(a){a= [...]
++"href");a=a.substring(9,a.lastIndexOf("."));p[a]=!0}),a=new e("img"+r+"_",function(){return p}));return a.generateName()}};
++// Input 40
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("gui.StyleHelper");runtime.loadClass("odf.OdfUtils");
- ops.OpApplyDirectStyling=function(){function g(b){var c=0<=f?m+f:m,d=b.getIteratorAtPosition(0<=f?m:m+f),c=f?b.getIteratorAtPosition(c):d;b=b.getDOM().createRange();b.setStart(d.container(),d.unfilteredDomOffset());b.setEnd(c.container(),c.unfilteredDomOffset());return b}var l,c,m,f,n,b=new odf.OdfUtils;this.init=function(b){l=b.memberid;c=b.timestamp;m=parseInt(b.position,10);f=parseInt(b.length,10);n=b.setProperties};this.isEdit=!0;this.execute=function(f){var m=g(f),d=b.getImpactedPa [...]
- (new gui.StyleHelper(f.getFormatting())).applyStyle(l,m,n);m.detach();f.getOdfCanvas().refreshCSS();f.fixCursorPositions();d.forEach(function(b){f.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:b,memberId:l,timeStamp:c})});f.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"ApplyDirectStyling",memberid:l,timestamp:c,position:m,length:f,setProperties:n}}};
- // Input 47
++runtime.loadClass("core.DomUtils");runtime.loadClass("core.LoopWatchDog");runtime.loadClass("odf.Namespaces");odf.TextStyleApplicatorFormatting=function(){};odf.TextStyleApplicatorFormatting.prototype.getAppliedStylesForElement=function(g){};odf.TextStyleApplicatorFormatting.prototype.createDerivedStyleObject=function(g,k,e){};odf.TextStyleApplicatorFormatting.prototype.updateStyle=function(g,k){};
++odf.TextStyleApplicator=function(g,k,e){function n(b){function f(a,c){return"object"===typeof a&&"object"===typeof c?Object.keys(a).every(function(b){return f(a[b],c[b])}):a===c}this.isStyleApplied=function(a){a=k.getAppliedStylesForElement(a);return f(b,a)}}function m(b){var f={};this.applyStyleToContainer=function(a){var c;c=a.getAttributeNS(h,"style-name");var p=a.ownerDocument;c=c||"";if(!f.hasOwnProperty(c)){var l=c,m;m=c?k.createDerivedStyleObject(c,"text",b):b;p=p.createElementNS [...]
++k.updateStyle(p,m);p.setAttributeNS(r,"style:name",g.generateStyleName());p.setAttributeNS(r,"style:family","text");p.setAttributeNS("urn:webodf:names:scope","scope","document-content");e.appendChild(p);f[l]=p}c=f[c].getAttributeNS(r,"name");a.setAttributeNS(h,"text:style-name",c)}}function q(d,f){var a=d.ownerDocument,c=d.parentNode,e,l,g=new core.LoopWatchDog(1E4);l=[];"span"!==c.localName||c.namespaceURI!==h?(e=a.createElementNS(h,"text:span"),c.insertBefore(e,d),c=!1):(d.previousSib [...]
++c.firstChild)?(e=c.cloneNode(!1),c.parentNode.insertBefore(e,c.nextSibling)):e=c,c=!0);l.push(d);for(a=d.nextSibling;a&&b.rangeContainsNode(f,a);)g.check(),l.push(a),a=a.nextSibling;l.forEach(function(a){a.parentNode!==e&&e.appendChild(a)});if(a&&c)for(l=e.cloneNode(!1),e.parentNode.insertBefore(l,e.nextSibling);a;)g.check(),c=a.nextSibling,l.appendChild(a),a=c;return e}var b=new core.DomUtils,h=odf.Namespaces.textns,r=odf.Namespaces.stylens;this.applyStyle=function(b,f,a){var c={},e,h, [...]
++a.hasOwnProperty("style:text-properties"),"applyStyle without any text properties");c["style:text-properties"]=a["style:text-properties"];g=new m(c);k=new n(c);b.forEach(function(a){e=k.isStyleApplied(a);!1===e&&(h=q(a,f),g.applyStyleToContainer(h))})}};
++// Input 41
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.OpRemoveCursor=function(){var g,l;this.init=function(c){g=c.memberid;l=c.timestamp};this.isEdit=!1;this.execute=function(c){return c.removeCursor(g)?!0:!1};this.spec=function(){return{optype:"RemoveCursor",memberid:g,timestamp:l}}};
- // Input 48
++runtime.loadClass("core.Utils");runtime.loadClass("odf.ObjectNameGenerator");runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.OdfContainer");runtime.loadClass("odf.StyleInfo");runtime.loadClass("odf.OdfUtils");runtime.loadClass("odf.TextStyleApplicator");
++odf.Formatting=function(){function g(a){return(a=s[a])?t.mergeObjects({},a):{}}function k(a,c,b){for(a=a&&a.firstElementChild;a&&(a.namespaceURI!==c||a.localName!==b);)a=a.nextElementSibling;return a}function e(){for(var c=a.rootElement.fontFaceDecls,b={},d,f,c=c&&c.firstElementChild;c;){if(d=c.getAttributeNS(l,"name"))if((f=c.getAttributeNS(p,"font-family"))||0<c.getElementsByTagNameNS(p,"font-face-uri").length)b[d]=f;c=c.nextElementSibling}return b}function n(c){for(var b=a.rootElemen [...]
++l&&"default-style"===b.localName&&b.getAttributeNS(l,"family")===c)return b;b=b.nextElementSibling}return null}function m(c,b,d){var f,e,h;d=d||[a.rootElement.automaticStyles,a.rootElement.styles];for(h=0;h<d.length;h+=1)for(f=d[h],f=f.firstElementChild;f;){e=f.getAttributeNS(l,"name");if(f.namespaceURI===l&&"style"===f.localName&&f.getAttributeNS(l,"family")===b&&e===c||"list-style"===b&&f.namespaceURI===u&&"list-style"===f.localName&&e===c||"data"===b&&f.namespaceURI===B&&e===c)return [...]
++function q(a){for(var c,b,d,f,e={},h=a.firstElementChild;h;){if(h.namespaceURI===l)for(d=e[h.nodeName]={},b=h.attributes,c=0;c<b.length;c+=1)f=b.item(c),d[f.name]=f.value;h=h.nextElementSibling}b=a.attributes;for(c=0;c<b.length;c+=1)f=b.item(c),e[f.name]=f.value;return e}function b(c,b){for(var d=a.rootElement.styles,f,e={},h=c.getAttributeNS(l,"family"),k=c;k;)f=q(k),e=t.mergeObjects(f,e),k=(f=k.getAttributeNS(l,"parent-style-name"))?m(f,h,[d]):null;if(k=n(h))f=q(k),e=t.mergeObjects(f, [...]
++(e=t.mergeObjects(f,e));return e}function h(a,b){function d(a){Object.keys(a).forEach(function(c){Object.keys(a[c]).forEach(function(a){l+="|"+c+":"+a+"|"})})}for(var f=a.nodeType===Node.TEXT_NODE?a.parentNode:a,e,h=[],l="",g=!1;f;)!g&&y.isGroupingElement(f)&&(g=!0),(e=c.determineStylesForNode(f))&&h.push(e),f=f.parentElement;g&&(h.forEach(d),b&&(b[l]=h));return g?h:void 0}function r(a){var c={orderedStyles:[]};a.forEach(function(a){Object.keys(a).forEach(function(d){var f=Object.keys(a [...]
++h;(e=m(f,d))?(h=b(e),c=t.mergeObjects(h,c),h=e.getAttributeNS(l,"display-name")):runtime.log("No style element found for '"+f+"' of family '"+d+"'");c.orderedStyles.push({name:f,family:d,displayName:h})})});return c}function d(a,c){var b=y.parseLength(a),d=c;if(b)switch(b.unit){case "cm":d=b.value;break;case "mm":d=0.1*b.value;break;case "in":d=2.54*b.value;break;case "pt":d=0.035277778*b.value;break;case "pc":case "px":case "em":break;default:runtime.log("Unit identifier: "+b.unit+" is [...]
++var f=this,a,c=new odf.StyleInfo,p=odf.Namespaces.svgns,l=odf.Namespaces.stylens,u=odf.Namespaces.textns,B=odf.Namespaces.numberns,w=odf.Namespaces.fons,y=new odf.OdfUtils,v=new core.DomUtils,t=new core.Utils,s={paragraph:{"style:paragraph-properties":{"fo:text-align":"left"}}};this.getSystemDefaultStyleAttributes=g;this.setOdfContainer=function(c){a=c};this.getFontMap=e;this.getAvailableParagraphStyles=function(){for(var c=a.rootElement.styles,b,d,f=[],c=c&&c.firstElementChild;c;)"styl [...]
++c.namespaceURI===l&&(b=c.getAttributeNS(l,"family"),"paragraph"===b&&(b=c.getAttributeNS(l,"name"),d=c.getAttributeNS(l,"display-name")||b,b&&d&&f.push({name:b,displayName:d}))),c=c.nextElementSibling;return f};this.isStyleUsed=function(b){var d,f=a.rootElement;d=c.hasDerivedStyles(f,odf.Namespaces.lookupNamespaceURI,b);b=(new c.UsedStyleList(f.styles)).uses(b)||(new c.UsedStyleList(f.automaticStyles)).uses(b)||(new c.UsedStyleList(f.body)).uses(b);return d||b};this.getDefaultStyleEleme [...]
++m;this.getStyleAttributes=q;this.getInheritedStyleAttributes=b;this.getFirstCommonParentStyleNameOrSelf=function(c){var b=a.rootElement.automaticStyles,d=a.rootElement.styles,f;for(f=m(c,"paragraph",[b]);f;)c=f.getAttributeNS(l,"parent-style-name"),f=m(c,"paragraph",[b]);return(f=m(c,"paragraph",[d]))?c:null};this.hasParagraphStyle=function(a){return Boolean(m(a,"paragraph"))};this.getAppliedStyles=function(a){var c={},b=[];a.forEach(function(a){h(a,c)});Object.keys(c).forEach(function( [...]
++return b};this.getAppliedStylesForElement=function(a){return(a=h(a))?r(a):void 0};this.applyStyle=function(c,b,d,e){(new odf.TextStyleApplicator(new odf.ObjectNameGenerator(a,c),f,a.rootElement.automaticStyles)).applyStyle(b,d,e)};this.updateStyle=function(c,b){var d,f;v.mapObjOntoNode(c,b,odf.Namespaces.lookupNamespaceURI);(d=b["style:text-properties"]&&b["style:text-properties"]["style:font-name"])&&!e().hasOwnProperty(d)&&(f=c.ownerDocument.createElementNS(l,"style:font-face"),f.setA [...]
++"style:name",d),f.setAttributeNS(p,"svg:font-family",d),a.rootElement.fontFaceDecls.appendChild(f))};this.createDerivedStyleObject=function(c,b,d){var f=m(c,b);runtime.assert(Boolean(f),"No style element found for '"+c+"' of family '"+b+"'");c=f.parentNode===a.rootElement.automaticStyles?q(f):{"style:parent-style-name":c};c["style:family"]=b;t.mergeObjects(c,d);return c};this.getDefaultTabStopDistance=function(){for(var a=n("paragraph"),a=a&&a.firstElementChild,c;a;)a.namespaceURI===l&& [...]
++a.localName&&(c=a.getAttributeNS(l,"tab-stop-distance")),a=a.nextElementSibling;c||(c="1.25cm");return y.parseNonNegativeLength(c)};this.getContentSize=function(c,b){var f,e,h,g,p,n,q,r,s,t,u;a:{var B,y,I;f=m(c,b);runtime.assert("paragraph"===b||"table"===b,"styleFamily has to be either paragraph or table");if(f){B=f.getAttributeNS(l,"master-page-name")||"Standard";for(f=a.rootElement.masterStyles.lastElementChild;f&&f.getAttributeNS(l,"name")!==B;)f=f.previousElementSibling;B=f.getAttr [...]
++"page-layout-name");y=v.getElementsByTagNameNS(a.rootElement.automaticStyles,l,"page-layout");for(I=0;I<y.length;I+=1)if(f=y[I],f.getAttributeNS(l,"name")===B)break a}f=null}f||(f=k(a.rootElement.styles,l,"default-page-layout"));if(f=k(f,l,"page-layout-properties"))e=f.getAttributeNS(l,"print-orientation")||"portrait","portrait"===e?(e=21.001,h=29.7):(e=29.7,h=21.001),e=d(f.getAttributeNS(w,"page-width"),e),h=d(f.getAttributeNS(w,"page-height"),h),g=d(f.getAttributeNS(w,"margin"),null), [...]
++d(f.getAttributeNS(w,"margin-left"),2),p=d(f.getAttributeNS(w,"margin-right"),2),n=d(f.getAttributeNS(w,"margin-top"),2),q=d(f.getAttributeNS(w,"margin-bottom"),2)):g=p=n=q=g,r=d(f.getAttributeNS(w,"padding"),null),null===r?(r=d(f.getAttributeNS(w,"padding-left"),0),s=d(f.getAttributeNS(w,"padding-right"),0),t=d(f.getAttributeNS(w,"padding-top"),0),u=d(f.getAttributeNS(w,"padding-bottom"),0)):r=s=t=u=r;return{width:e-g-p-r-s,height:h-n-q-t-u}}};
++// Input 42
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.OpMoveCursor=function(){var g,l,c,m,f;this.init=function(n){g=n.memberid;l=n.timestamp;c=n.position;m=n.length||0;f=n.selectionType||ops.OdtCursor.RangeSelection};this.isEdit=!1;this.execute=function(l){var b=l.getCursor(g),p;if(!b)return!1;p=l.convertCursorToDomRange(c,m);b.setSelectedRange(p,0<=m);b.setSelectionType(f);l.emit(ops.OdtDocument.signalCursorMoved,b);return!0};this.spec=function(){return{optype:"MoveCursor",memberid:g,timestamp:l,position:c,length:m,selectionType:f}}};
- // Input 49
++runtime.loadClass("core.DomUtils");runtime.loadClass("odf.OdfContainer");runtime.loadClass("odf.Formatting");runtime.loadClass("xmldom.XPath");runtime.loadClass("odf.FontLoader");runtime.loadClass("odf.Style2CSS");runtime.loadClass("odf.OdfUtils");runtime.loadClass("gui.AnnotationViewManager");
++(function(){function g(){function a(d){b=!0;runtime.setTimeout(function(){try{d()}catch(f){runtime.log(String(f))}b=!1;0<c.length&&a(c.pop())},10)}var c=[],b=!1;this.clearQueue=function(){c.length=0};this.addToQueue=function(d){if(0===c.length&&!b)return a(d);c.push(d)}}function k(a){function c(){for(;0<b.cssRules.length;)b.deleteRule(0);b.insertRule("#shadowContent draw|page {display:none;}",0);b.insertRule("office|presentation draw|page {display:none;}",1);b.insertRule("#shadowContent [...]
++d+") {display:block;}",2);b.insertRule("office|presentation draw|page:nth-of-type("+d+") {display:block;}",3)}var b=a.sheet,d=1;this.showFirstPage=function(){d=1;c()};this.showNextPage=function(){d+=1;c()};this.showPreviousPage=function(){1<d&&(d-=1,c())};this.showPage=function(a){0<a&&(d=a,c())};this.css=a;this.destroy=function(c){a.parentNode.removeChild(a);c()}}function e(a){for(;a.firstChild;)a.removeChild(a.firstChild)}function n(a,c,b){(new odf.Style2CSS).style2css(a.getDocumentTy [...]
++c.getFontMap(),a.rootElement.styles,a.rootElement.automaticStyles)}function m(a,c,b){var d=null;a=a.rootElement.body.getElementsByTagNameNS(R,b+"-decl");b=c.getAttributeNS(R,"use-"+b+"-name");var f;if(b&&0<a.length)for(c=0;c<a.length;c+=1)if(f=a[c],f.getAttributeNS(R,"name")===b){d=f.textContent;break}return d}function q(a,c,b,d){var f=a.ownerDocument;c=a.getElementsByTagNameNS(c,b);for(a=0;a<c.length;a+=1)e(c[a]),d&&(b=c[a],b.appendChild(f.createTextNode(d)))}function b(a,c,b){c.setAtt [...]
++"styleid",a);var d,f=c.getAttributeNS(N,"anchor-type"),e=c.getAttributeNS(t,"x"),h=c.getAttributeNS(t,"y"),l=c.getAttributeNS(t,"width"),g=c.getAttributeNS(t,"height"),k=c.getAttributeNS(w,"min-height"),p=c.getAttributeNS(w,"min-width");if("as-char"===f)d="display: inline-block;";else if(f||e||h)d="position: absolute;";else if(l||g||k||p)d="display: block;";e&&(d+="left: "+e+";");h&&(d+="top: "+h+";");l&&(d+="width: "+l+";");g&&(d+="height: "+g+";");k&&(d+="min-height: "+k+";");p&&(d+=" [...]
++p+";");d&&(d="draw|"+c.localName+'[webodfhelper|styleid="'+a+'"] {'+d+"}",b.insertRule(d,b.cssRules.length))}function h(a){for(a=a.firstChild;a;){if(a.namespaceURI===y&&"binary-data"===a.localName)return"data:image/png;base64,"+a.textContent.replace(/[\r\n\s]/g,"");a=a.nextSibling}return""}function r(a,c,b,d){function f(c){c&&(c='draw|image[webodfhelper|styleid="'+a+'"] {'+("background-image: url("+c+");")+"}",d.insertRule(c,d.cssRules.length))}function e(a){f(a.url)}b.setAttributeNS("u [...]
++"styleid",a);var l=b.getAttributeNS(z,"href"),g;if(l)try{g=c.getPart(l),g.onchange=e,g.load()}catch(k){runtime.log("slight problem: "+String(k))}else l=h(b),f(l)}function d(a){function c(b){var d,f;b.hasAttributeNS(z,"href")&&(d=b.getAttributeNS(z,"href"),"#"===d[0]?(d=d.substring(1),f=function(){var c=U.getODFElementsWithXPath(a,"//text:bookmark-start[@text:name='"+d+"']",odf.Namespaces.lookupNamespaceURI);0===c.length&&(c=U.getODFElementsWithXPath(a,"//text:bookmark[@text:name='"+d+"' [...]
++0<c.length&&c[0].scrollIntoView(!0);return!1}):f=function(){F.open(d)},b.onclick=f)}var b,d,f;d=a.getElementsByTagNameNS(N,"a");for(b=0;b<d.length;b+=1)f=d.item(b),c(f)}function f(a){var c=a.ownerDocument;A.getElementsByTagNameNS(a,N,"line-break").forEach(function(a){a.hasChildNodes()||a.appendChild(c.createElement("br"))})}function a(a){var c=a.ownerDocument;A.getElementsByTagNameNS(a,N,"s").forEach(function(a){for(var b,d;a.firstChild;)a.removeChild(a.firstChild);a.appendChild(c.creat [...]
++d=parseInt(a.getAttributeNS(N,"c"),10);if(1<d)for(a.removeAttributeNS(N,"c"),b=1;b<d;b+=1)a.parentNode.insertBefore(a.cloneNode(!0),a)})}function c(a){A.getElementsByTagNameNS(a,N,"tab").forEach(function(a){a.textContent="\t"})}function p(a,c){function b(a,d){var h=g.documentElement.namespaceURI;"video/"===d.substr(0,6)?(f=g.createElementNS(h,"video"),f.setAttribute("controls","controls"),e=g.createElementNS(h,"source"),a&&e.setAttribute("src",a),e.setAttribute("type",d),f.appendChild(e [...]
++c.innerHtml="Unrecognised Plugin"}function d(a){b(a.url,a.mimetype)}var f,e,l,g=c.ownerDocument,k;if(l=c.getAttributeNS(z,"href"))try{k=a.getPart(l),k.onchange=d,k.load()}catch(p){runtime.log("slight problem: "+String(p))}else runtime.log("using MP4 data fallback"),l=h(c),b(l,"video/mp4")}function l(a){var c=a.getElementsByTagName("head")[0],b;"undefined"!==String(typeof webodf_css)?(b=a.createElementNS(c.namespaceURI,"style"),b.setAttribute("media","screen, print, handheld, projection" [...]
++(b=a.createElementNS(c.namespaceURI,"link"),a="webodf.css",runtime.currentDirectory&&(a=runtime.currentDirectory()+"/../"+a),b.setAttribute("href",a),b.setAttribute("rel","stylesheet"));b.setAttribute("type","text/css");c.appendChild(b);return b}function u(a){var c=a.getElementsByTagName("head")[0],b=a.createElementNS(c.namespaceURI,"style"),d="";b.setAttribute("type","text/css");b.setAttribute("media","screen, print, handheld, projection");odf.Namespaces.forEachPrefix(function(a,c){d+= [...]
++a+" url("+c+");\n"});d+="@namespace webodfhelper url(urn:webodf:names:helper);\n";b.appendChild(a.createTextNode(d));c.appendChild(b);return b}var B=odf.Namespaces.drawns,w=odf.Namespaces.fons,y=odf.Namespaces.officens,v=odf.Namespaces.stylens,t=odf.Namespaces.svgns,s=odf.Namespaces.tablens,N=odf.Namespaces.textns,z=odf.Namespaces.xlinkns,x=odf.Namespaces.xmlns,R=odf.Namespaces.presentationns,F=runtime.getWindow(),U=xmldom.XPath,P=new odf.OdfUtils,A=new core.DomUtils;odf.OdfCanvas=funct [...]
++c,b){function d(a,c,b,f){D.addToQueue(function(){r(a,c,b,f)})}var f,e;f=c.getElementsByTagNameNS(B,"image");for(c=0;c<f.length;c+=1)e=f.item(c),d("image"+String(c),a,e,b)}function w(a,c){function b(a,c){D.addToQueue(function(){p(a,c)})}var d,f,e;f=c.getElementsByTagNameNS(B,"plugin");for(d=0;d<f.length;d+=1)e=f.item(d),b(a,e)}function z(){L.firstChild&&(1<S?(L.style.MozTransformOrigin="center top",L.style.WebkitTransformOrigin="center top",L.style.OTransformOrigin="center top",L.style.m [...]
++"center top"):(L.style.MozTransformOrigin="left top",L.style.WebkitTransformOrigin="left top",L.style.OTransformOrigin="left top",L.style.msTransformOrigin="left top"),L.style.WebkitTransform="scale("+S+")",L.style.MozTransform="scale("+S+")",L.style.OTransform="scale("+S+")",L.style.msTransform="scale("+S+")",h.style.width=Math.round(S*L.offsetWidth)+"px",h.style.height=Math.round(S*L.offsetHeight)+"px")}function O(a){function c(a){return d===a.getAttributeNS(y,"name")}var b=A.getEleme [...]
++y,"annotation");a=A.getElementsByTagNameNS(a,y,"annotation-end");var d,f;for(f=0;f<b.length;f+=1)d=b[f].getAttributeNS(y,"name"),aa.addAnnotation({node:b[f],end:a.filter(c)[0]||null});aa.rerenderAnnotations()}function ba(a){la?(ca.parentNode||(L.appendChild(ca),z()),aa&&aa.forgetAnnotations(),aa=new gui.AnnotationViewManager(C,a.body,ca),O(a.body)):ca.parentNode&&(L.removeChild(ca),aa.forgetAnnotations(),z())}function K(l){function g(){e(h);h.style.display="inline-block";var k=H.rootEle [...]
++!0);X.setOdfContainer(H);var p=H,r=T;(new odf.FontLoader).loadFonts(p,r.sheet);n(H,X,$);r=H;p=W.sheet;e(h);L=Y.createElementNS(h.namespaceURI,"div");L.style.display="inline-block";L.style.background="white";L.appendChild(k);h.appendChild(L);ca=Y.createElementNS(h.namespaceURI,"div");ca.id="annotationsPane";da=Y.createElementNS(h.namespaceURI,"div");da.id="shadowContent";da.style.position="absolute";da.style.top=0;da.style.left=0;r.getContentElement().appendChild(da);var u=k.body,A,E=[], [...]
++A!==u;)if(A.namespaceURI===B&&(E[E.length]=A),A.firstElementChild)A=A.firstElementChild;else{for(;A&&A!==u&&!A.nextElementSibling;)A=A.parentElement;A&&A.nextElementSibling&&(A=A.nextElementSibling)}for(C=0;C<E.length;C+=1)A=E[C],b("frame"+String(C),A,p);E=U.getODFElementsWithXPath(u,".//*[*[@text:anchor-type='paragraph']]",odf.Namespaces.lookupNamespaceURI);for(A=0;A<E.length;A+=1)u=E[A],u.setAttributeNS&&u.setAttributeNS("urn:webodf:names:helper","containsparagraphanchor",!0);var u=da [...]
++var K,Q,E=r.rootElement.ownerDocument;if((A=k.body.firstElementChild)&&A.namespaceURI===y&&("presentation"===A.localName||"drawing"===A.localName))for(A=A.firstElementChild;A;){C=A.getAttributeNS(B,"master-page-name");if(C){for(O=r.rootElement.masterStyles.firstElementChild;O&&(O.getAttributeNS(v,"name")!==C||"master-page"!==O.localName||O.namespaceURI!==v););C=O}else C=null;if(C){O=A.getAttributeNS("urn:webodf:names:helper","styleid");I=E.createElementNS(B,"draw:page");Q=C.firstElement [...]
++0;Q;)"true"!==Q.getAttributeNS(R,"placeholder")&&(D=Q.cloneNode(!0),I.appendChild(D),b(O+"_"+K,D,p)),Q=Q.nextElementSibling,K+=1;Q=K=D=void 0;var V=I.getElementsByTagNameNS(B,"frame");for(D=0;D<V.length;D+=1)K=V[D],(Q=K.getAttributeNS(R,"class"))&&!/^(date-time|footer|header|page-number')$/.test(Q)&&K.parentNode.removeChild(K);u.appendChild(I);D=String(u.getElementsByTagNameNS(B,"page").length);q(I,N,"page-number",D);q(I,R,"header",m(r,A,"header"));q(I,R,"footer",m(r,A,"footer"));b(O,I, [...]
++"draw:master-page-name",C.getAttributeNS(v,"name"))}A=A.nextElementSibling}u=h.namespaceURI;E=k.body.getElementsByTagNameNS(s,"table-cell");for(A=0;A<E.length;A+=1)C=E.item(A),C.hasAttributeNS(s,"number-columns-spanned")&&C.setAttributeNS(u,"colspan",C.getAttributeNS(s,"number-columns-spanned")),C.hasAttributeNS(s,"number-rows-spanned")&&C.setAttributeNS(u,"rowspan",C.getAttributeNS(s,"number-rows-spanned"));d(k.body);f(k.body);a(k.body);c(k.body);t(r,k.body,p);w(r,k.body);C=k.body;r=h. [...]
++A={};var E={},J;O=F.document.getElementsByTagNameNS(N,"list-style");for(u=0;u<O.length;u+=1)K=O.item(u),(Q=K.getAttributeNS(v,"name"))&&(E[Q]=K);C=C.getElementsByTagNameNS(N,"list");for(u=0;u<C.length;u+=1)if(K=C.item(u),O=K.getAttributeNS(x,"id")){I=K.getAttributeNS(N,"continue-list");K.setAttributeNS(r,"id",O);D="text|list#"+O+" > text|list-item > *:first-child:before {";if(Q=K.getAttributeNS(N,"style-name")){K=E[Q];J=P.getFirstNonWhitespaceChild(K);K=void 0;if(J)if("list-level-style- [...]
++J.localName){K=J.getAttributeNS(v,"num-format");Q=J.getAttributeNS(v,"num-suffix")||"";var V="",V={1:"decimal",a:"lower-latin",A:"upper-latin",i:"lower-roman",I:"upper-roman"},S=void 0,S=J.getAttributeNS(v,"num-prefix")||"",S=V.hasOwnProperty(K)?S+(" counter(list, "+V[K]+")"):K?S+("'"+K+"';"):S+" ''";Q&&(S+=" '"+Q+"'");K=V="content: "+S+";"}else"list-level-style-image"===J.localName?K="content: none;":"list-level-style-bullet"===J.localName&&(K="content: '"+J.getAttributeNS(N,"bullet-ch [...]
++J=K}if(I){for(K=A[I];K;)K=A[K];D+="counter-increment:"+I+";";J?(J=J.replace("list",I),D+=J):D+="content:counter("+I+");"}else I="",J?(J=J.replace("list",O),D+=J):D+="content: counter("+O+");",D+="counter-increment:"+O+";",p.insertRule("text|list#"+O+" {counter-reset:"+O+"}",p.cssRules.length);D+="}";A[O]=I;D&&p.insertRule(D,p.cssRules.length)}L.insertBefore(da,L.firstChild);z();ba(k);if(!l&&(k=[H],ga.hasOwnProperty("statereadychange")))for(p=ga.statereadychange,J=0;J<p.length;J+=1)p[J]. [...]
++k)}H.state===odf.OdfContainer.DONE?g():(runtime.log("WARNING: refreshOdf called but ODF was not DONE."),runtime.setTimeout(function ha(){H.state===odf.OdfContainer.DONE?g():(runtime.log("will be back later..."),runtime.setTimeout(ha,500))},100))}function I(a){D.clearQueue();h.innerHTML=runtime.tr("Loading")+" "+a+"...";h.removeAttribute("style");H=new odf.OdfContainer(a,function(a){H=a;K(!1)})}runtime.assert(null!==h&&void 0!==h,"odf.OdfCanvas constructor needs DOM element");runtime.ass [...]
++h.ownerDocument&&void 0!==h.ownerDocument,"odf.OdfCanvas constructor needs DOM");var C=this,Y=h.ownerDocument,H,X=new odf.Formatting,Q,L=null,ca=null,la=!1,aa=null,ma,T,$,W,da,S=1,ga={},D=new g;this.refreshCSS=function(){n(H,X,$);z()};this.refreshSize=function(){z()};this.odfContainer=function(){return H};this.setOdfContainer=function(a,c){H=a;K(!0===c)};this.load=this.load=I;this.save=function(a){H.save(a)};this.addListener=function(a,c){switch(a){case "click":var b=h,d=a;b.addEventLis [...]
++c,!1):b.attachEvent?b.attachEvent("on"+d,c):b["on"+d]=c;break;default:b=ga.hasOwnProperty(a)?ga[a]:ga[a]=[],c&&-1===b.indexOf(c)&&b.push(c)}};this.getFormatting=function(){return X};this.getAnnotationViewManager=function(){return aa};this.refreshAnnotations=function(){ba(H.rootElement)};this.rerenderAnnotations=function(){aa&&aa.rerenderAnnotations()};this.getSizer=function(){return L};this.enableAnnotations=function(a){a!==la&&(la=a,H&&ba(H.rootElement))};this.addAnnotation=function(a) [...]
++this.forgetAnnotations=function(){aa&&aa.forgetAnnotations()};this.setZoomLevel=function(a){S=a;z()};this.getZoomLevel=function(){return S};this.fitToContainingElement=function(a,c){var b=h.offsetHeight/S;S=a/(h.offsetWidth/S);c/b<S&&(S=c/b);z()};this.fitToWidth=function(a){S=a/(h.offsetWidth/S);z()};this.fitSmart=function(a,c){var b,d;b=h.offsetWidth/S;d=h.offsetHeight/S;b=a/b;void 0!==c&&c/d<b&&(b=c/d);S=Math.min(1,b);z()};this.fitToHeight=function(a){S=a/(h.offsetHeight/S);z()};this. [...]
++function(){Q.showFirstPage()};this.showNextPage=function(){Q.showNextPage()};this.showPreviousPage=function(){Q.showPreviousPage()};this.showPage=function(a){Q.showPage(a);z()};this.getElement=function(){return h};this.addCssForFrameWithImage=function(a){var c=a.getAttributeNS(B,"name"),d=a.firstElementChild;b(c,a,W.sheet);d&&r(c+"img",H,d,W.sheet)};this.destroy=function(a){var c=Y.getElementsByTagName("head")[0];ca&&ca.parentNode&&ca.parentNode.removeChild(ca);L&&(h.removeChild(L),L=nu [...]
++c.removeChild(T);c.removeChild($);c.removeChild(W);Q.destroy(a)};ma=l(Y);Q=new k(u(Y));T=u(Y);$=u(Y);W=u(Y)}})();
++// Input 43
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.OpSetBlob=function(){var g,l,c,m,f;this.init=function(n){g=n.memberid;l=n.timestamp;c=n.filename;m=n.mimetype;f=n.content};this.isEdit=!0;this.execute=function(g){g.getOdfCanvas().odfContainer().setBlob(c,m,f);return!0};this.spec=function(){return{optype:"SetBlob",memberid:g,timestamp:l,filename:c,mimetype:m,content:f}}};
- // Input 50
++runtime.loadClass("core.DomUtils");runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.OdfUtils");
++gui.StyleHelper=function(g){function k(b,e,g){var d=!0,f;for(f=0;f<b.length&&!(d=b[f]["style:text-properties"],d=!d||d[e]!==g);f+=1);return!d}function e(b,e,k){function d(){p=!0;(a=g.getDefaultStyleElement("paragraph"))||(a=null)}var f,a;b=m.getParagraphElements(b);for(var c={},p=!1;0<b.length;){(f=b[0].getAttributeNS(q,"style-name"))?c[f]||(a=g.getStyleElement(f,"paragraph"),c[f]=!0,a||p||d()):p?a=void 0:d();if(void 0!==a&&(f=null===a?g.getSystemDefaultStyleAttributes("paragraph"):g.ge [...]
++!0),(f=f["style:paragraph-properties"])&&-1===k.indexOf(f[e])))return!1;b.pop()}return!0}var n=new core.DomUtils,m=new odf.OdfUtils,q=odf.Namespaces.textns;this.getAppliedStyles=function(b){var e;b.collapsed?(e=b.startContainer,e.hasChildNodes()&&b.startOffset<e.childNodes.length&&(e=e.childNodes.item(b.startOffset)),b=[e]):b=m.getTextNodes(b,!0);return g.getAppliedStyles(b)};this.applyStyle=function(b,e,k){var d=n.splitBoundaries(e),f=m.getTextNodes(e,!1);g.applyStyle(b,f,{startContain [...]
++startOffset:e.startOffset,endContainer:e.endContainer,endOffset:e.endOffset},k);d.forEach(n.normalizeTextNodes)};this.isBold=function(b){return k(b,"fo:font-weight","bold")};this.isItalic=function(b){return k(b,"fo:font-style","italic")};this.hasUnderline=function(b){return k(b,"style:text-underline-style","solid")};this.hasStrikeThrough=function(b){return k(b,"style:text-line-through-style","solid")};this.isAlignedLeft=function(b){return e(b,"fo:text-align",["left","start"])};this.isAl [...]
++function(b){return e(b,"fo:text-align",["center"])};this.isAlignedRight=function(b){return e(b,"fo:text-align",["right","end"])};this.isAlignedJustified=function(b){return e(b,"fo:text-align",["justify"])}};
++// Input 44
++core.RawDeflate=function(){function g(){this.dl=this.fc=0}function k(){this.extra_bits=this.static_tree=this.dyn_tree=null;this.max_code=this.max_length=this.elems=this.extra_base=0}function e(a,c,b,d){this.good_length=a;this.max_lazy=c;this.nice_length=b;this.max_chain=d}function n(){this.next=null;this.len=0;this.ptr=[];this.ptr.length=m;this.off=0}var m=8192,q,b,h,r,d=null,f,a,c,p,l,u,B,w,y,v,t,s,N,z,x,R,F,U,P,A,ja,ka,G,Z,O,ba,K,I,C,Y,H,X,Q,L,ca,la,aa,ma,T,$,W,da,S,ga,D,fa,E,pa,ha,ia [...]
++0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],qa=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],ra=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],wa=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],sa;sa=[new e(0,0,0,0),new e(4,4,8,4),new e(4,5,16,8),new e(4,6,32,32),new e(4,4,16,16),new e(8,16,32,32),new e(8,16,128,128),new e(8,32,128,256),new e(32,128,258,1024),new e(32,258,258,4096)];var Aa=function(c){d[a+f++]=c;if(a+f===m){var e;if(0!==f){null!==q?(c=q,q=q. [...]
++c.next=null;c.len=c.off=0;null===b?b=h=c:h=h.next=c;c.len=f-a;for(e=0;e<c.len;e++)c.ptr[e]=d[a+e];f=a=0}}},ta=function(c){c&=65535;a+f<m-2?(d[a+f++]=c&255,d[a+f++]=c>>>8):(Aa(c&255),Aa(c>>>8))},Ba=function(){t=(t<<5^p[F+3-1]&255)&8191;s=B[32768+t];B[F&32767]=s;B[32768+t]=F},V=function(a,c){y>16-c?(w|=a<<y,ta(w),w=a>>16-y,y+=c-16):(w|=a<<y,y+=c)},J=function(a,c){V(c[a].fc,c[a].dl)},ua=function(a,c,b){return a[c].fc<a[b].fc||a[c].fc===a[b].fc&&aa[c]<=aa[b]},na=function(a,c,b){var d;for(d= [...]
++ia.length;d++)a[c+d]=ia.charCodeAt(Ea++)&255;return d},ea=function(){var a,c,b=65536-A-F;if(-1===b)b--;else if(65274<=F){for(a=0;32768>a;a++)p[a]=p[a+32768];U-=32768;F-=32768;v-=32768;for(a=0;8192>a;a++)c=B[32768+a],B[32768+a]=32768<=c?c-32768:0;for(a=0;32768>a;a++)c=B[a],B[a]=32768<=c?c-32768:0;b+=32768}P||(a=na(p,F+A,b),0>=a?P=!0:A+=a)},oa=function(a){var c=ja,b=F,d,f=R,e=32506<F?F-32506:0,h=F+258,l=p[b+f-1],g=p[b+f];R>=Z&&(c>>=2);do if(d=a,p[d+f]===g&&p[d+f-1]===l&&p[d]===p[b]&&p[++d [...]
++2;d++;do++b;while(p[b]===p[++d]&&p[++b]===p[++d]&&p[++b]===p[++d]&&p[++b]===p[++d]&&p[++b]===p[++d]&&p[++b]===p[++d]&&p[++b]===p[++d]&&p[++b]===p[++d]&&b<h);d=258-(h-b);b=h-258;if(d>f){U=a;f=d;if(258<=d)break;l=p[b+f-1];g=p[b+f]}a=B[a&32767]}while(a>e&&0!==--c);return f},Ca=function(a,c){u[S++]=c;0===a?O[c].fc++:(a--,O[ma[c]+256+1].fc++,ba[(256>a?T[a]:T[256+(a>>7)])&255].fc++,l[ga++]=a,fa|=E);E<<=1;0===(S&7)&&(da[D++]=fa,fa=0,E=1);if(2<G&&0===(S&4095)){var b=8*S,d=F-v,f;for(f=0;30>f;f++ [...]
++(5+qa[f]);b>>=3;if(ga<parseInt(S/2,10)&&b<parseInt(d/2,10))return!0}return 8191===S||8192===ga},va=function(a,c){for(var b=L[c],d=c<<1;d<=ca;){d<ca&&ua(a,L[d+1],L[d])&&d++;if(ua(a,b,L[d]))break;L[c]=L[d];c=d;d<<=1}L[c]=b},Fa=function(a,c){var b=0;do b|=a&1,a>>=1,b<<=1;while(0<--c);return b>>1},xa=function(a,c){var b=[];b.length=16;var d=0,f;for(f=1;15>=f;f++)d=d+Q[f-1]<<1,b[f]=d;for(d=0;d<=c;d++)f=a[d].dl,0!==f&&(a[d].fc=Fa(b[f]++,f))},Da=function(a){var c=a.dyn_tree,b=a.static_tree,d=a [...]
++-1,h=d;ca=0;la=573;for(f=0;f<d;f++)0!==c[f].fc?(L[++ca]=e=f,aa[f]=0):c[f].dl=0;for(;2>ca;)f=L[++ca]=2>e?++e:0,c[f].fc=1,aa[f]=0,pa--,null!==b&&(ha-=b[f].dl);a.max_code=e;for(f=ca>>1;1<=f;f--)va(c,f);do f=L[1],L[1]=L[ca--],va(c,1),b=L[1],L[--la]=f,L[--la]=b,c[h].fc=c[f].fc+c[b].fc,aa[h]=aa[f]>aa[b]+1?aa[f]:aa[b]+1,c[f].dl=c[b].dl=h,L[1]=h++,va(c,1);while(2<=ca);L[--la]=L[1];h=a.dyn_tree;f=a.extra_bits;var d=a.extra_base,b=a.max_code,l=a.max_length,g=a.static_tree,k,p,m,n,r=0;for(p=0;15>= [...]
++0;h[L[la]].dl=0;for(a=la+1;573>a;a++)k=L[a],p=h[h[k].dl].dl+1,p>l&&(p=l,r++),h[k].dl=p,k>b||(Q[p]++,m=0,k>=d&&(m=f[k-d]),n=h[k].fc,pa+=n*(p+m),null!==g&&(ha+=n*(g[k].dl+m)));if(0!==r){do{for(p=l-1;0===Q[p];)p--;Q[p]--;Q[p+1]+=2;Q[l]--;r-=2}while(0<r);for(p=l;0!==p;p--)for(k=Q[p];0!==k;)f=L[--a],f>b||(h[f].dl!==p&&(pa+=(p-h[f].dl)*h[f].fc,h[f].fc=p),k--)}xa(c,e)},ya=function(a,c){var b,d=-1,f,e=a[0].dl,h=0,l=7,g=4;0===e&&(l=138,g=3);a[c+1].dl=65535;for(b=0;b<=c;b++)f=e,e=a[b+1].dl,++h<l& [...]
++g?C[f].fc+=h:0!==f?(f!==d&&C[f].fc++,C[16].fc++):10>=h?C[17].fc++:C[18].fc++,h=0,d=f,0===e?(l=138,g=3):f===e?(l=6,g=3):(l=7,g=4))},Ga=function(){8<y?ta(w):0<y&&Aa(w);y=w=0},za=function(a,c){var b,d=0,f=0,e=0,h=0,g,k;if(0!==S){do 0===(d&7)&&(h=da[e++]),b=u[d++]&255,0===(h&1)?J(b,a):(g=ma[b],J(g+256+1,a),k=M[g],0!==k&&(b-=$[g],V(b,k)),b=l[f++],g=(256>b?T[b]:T[256+(b>>7)])&255,J(g,c),k=qa[g],0!==k&&(b-=W[g],V(b,k))),h>>=1;while(d<S)}J(256,a)},Ia=function(a,c){var b,d=-1,f,e=a[0].dl,h=0,l=7 [...]
++(l=138,g=3);for(b=0;b<=c;b++)if(f=e,e=a[b+1].dl,!(++h<l&&f===e)){if(h<g){do J(f,C);while(0!==--h)}else 0!==f?(f!==d&&(J(f,C),h--),J(16,C),V(h-3,2)):10>=h?(J(17,C),V(h-3,3)):(J(18,C),V(h-11,7));h=0;d=f;0===e?(l=138,g=3):f===e?(l=6,g=3):(l=7,g=4)}},Ja=function(){var a;for(a=0;286>a;a++)O[a].fc=0;for(a=0;30>a;a++)ba[a].fc=0;for(a=0;19>a;a++)C[a].fc=0;O[256].fc=1;fa=S=ga=D=pa=ha=0;E=1},Ha=function(a){var c,b,d,f;f=F-v;da[D]=fa;Da(Y);Da(H);ya(O,Y.max_code);ya(ba,H.max_code);Da(X);for(d=18;3< [...]
++pa+=3*(d+1)+14;c=pa+3+7>>3;b=ha+3+7>>3;b<=c&&(c=b);if(f+4<=c&&0<=v)for(V(0+a,3),Ga(),ta(f),ta(~f),d=0;d<f;d++)Aa(p[v+d]);else if(b===c)V(2+a,3),za(K,I);else{V(4+a,3);f=Y.max_code+1;c=H.max_code+1;d+=1;V(f-257,5);V(c-1,5);V(d-4,4);for(b=0;b<d;b++)V(C[wa[b]].dl,3);Ia(O,f-1);Ia(ba,c-1);za(O,ba)}Ja();0!==a&&Ga()},Ka=function(c,e,h){var l,g,k;for(l=0;null!==b&&l<h;){g=h-l;g>b.len&&(g=b.len);for(k=0;k<g;k++)c[e+l+k]=b.ptr[b.off+k];b.off+=g;b.len-=g;l+=g;0===b.len&&(g=b,b=b.next,g.next=q,q=g)} [...]
++if(a<f){g=h-l;g>f-a&&(g=f-a);for(k=0;k<g;k++)c[e+l+k]=d[a+k];a+=g;l+=g;f===a&&(f=a=0)}return l},La=function(d,e,h){var l;if(!r){if(!P){y=w=0;var g,k;if(0===I[0].dl){Y.dyn_tree=O;Y.static_tree=K;Y.extra_bits=M;Y.extra_base=257;Y.elems=286;Y.max_length=15;Y.max_code=0;H.dyn_tree=ba;H.static_tree=I;H.extra_bits=qa;H.extra_base=0;H.elems=30;H.max_length=15;H.max_code=0;X.dyn_tree=C;X.static_tree=null;X.extra_bits=ra;X.extra_base=0;X.elems=19;X.max_length=7;for(k=g=X.max_code=0;28>k;k++)for( [...]
++1<<M[k];l++)ma[g++]=k;ma[g-1]=k;for(k=g=0;16>k;k++)for(W[k]=g,l=0;l<1<<qa[k];l++)T[g++]=k;for(g>>=7;30>k;k++)for(W[k]=g<<7,l=0;l<1<<qa[k]-7;l++)T[256+g++]=k;for(l=0;15>=l;l++)Q[l]=0;for(l=0;143>=l;)K[l++].dl=8,Q[8]++;for(;255>=l;)K[l++].dl=9,Q[9]++;for(;279>=l;)K[l++].dl=7,Q[7]++;for(;287>=l;)K[l++].dl=8,Q[8]++;xa(K,287);for(l=0;30>l;l++)I[l].dl=5,I[l].fc=Fa(l,5);Ja()}for(l=0;8192>l;l++)B[32768+l]=0;ka=sa[G].max_lazy;Z=sa[G].good_length;ja=sa[G].max_chain;v=F=0;A=na(p,0,65536);if(0>=A)P [...]
++!1;262>A&&!P;)ea();for(l=t=0;2>l;l++)t=(t<<5^p[l]&255)&8191}b=null;a=f=0;3>=G?(R=2,x=0):(x=2,z=0);c=!1}r=!0;if(0===A)return c=!0,0}l=Ka(d,e,h);if(l===h)return h;if(c)return l;if(3>=G)for(;0!==A&&null===b;){Ba();0!==s&&32506>=F-s&&(x=oa(s),x>A&&(x=A));if(3<=x)if(k=Ca(F-U,x-3),A-=x,x<=ka){x--;do F++,Ba();while(0!==--x);F++}else F+=x,x=0,t=p[F]&255,t=(t<<5^p[F+1]&255)&8191;else k=Ca(0,p[F]&255),A--,F++;k&&(Ha(0),v=F);for(;262>A&&!P;)ea()}else for(;0!==A&&null===b;){Ba();R=x;N=U;x=2;0!==s&& [...]
++F-s&&(x=oa(s),x>A&&(x=A),3===x&&4096<F-U&&x--);if(3<=R&&x<=R){k=Ca(F-1-N,R-3);A-=R-1;R-=2;do F++,Ba();while(0!==--R);z=0;x=2;F++;k&&(Ha(0),v=F)}else 0!==z?Ca(0,p[F-1]&255)&&(Ha(0),v=F):z=1,F++,A--;for(;262>A&&!P;)ea()}0===A&&(0!==z&&Ca(0,p[F-1]&255),Ha(1),c=!0);return l+Ka(d,l+e,h-l)};this.deflate=function(a,c){var f,e;ia=a;Ea=0;"undefined"===String(typeof c)&&(c=6);(f=c)?1>f?f=1:9<f&&(f=9):f=6;G=f;P=r=!1;if(null===d){q=b=h=null;d=[];d.length=m;p=[];p.length=65536;l=[];l.length=8192;u=[ [...]
++32832;B=[];B.length=65536;O=[];O.length=573;for(f=0;573>f;f++)O[f]=new g;ba=[];ba.length=61;for(f=0;61>f;f++)ba[f]=new g;K=[];K.length=288;for(f=0;288>f;f++)K[f]=new g;I=[];I.length=30;for(f=0;30>f;f++)I[f]=new g;C=[];C.length=39;for(f=0;39>f;f++)C[f]=new g;Y=new k;H=new k;X=new k;Q=[];Q.length=16;L=[];L.length=573;aa=[];aa.length=573;ma=[];ma.length=256;T=[];T.length=512;$=[];$.length=29;W=[];W.length=30;da=[];da.length=1024}var n=Array(1024),v=[],s=[];for(f=La(n,0,n.length);0<f;){s.le [...]
++0;e<f;e++)s[e]=String.fromCharCode(n[e]);v[v.length]=s.join("");f=La(n,0,n.length)}ia="";return v.join("")}};
++// Input 45
++runtime.loadClass("odf.Namespaces");
++gui.ImageSelector=function(g){function k(){var b=g.getSizer(),e,k;e=m.createElement("div");e.id="imageSelector";e.style.borderWidth="1px";b.appendChild(e);n.forEach(function(b){k=m.createElement("div");k.className=b;e.appendChild(k)});return e}var e=odf.Namespaces.svgns,n="topLeft topRight bottomRight bottomLeft topMiddle rightMiddle bottomMiddle leftMiddle".split(" "),m=g.getElement().ownerDocument,q=!1;this.select=function(b){var h,n,d=m.getElementById("imageSelector");d||(d=k());q=!0 [...]
++n=b.getBoundingClientRect();var f=h.getBoundingClientRect(),a=g.getZoomLevel();h=(n.left-f.left)/a-1;n=(n.top-f.top)/a-1;d.style.display="block";d.style.left=h+"px";d.style.top=n+"px";d.style.width=b.getAttributeNS(e,"width");d.style.height=b.getAttributeNS(e,"height")};this.clearSelection=function(){var b;q&&(b=m.getElementById("imageSelector"))&&(b.style.display="none");q=!1};this.isSelectorElement=function(b){var e=m.getElementById("imageSelector");return e?b===e||b.parentNode===e:!1}};
++// Input 46
++runtime.loadClass("odf.OdfCanvas");
++odf.CommandLineTools=function(){this.roundTrip=function(g,k,e){return new odf.OdfContainer(g,function(n){if(n.state===odf.OdfContainer.INVALID)return e("Document "+g+" is invalid.");n.state===odf.OdfContainer.DONE?n.saveAs(k,function(g){e(g)}):e("Document was not completely loaded.")})};this.render=function(g,k,e){for(k=k.getElementsByTagName("body")[0];k.firstChild;)k.removeChild(k.firstChild);k=new odf.OdfCanvas(k);k.addListener("statereadychange",function(g){e(g)});k.load(g)}};
++// Input 47
++/*
++
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ This file is part of WebODF.
++
++ WebODF is free software: you can redistribute it and/or modify it
++ under the terms of the GNU Affero General Public License (GNU AGPL)
++ as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version.
++
++ WebODF is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU Affero General Public License for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
++ @licend
++
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++ops.Member=function(g,k){var e={};this.getMemberId=function(){return g};this.getProperties=function(){return e};this.setProperties=function(g){Object.keys(g).forEach(function(k){e[k]=g[k]})};this.removeProperties=function(g){delete g.fullName;delete g.color;delete g.imageUrl;Object.keys(g).forEach(function(g){e.hasOwnProperty(g)&&delete e[g]})};runtime.assert(Boolean(g),"No memberId was supplied!");k.fullName||(k.fullName=runtime.tr("Unknown Author"));k.color||(k.color="black");k.imageU [...]
++"avatar-joe.png");e=k};
++// Input 48
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.OpRemoveBlob=function(){var g,l,c;this.init=function(m){g=m.memberid;l=m.timestamp;c=m.filename};this.isEdit=!0;this.execute=function(g){g.getOdfCanvas().odfContainer().removeBlob(c);return!0};this.spec=function(){return{optype:"RemoveBlob",memberid:g,timestamp:l,filename:c}}};
++runtime.loadClass("core.DomUtils");runtime.loadClass("core.PositionFilter");runtime.loadClass("odf.OdfUtils");
++(function(){function g(e,g,m){function q(a,c){function b(a){for(var c=0;a&&a.previousSibling;)c+=1,a=a.previousSibling;return c}this.steps=a;this.node=c;this.setIteratorPosition=function(a){a.setUnfilteredPosition(c.parentNode,b(c));do if(g.acceptPosition(a)===u)break;while(a.nextPosition())}}function b(a){return a.nodeType===Node.ELEMENT_NODE&&a.getAttributeNS(d,"nodeId")}function h(a){var c=k;a.setAttributeNS(d,"nodeId",c.toString());k+=1;return c}function r(c,f){var h,l=null;for(c=c. [...]
++c;!l&&c&&c!==e;)(h=b(c))&&(l=a[h])&&l.node!==c&&(runtime.log("Cloned node detected. Creating new bookmark"),l=null,c.removeAttributeNS(d,"nodeId")),c=c.parentNode;return l}var d="urn:webodf:names:steps",f={},a={},c=new odf.OdfUtils,p=new core.DomUtils,l,u=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.updateCache=function(d,e,l,g){var k;0===l&&c.isParagraph(e)?(k=!0,g||(d+=1)):e.hasChildNodes()&&e.childNodes[l]&&(e=e.childNodes[l],(k=c.isParagraph(e))&&(d+=1));k&&(l=b(e)||h(e),(g=a [...]
++e?g.steps=d:(runtime.log("Cloned node detected. Creating new bookmark"),l=h(e),g=a[l]=new q(d,e)):g=a[l]=new q(d,e),l=g,d=Math.ceil(l.steps/m)*m,e=f[d],!e||l.steps>e.steps)&&(f[d]=l)};this.setToClosestStep=function(a,c){for(var b=Math.floor(a/m)*m,d;!d&&0!==b;)d=f[b],b-=m;d=d||l;d.setIteratorPosition(c);return d.steps};this.setToClosestDomPoint=function(a,c,b){var d;if(a===e&&0===c)d=l;else if(a===e&&c===e.childNodes.length)d=Object.keys(f).map(function(a){return f[a]}).reduce(function( [...]
++a.steps?c:a},l);else if(d=r(a,c),!d)for(b.setUnfilteredPosition(a,c);!d&&b.previousNode();)d=r(b.container(),b.unfilteredDomOffset());d=d||l;d.setIteratorPosition(b);return d.steps};this.updateCacheAtPoint=function(c,d){var h={};Object.keys(a).map(function(c){return a[c]}).filter(function(a){return a.steps>c}).forEach(function(c){var l=Math.ceil(c.steps/m)*m,g,k;if(p.containsNode(e,c.node)){if(d(c),g=Math.ceil(c.steps/m)*m,k=h[g],!k||c.steps>k.steps)h[g]=c}else delete a[b(c.node)];f[l]= [...]
++Object.keys(h).forEach(function(a){f[a]=h[a]})};l=new function(a,c){this.steps=a;this.node=c;this.setIteratorPosition=function(a){a.setUnfilteredPosition(c,0);do if(g.acceptPosition(a)===u)break;while(a.nextPosition())}}(0,e)}var k=0;ops.StepsTranslator=function(e,k,m,q){function b(){var c=e();c!==r&&(runtime.log("Undo detected. Resetting steps cache"),r=c,d=new g(r,m,q),a=k(r))}function h(a,b){if(!b||m.acceptPosition(a)===c)return!0;for(;a.previousPosition();)if(m.acceptPosition(a)===c [...]
++a.unfilteredDomOffset()))return!0;break}for(;a.nextPosition();)if(m.acceptPosition(a)===c){if(b(1,a.container(),a.unfilteredDomOffset()))return!0;break}return!1}var r=e(),d=new g(r,m,q),f=new core.DomUtils,a=k(e()),c=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.convertStepsToDomPoint=function(f){var e,h;0>f&&(runtime.log("warn","Requested steps were negative ("+f+")"),f=0);b();for(e=d.setToClosestStep(f,a);e<f&&a.nextPosition();)(h=m.acceptPosition(a)===c)&&(e+=1),d.updateCache(e [...]
++a.unfilteredDomOffset(),h);e!==f&&runtime.log("warn","Requested "+f+" steps but only "+e+" are available");return{node:a.container(),offset:a.unfilteredDomOffset()}};this.convertDomPointToSteps=function(e,l,g){var k;b();f.containsNode(r,e)||(l=0>f.comparePoints(r,0,e,l),e=r,l=l?0:r.childNodes.length);a.setUnfilteredPosition(e,l);h(a,g)||a.setUnfilteredPosition(e,l);g=a.container();l=a.unfilteredDomOffset();e=d.setToClosestDomPoint(g,l,a);if(0>f.comparePoints(a.container(),a.unfilteredDo [...]
++g,l))return 0<e?e-1:e;for(;(a.container()!==g||a.unfilteredDomOffset()!==l)&&a.nextPosition();)(k=m.acceptPosition(a)===c)&&(e+=1),d.updateCache(e,a.container(),a.unfilteredDomOffset(),k);return e+0};this.prime=function(){var f,e;b();for(f=d.setToClosestStep(0,a);a.nextPosition();)(e=m.acceptPosition(a)===c)&&(f+=1),d.updateCache(f,a.container(),a.unfilteredDomOffset(),e)};this.handleStepsInserted=function(a){b();d.updateCacheAtPoint(a.position,function(c){c.steps+=a.length})};this.hand [...]
++function(a){b();d.updateCacheAtPoint(a.position,function(c){c.steps-=a.length;0>c.steps&&(c.steps=0)})}};ops.StepsTranslator.PREVIOUS_STEP=0;ops.StepsTranslator.NEXT_STEP=1;return ops.StepsTranslator})();
++// Input 49
++xmldom.RNG={};
++xmldom.RelaxNGParser=function(){function g(b,f){this.message=function(){f&&(b+=1===f.nodeType?" Element ":" Node ",b+=f.nodeName,f.nodeValue&&(b+=" with value '"+f.nodeValue+"'"),b+=".");return b}}function k(b){if(2>=b.e.length)return b;var f={name:b.name,e:b.e.slice(0,2)};return k({name:b.name,e:[f].concat(b.e.slice(2))})}function e(b){b=b.split(":",2);var f="",a;1===b.length?b=["",b[0]]:f=b[0];for(a in h)h[a]===f&&(b[0]=a);return b}function n(b,f){for(var a=0,c,h,l=b.name;b.e&&a<b.e.l [...]
++"ref"===c.name){h=f[c.a.name];if(!h)throw c.a.name+" was not defined.";c=b.e.slice(a+1);b.e=b.e.slice(0,a);b.e=b.e.concat(h.e);b.e=b.e.concat(c)}else a+=1,n(c,f);c=b.e;"choice"!==l||c&&c[1]&&"empty"!==c[1].name||(c&&c[0]&&"empty"!==c[0].name?(c[1]=c[0],c[0]={name:"empty"}):(delete b.e,b.name="empty"));if("group"===l||"interleave"===l)"empty"===c[0].name?"empty"===c[1].name?(delete b.e,b.name="empty"):(l=b.name=c[1].name,b.names=c[1].names,c=b.e=c[1].e):"empty"===c[1].name&&(l=b.name=c[0 [...]
++c[0].names,c=b.e=c[0].e);"oneOrMore"===l&&"empty"===c[0].name&&(delete b.e,b.name="empty");if("attribute"===l){h=b.names?b.names.length:0;for(var g,k=[],m=[],a=0;a<h;a+=1)g=e(b.names[a]),m[a]=g[0],k[a]=g[1];b.localnames=k;b.namespaces=m}"interleave"===l&&("interleave"===c[0].name?b.e="interleave"===c[1].name?c[0].e.concat(c[1].e):[c[1]].concat(c[0].e):"interleave"===c[1].name&&(b.e=[c[0]].concat(c[1].e)))}function m(b,f){for(var a=0,c;b.e&&a<b.e.length;)c=b.e[a],"elementref"===c.name?(c [...]
++0,b.e[a]=f[c.id]):"element"!==c.name&&m(c,f),a+=1}var q=this,b,h={"http://www.w3.org/XML/1998/namespace":"xml"},r;r=function(b,f,a){var c=[],g,l,m=b.localName,n=[];g=b.attributes;var q=m,y=n,v={},t,s;for(t=0;g&&t<g.length;t+=1)if(s=g.item(t),s.namespaceURI)"http://www.w3.org/2000/xmlns/"===s.namespaceURI&&(h[s.value]=s.localName);else{"name"!==s.localName||"element"!==q&&"attribute"!==q||y.push(s.value);if("name"===s.localName||"combine"===s.localName||"type"===s.localName){var N=s,z;z= [...]
++z.replace(/^\s\s*/,"");for(var x=/\s/,R=z.length-1;x.test(z.charAt(R));)R-=1;z=z.slice(0,R+1);N.value=z}v[s.localName]=s.value}g=v;g.combine=g.combine||void 0;b=b.firstChild;q=c;y=n;for(v="";b;){if(b.nodeType===Node.ELEMENT_NODE&&"http://relaxng.org/ns/structure/1.0"===b.namespaceURI){if(t=r(b,f,q))"name"===t.name?y.push(h[t.a.ns]+":"+t.text):"choice"===t.name&&t.names&&t.names.length&&(y=y.concat(t.names),delete t.names),q.push(t)}else b.nodeType===Node.TEXT_NODE&&(v+=b.nodeValue);b=b. [...]
++v;"value"!==m&&"param"!==m&&(b=/^\s*([\s\S]*\S)?\s*$/.exec(b)[1]);"value"===m&&void 0===g.type&&(g.type="token",g.datatypeLibrary="");"attribute"!==m&&"element"!==m||void 0===g.name||(l=e(g.name),c=[{name:"name",text:l[1],a:{ns:l[0]}}].concat(c),delete g.name);"name"===m||"nsName"===m||"value"===m?void 0===g.ns&&(g.ns=""):delete g.ns;"name"===m&&(l=e(b),g.ns=l[0],b=l[1]);1<c.length&&("define"===m||"oneOrMore"===m||"zeroOrMore"===m||"optional"===m||"list"===m||"mixed"===m)&&(c=[{name:"gr [...]
++e:c}).e}]);2<c.length&&"element"===m&&(c=[c[0]].concat({name:"group",e:k({name:"group",e:c.slice(1)}).e}));1===c.length&&"attribute"===m&&c.push({name:"text",text:b});1!==c.length||"choice"!==m&&"group"!==m&&"interleave"!==m?2<c.length&&("choice"===m||"group"===m||"interleave"===m)&&(c=k({name:m,e:c}).e):(m=c[0].name,n=c[0].names,g=c[0].a,b=c[0].text,c=c[0].e);"mixed"===m&&(m="interleave",c=[c[0],{name:"text"}]);"optional"===m&&(m="choice",c=[c[0],{name:"empty"}]);"zeroOrMore"===m&&(m=" [...]
++[{name:"oneOrMore",e:[c[0]]},{name:"empty"}]);if("define"===m&&g.combine){a:{q=g.combine;y=g.name;v=c;for(t=0;a&&t<a.length;t+=1)if(s=a[t],"define"===s.name&&s.a&&s.a.name===y){s.e=[{name:q,e:s.e.concat(v)}];a=s;break a}a=null}if(a)return null}a={name:m};c&&0<c.length&&(a.e=c);for(l in g)if(g.hasOwnProperty(l)){a.a=g;break}void 0!==b&&(a.text=b);n&&0<n.length&&(a.names=n);"element"===m&&(a.id=f.length,f.push(a),a={name:"elementref",id:a.id});return a};this.parseRelaxNGDOM=function(d,f){ [...]
++r(d&&d.documentElement,a,void 0),e,l,k={};for(e=0;e<c.e.length;e+=1)l=c.e[e],"define"===l.name?k[l.a.name]=l:"start"===l.name&&(b=l);if(!b)return[new g("No Relax NG start element was found.")];n(b,k);for(e in k)k.hasOwnProperty(e)&&n(k[e],k);for(e=0;e<a.length;e+=1)n(a[e],k);f&&(q.rootPattern=f(b.e[0],a));m(b,a);for(e=0;e<a.length;e+=1)m(a[e],a);q.start=b;q.elements=a;q.nsmap=h;return null}};
++// Input 50
++runtime.loadClass("core.Cursor");runtime.loadClass("gui.SelectionMover");
++ops.OdtCursor=function(g,k){var e=this,n={},m,q,b;this.removeFromOdtDocument=function(){b.remove()};this.move=function(b,g){var d=0;0<b?d=q.movePointForward(b,g):0>=b&&(d=-q.movePointBackward(-b,g));e.handleUpdate();return d};this.handleUpdate=function(){};this.getStepCounter=function(){return q.getStepCounter()};this.getMemberId=function(){return g};this.getNode=function(){return b.getNode()};this.getAnchorNode=function(){return b.getAnchorNode()};this.getSelectedRange=function(){retur [...]
++this.setSelectedRange=function(h,g){b.setSelectedRange(h,g);e.handleUpdate()};this.hasForwardSelection=function(){return b.hasForwardSelection()};this.getOdtDocument=function(){return k};this.getSelectionType=function(){return m};this.setSelectionType=function(b){n.hasOwnProperty(b)?m=b:runtime.log("Invalid selection type: "+b)};this.resetSelectionType=function(){e.setSelectionType(ops.OdtCursor.RangeSelection)};b=new core.Cursor(k.getDOM(),g);q=new gui.SelectionMover(b,k.getRootNode()) [...]
++!0;n[ops.OdtCursor.RegionSelection]=!0;e.resetSelectionType()};ops.OdtCursor.RangeSelection="Range";ops.OdtCursor.RegionSelection="Region";(function(){return ops.OdtCursor})();
+// Input 51
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.OpInsertImage=function(){var g,l,c,m,f,n,b,p,r=odf.Namespaces.drawns,d=odf.Namespaces.svgns,k=odf.Namespaces.textns,a=odf.Namespaces.xlinkns;this.init=function(a){g=a.memberid;l=a.timestamp;c=a.position;m=a.filename;f=a.frameWidth;n=a.frameHeight;b=a.frameStyleName;p=a.frameName};this.isEdit=!0;this.execute=function(e){var h=e.getOdfCanvas(),q=e.getTextNodeAtStep(c,g),u,x;if(!q)return!1;u=q.textNode;x=e.getParagraphElement(u);var q=q.offset!==u.length?u.splitText(q.offset):u.nextSib [...]
- y=v.createElementNS(r,"draw:image"),v=v.createElementNS(r,"draw:frame");y.setAttributeNS(a,"xlink:href",m);y.setAttributeNS(a,"xlink:type","simple");y.setAttributeNS(a,"xlink:show","embed");y.setAttributeNS(a,"xlink:actuate","onLoad");v.setAttributeNS(r,"draw:style-name",b);v.setAttributeNS(r,"draw:name",p);v.setAttributeNS(k,"text:anchor-type","as-char");v.setAttributeNS(d,"svg:width",f);v.setAttributeNS(d,"svg:height",n);v.appendChild(y);u.parentNode.insertBefore(v,q);e.emit(ops.OdtDo [...]
- {position:c,length:1});0===u.length&&u.parentNode.removeChild(u);h.addCssForFrameWithImage(v);h.refreshCSS();e.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:x,memberId:g,timeStamp:l});h.rerenderAnnotations();return!0};this.spec=function(){return{optype:"InsertImage",memberid:g,timestamp:l,filename:m,position:c,frameWidth:f,frameHeight:n,frameStyleName:b,frameName:p}}};
++runtime.loadClass("core.EventNotifier");runtime.loadClass("core.DomUtils");runtime.loadClass("odf.OdfUtils");runtime.loadClass("odf.Namespaces");runtime.loadClass("gui.SelectionMover");runtime.loadClass("core.PositionFilterChain");runtime.loadClass("ops.StepsTranslator");runtime.loadClass("ops.TextPositionFilter");runtime.loadClass("ops.Member");
++ops.OdtDocument=function(g){function k(){var a=g.odfContainer().getContentElement(),c=a&&a.localName;runtime.assert("text"===c,"Unsupported content element type '"+c+"' for OdtDocument");return a}function e(){return k().ownerDocument}function n(a){for(;a&&!(a.namespaceURI===odf.Namespaces.officens&&"text"===a.localName||a.namespaceURI===odf.Namespaces.officens&&"annotation"===a.localName);)a=a.parentNode;return a}function m(c){this.acceptPosition=function(b){b=b.container();var d;d="str [...]
++a[c].getNode():c;return n(b)===n(d)?l:u}}function q(a){var c=gui.SelectionMover.createPositionIterator(k());a=w.convertStepsToDomPoint(a);c.setUnfilteredPosition(a.node,a.offset);return c}function b(a,c){return g.getFormatting().getStyleElement(a,c)}function h(a){return b(a,"paragraph")}var r=this,d,f,a={},c={},p=new core.EventNotifier([ops.OdtDocument.signalMemberAdded,ops.OdtDocument.signalMemberUpdated,ops.OdtDocument.signalMemberRemoved,ops.OdtDocument.signalCursorAdded,ops.OdtDocum [...]
++ops.OdtDocument.signalCursorMoved,ops.OdtDocument.signalParagraphChanged,ops.OdtDocument.signalParagraphStyleModified,ops.OdtDocument.signalCommonStyleCreated,ops.OdtDocument.signalCommonStyleDeleted,ops.OdtDocument.signalTableAdded,ops.OdtDocument.signalOperationExecuted,ops.OdtDocument.signalUndoStackChanged,ops.OdtDocument.signalStepsInserted,ops.OdtDocument.signalStepsRemoved]),l=core.PositionFilter.FilterResult.FILTER_ACCEPT,u=core.PositionFilter.FilterResult.FILTER_REJECT,B,w,y;th [...]
++e;this.getRootElement=n;this.getIteratorAtPosition=q;this.convertDomPointToCursorStep=function(a,c,b){return w.convertDomPointToSteps(a,c,b)};this.convertDomToCursorRange=function(a,c){var b,d;b=c(a.anchorNode,a.anchorOffset);b=w.convertDomPointToSteps(a.anchorNode,a.anchorOffset,b);c||a.anchorNode!==a.focusNode||a.anchorOffset!==a.focusOffset?(d=c(a.focusNode,a.focusOffset),d=w.convertDomPointToSteps(a.focusNode,a.focusOffset,d)):d=b;return{position:b,length:d-b}};this.convertCursorToD [...]
++c){var b=e().createRange(),d,f;d=w.convertStepsToDomPoint(a);c?(f=w.convertStepsToDomPoint(a+c),0<c?(b.setStart(d.node,d.offset),b.setEnd(f.node,f.offset)):(b.setStart(f.node,f.offset),b.setEnd(d.node,d.offset))):b.setStart(d.node,d.offset);return b};this.getStyleElement=b;this.upgradeWhitespacesAtPosition=function(a){a=q(a);var c,b,f;a.previousPosition();a.previousPosition();for(f=-1;1>=f;f+=1){c=a.container();b=a.unfilteredDomOffset();if(c.nodeType===Node.TEXT_NODE&&" "===c.data[b]&&d [...]
++b)){runtime.assert(" "===c.data[b],"upgradeWhitespaceToElement: textNode.data[offset] should be a literal space");var e=c.ownerDocument.createElementNS(odf.Namespaces.textns,"text:s");e.appendChild(c.ownerDocument.createTextNode(" "));c.deleteData(b,1);0<b&&(c=c.splitText(b));c.parentNode.insertBefore(e,c);c=e;a.moveToEndOfNode(c)}a.nextPosition()}};this.downgradeWhitespacesAtPosition=function(a){var c=q(a),b;a=c.container();for(c=c.unfilteredDomOffset();!d.isCharacterElement(a)&&a.chil [...]
++a.childNodes[c],c=0;a.nodeType===Node.TEXT_NODE&&(a=a.parentNode);d.isDowngradableSpaceElement(a)&&(c=a.firstChild,b=a.lastChild,f.mergeIntoParent(a),b!==c&&f.normalizeTextNodes(b),f.normalizeTextNodes(c))};this.getParagraphStyleElement=h;this.getParagraphElement=function(a){return d.getParagraphElement(a)};this.getParagraphStyleAttributes=function(a){return(a=h(a))?g.getFormatting().getInheritedStyleAttributes(a):null};this.getTextNodeAtStep=function(c,b){var d=q(c),f=d.container(),h,g [...]
++f.nodeType===Node.TEXT_NODE?(h=f,g=d.unfilteredDomOffset()):(h=e().createTextNode(""),g=0,f.insertBefore(h,d.rightNode()));if(b&&a[b]&&r.getCursorPosition(b)===c){for(l=a[b].getNode();l.nextSibling&&"cursor"===l.nextSibling.localName;)l.parentNode.insertBefore(l.nextSibling,l);0<h.length&&h.nextSibling!==l&&(h=e().createTextNode(""),g=0);l.parentNode.insertBefore(h,l)}for(;h.previousSibling&&h.previousSibling.nodeType===Node.TEXT_NODE;)h.previousSibling.appendData(h.data),g=h.previousSi [...]
++h=h.previousSibling,h.parentNode.removeChild(h.nextSibling);return{textNode:h,offset:g}};this.fixCursorPositions=function(){var c=new core.PositionFilterChain;c.addFilter("BaseFilter",B);Object.keys(a).forEach(function(b){var d=a[b],f=d.getStepCounter(),e,h,g=!1;c.addFilter("RootFilter",r.createRootFilter(b));b=f.countStepsToPosition(d.getAnchorNode(),0,c);f.isPositionWalkable(c)?0===b&&(g=!0,d.move(0)):(g=!0,e=f.countPositionsToNearestStep(d.getNode(),0,c),h=f.countPositionsToNearestSt [...]
++0,c),d.move(e),0!==b&&(0<h&&(b+=1),0<e&&(b-=1),f=f.countSteps(b,c),d.move(f),d.move(-f,!0)));g&&r.emit(ops.OdtDocument.signalCursorMoved,d);c.removeFilter("RootFilter")})};this.getDistanceFromCursor=function(c,b,d){c=a[c];var f,e;runtime.assert(null!==b&&void 0!==b,"OdtDocument.getDistanceFromCursor called without node");c&&(f=w.convertDomPointToSteps(c.getNode(),0),e=w.convertDomPointToSteps(b,d));return e-f};this.getCursorPosition=function(c){return(c=a[c])?w.convertDomPointToSteps(c. [...]
++0):0};this.getCursorSelection=function(c){c=a[c];var b=0,d=0;c&&(b=w.convertDomPointToSteps(c.getNode(),0),d=w.convertDomPointToSteps(c.getAnchorNode(),0));return{position:d,length:b-d}};this.getPositionFilter=function(){return B};this.getOdfCanvas=function(){return g};this.getRootNode=k;this.addMember=function(a){runtime.assert(void 0===c[a.getMemberId()],"This member already exists");c[a.getMemberId()]=a};this.getMember=function(a){return c.hasOwnProperty(a)?c[a]:null};this.removeMemb [...]
++this.getCursor=function(c){return a[c]};this.getCursors=function(){var c=[],b;for(b in a)a.hasOwnProperty(b)&&c.push(a[b]);return c};this.addCursor=function(c){runtime.assert(Boolean(c),"OdtDocument::addCursor without cursor");var b=c.getStepCounter().countSteps(1,B),d=c.getMemberId();runtime.assert("string"===typeof d,"OdtDocument::addCursor has cursor without memberid");runtime.assert(!a[d],"OdtDocument::addCursor is adding a duplicate cursor with memberid "+d);c.move(b);a[d]=c};this. [...]
++function(c){var b=a[c];return b?(b.removeFromOdtDocument(),delete a[c],r.emit(ops.OdtDocument.signalCursorRemoved,c),!0):!1};this.getFormatting=function(){return g.getFormatting()};this.emit=function(a,c){p.emit(a,c)};this.subscribe=function(a,c){p.subscribe(a,c)};this.unsubscribe=function(a,c){p.unsubscribe(a,c)};this.createRootFilter=function(a){return new m(a)};this.close=function(a){a()};this.destroy=function(a){a()};B=new ops.TextPositionFilter(k);d=new odf.OdfUtils;f=new core.DomU [...]
++gui.SelectionMover.createPositionIterator,B,500);p.subscribe(ops.OdtDocument.signalStepsInserted,w.handleStepsInserted);p.subscribe(ops.OdtDocument.signalStepsRemoved,w.handleStepsRemoved);p.subscribe(ops.OdtDocument.signalOperationExecuted,function(a){var c=a.spec(),b=c.memberid,c=(new Date(c.timestamp)).toISOString(),d=g.odfContainer().getMetadataManager();a.isEdit&&(b=r.getMember(b).getProperties().fullName,d.setMetadata({"dc:creator":b,"dc:date":c},null),y||(d.incrementEditingCycles [...]
++["meta:editing-duration","meta:document-statistic"])),y=a)})};ops.OdtDocument.signalMemberAdded="member/added";ops.OdtDocument.signalMemberUpdated="member/updated";ops.OdtDocument.signalMemberRemoved="member/removed";ops.OdtDocument.signalCursorAdded="cursor/added";ops.OdtDocument.signalCursorRemoved="cursor/removed";ops.OdtDocument.signalCursorMoved="cursor/moved";ops.OdtDocument.signalParagraphChanged="paragraph/changed";ops.OdtDocument.signalTableAdded="table/added";
++ops.OdtDocument.signalCommonStyleCreated="style/created";ops.OdtDocument.signalCommonStyleDeleted="style/deleted";ops.OdtDocument.signalParagraphStyleModified="paragraphstyle/modified";ops.OdtDocument.signalOperationExecuted="operation/executed";ops.OdtDocument.signalUndoStackChanged="undo/changed";ops.OdtDocument.signalStepsInserted="steps/inserted";ops.OdtDocument.signalStepsRemoved="steps/removed";(function(){return ops.OdtDocument})();
+// Input 52
+/*
+
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.OpInsertTable=function(){function g(b,a){var c;if(1===d.length)c=d[0];else if(3===d.length)switch(b){case 0:c=d[0];break;case m-1:c=d[2];break;default:c=d[1]}else c=d[b];if(1===c.length)return c[0];if(3===c.length)switch(a){case 0:return c[0];case f-1:return c[2];default:return c[1]}return c[a]}var l,c,m,f,n,b,p,r,d;this.init=function(k){l=k.memberid;c=k.timestamp;n=k.position;m=k.initialRows;f=k.initialColumns;b=k.tableName;p=k.tableStyleName;r=k.tableColumnStyleName;d=k.tableCellS [...]
- this.isEdit=!0;this.execute=function(d){var a=d.getTextNodeAtStep(n),e=d.getRootNode();if(a){var h=d.getDOM(),q=h.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table"),u=h.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table-column"),x,v,y,w;p&&q.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:style-name",p);b&&q.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:name",b);u.setAttributeNS(" [...]
- "table:number-columns-repeated",f);r&&u.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:style-name",r);q.appendChild(u);for(y=0;y<m;y+=1){u=h.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table-row");for(w=0;w<f;w+=1)x=h.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table-cell"),(v=g(y,w))&&x.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:style-name",v),v=h.createElementNS("urn:oasis:n [...]
- "text:p"),x.appendChild(v),u.appendChild(x);q.appendChild(u)}a=d.getParagraphElement(a.textNode);e.insertBefore(q,a.nextSibling);d.emit(ops.OdtDocument.signalStepsInserted,{position:n,length:f*m+1});d.getOdfCanvas().refreshSize();d.emit(ops.OdtDocument.signalTableAdded,{tableElement:q,memberId:l,timeStamp:c});d.getOdfCanvas().rerenderAnnotations();return!0}return!1};this.spec=function(){return{optype:"InsertTable",memberid:l,timestamp:c,position:n,initialRows:m,initialColumns:f,tableNam [...]
- tableColumnStyleName:r,tableCellStyleMatrix:d}}};
++ops.Operation=function(){};ops.Operation.prototype.init=function(g){};ops.Operation.prototype.execute=function(g){};ops.Operation.prototype.spec=function(){};
+// Input 53
++runtime.loadClass("xmldom.RelaxNGParser");
++xmldom.RelaxNG=function(){function g(a){return function(){var c;return function(){void 0===c&&(c=a());return c}}()}function k(a,c){return function(){var b={},d=0;return function(f){var e=f.hash||f.toString();if(b.hasOwnProperty(e))return b[e];b[e]=f=c(f);f.hash=a+d.toString();d+=1;return f}}()}function e(a){return function(){var c={};return function(b){var d,f;if(c.hasOwnProperty(b.localName)){if(f=c[b.localName],d=f[b.namespaceURI],void 0!==d)return d}else c[b.localName]=f={};return f[ [...]
++d=a(b)}}()}function n(a,c,b){return function(){var d={},f=0;return function(e,h){var g=c&&c(e,h),l;if(void 0!==g)return g;l=e.hash||e.toString();g=h.hash||h.toString();if(d.hasOwnProperty(l)){if(l=d[l],l.hasOwnProperty(g))return l[g]}else d[l]=l={};l[g]=g=b(e,h);g.hash=a+f.toString();f+=1;return g}}()}function m(a,c){"choice"===c.p1.type?m(a,c.p1):a[c.p1.hash]=c.p1;"choice"===c.p2.type?m(a,c.p2):a[c.p2.hash]=c.p2}function q(a,c){return{type:"element",nc:a,nullable:!1,textDeriv:function( [...]
++startTagOpenDeriv:function(b){return a.contains(b)?p(c,x):z},attDeriv:function(){return z},startTagCloseDeriv:function(){return this}}}function b(){return{type:"list",nullable:!1,hash:"list",textDeriv:function(){return x}}}function h(a,c,b,f){if(c===z)return z;if(f>=b.length)return c;0===f&&(f=0);for(var e=b.item(f);e.namespaceURI===d;){f+=1;if(f>=b.length)return c;e=b.item(f)}return e=h(a,c.attDeriv(a,b.item(f)),b,f+1)}function r(a,c,b){b.e[0].a?(a.push(b.e[0].text),c.push(b.e[0].a.ns) [...]
++b.e[1].a?(a.push(b.e[1].text),c.push(b.e[1].a.ns)):r(a,c,b.e[1])}var d="http://www.w3.org/2000/xmlns/",f,a,c,p,l,u,B,w,y,v,t,s,N,z={type:"notAllowed",nullable:!1,hash:"notAllowed",nc:void 0,p:void 0,p1:void 0,p2:void 0,textDeriv:function(){return z},startTagOpenDeriv:function(){return z},attDeriv:function(){return z},startTagCloseDeriv:function(){return z},endTagDeriv:function(){return z}},x={type:"empty",nullable:!0,hash:"empty",nc:void 0,p:void 0,p1:void 0,p2:void 0,textDeriv:function [...]
++startTagOpenDeriv:function(){return z},attDeriv:function(){return z},startTagCloseDeriv:function(){return x},endTagDeriv:function(){return z}},R={type:"text",nullable:!0,hash:"text",nc:void 0,p:void 0,p1:void 0,p2:void 0,textDeriv:function(){return R},startTagOpenDeriv:function(){return z},attDeriv:function(){return z},startTagCloseDeriv:function(){return R},endTagDeriv:function(){return z}};f=n("choice",function(a,c){if(a===z)return c;if(c===z||a===c)return a},function(a,c){var b={},d; [...]
++p2:c});c=a=void 0;for(d in b)b.hasOwnProperty(d)&&(void 0===a?a=b[d]:c=void 0===c?b[d]:f(c,b[d]));return function(a,c){return{type:"choice",nullable:a.nullable||c.nullable,hash:void 0,nc:void 0,p:void 0,p1:a,p2:c,textDeriv:function(b,d){return f(a.textDeriv(b,d),c.textDeriv(b,d))},startTagOpenDeriv:e(function(b){return f(a.startTagOpenDeriv(b),c.startTagOpenDeriv(b))}),attDeriv:function(b,d){return f(a.attDeriv(b,d),c.attDeriv(b,d))},startTagCloseDeriv:g(function(){return f(a.startTagCl [...]
++c.startTagCloseDeriv())}),endTagDeriv:g(function(){return f(a.endTagDeriv(),c.endTagDeriv())})}}(a,c)});a=function(a,c,b){return function(){var d={},f=0;return function(e,h){var g=c&&c(e,h),l,k;if(void 0!==g)return g;l=e.hash||e.toString();g=h.hash||h.toString();l<g&&(k=l,l=g,g=k,k=e,e=h,h=k);if(d.hasOwnProperty(l)){if(l=d[l],l.hasOwnProperty(g))return l[g]}else d[l]=l={};l[g]=g=b(e,h);g.hash=a+f.toString();f+=1;return g}}()}("interleave",function(a,c){if(a===z||c===z)return z;if(a===x) [...]
++x)return a},function(c,b){return{type:"interleave",nullable:c.nullable&&b.nullable,hash:void 0,p1:c,p2:b,textDeriv:function(d,e){return f(a(c.textDeriv(d,e),b),a(c,b.textDeriv(d,e)))},startTagOpenDeriv:e(function(d){return f(t(function(c){return a(c,b)},c.startTagOpenDeriv(d)),t(function(b){return a(c,b)},b.startTagOpenDeriv(d)))}),attDeriv:function(d,e){return f(a(c.attDeriv(d,e),b),a(c,b.attDeriv(d,e)))},startTagCloseDeriv:g(function(){return a(c.startTagCloseDeriv(),b.startTagCloseDe [...]
++c=n("group",function(a,c){if(a===z||c===z)return z;if(a===x)return c;if(c===x)return a},function(a,b){return{type:"group",p1:a,p2:b,nullable:a.nullable&&b.nullable,textDeriv:function(d,e){var h=c(a.textDeriv(d,e),b);return a.nullable?f(h,b.textDeriv(d,e)):h},startTagOpenDeriv:function(d){var e=t(function(a){return c(a,b)},a.startTagOpenDeriv(d));return a.nullable?f(e,b.startTagOpenDeriv(d)):e},attDeriv:function(d,e){return f(c(a.attDeriv(d,e),b),c(a,b.attDeriv(d,e)))},startTagCloseDeriv [...]
++b.startTagCloseDeriv())})}});p=n("after",function(a,c){if(a===z||c===z)return z},function(a,c){return{type:"after",p1:a,p2:c,nullable:!1,textDeriv:function(b,d){return p(a.textDeriv(b,d),c)},startTagOpenDeriv:e(function(b){return t(function(a){return p(a,c)},a.startTagOpenDeriv(b))}),attDeriv:function(b,d){return p(a.attDeriv(b,d),c)},startTagCloseDeriv:g(function(){return p(a.startTagCloseDeriv(),c)}),endTagDeriv:g(function(){return a.nullable?c:z})}});l=k("oneormore",function(a){retur [...]
++{type:"oneOrMore",p:a,nullable:a.nullable,textDeriv:function(b,d){return c(a.textDeriv(b,d),f(this,x))},startTagOpenDeriv:function(b){var d=this;return t(function(a){return c(a,f(d,x))},a.startTagOpenDeriv(b))},attDeriv:function(b,d){return c(a.attDeriv(b,d),f(this,x))},startTagCloseDeriv:g(function(){return l(a.startTagCloseDeriv())})}});B=n("attribute",void 0,function(a,c){return{type:"attribute",nullable:!1,hash:void 0,nc:a,p:c,p1:void 0,p2:void 0,textDeriv:void 0,startTagOpenDeriv:v [...]
++d){return a.contains(d)&&(c.nullable&&/^\s+$/.test(d.nodeValue)||c.textDeriv(b,d.nodeValue).nullable)?x:z},startTagCloseDeriv:function(){return z},endTagDeriv:void 0}});u=k("value",function(a){return{type:"value",nullable:!1,value:a,textDeriv:function(c,b){return b===a?x:z},attDeriv:function(){return z},startTagCloseDeriv:function(){return this}}});y=k("data",function(a){return{type:"data",nullable:!1,dataType:a,textDeriv:function(){return x},attDeriv:function(){return z},startTagCloseD [...]
++t=function U(a,c){return"after"===c.type?p(c.p1,a(c.p2)):"choice"===c.type?f(U(a,c.p1),U(a,c.p2)):c};s=function(a,c,b){var d=b.currentNode;c=c.startTagOpenDeriv(d);c=h(a,c,d.attributes,0);var e=c=c.startTagCloseDeriv(),d=b.currentNode;c=b.firstChild();for(var g=[],l;c;)c.nodeType===Node.ELEMENT_NODE?g.push(c):c.nodeType!==Node.TEXT_NODE||/^\s*$/.test(c.nodeValue)||g.push(c.nodeValue),c=b.nextSibling();0===g.length&&(g=[""]);l=e;for(e=0;l!==z&&e<g.length;e+=1)c=g[e],"string"===typeof c?l [...]
++f(l,l.textDeriv(a,c)):l.textDeriv(a,c):(b.currentNode=c,l=s(a,l,b));b.currentNode=d;return c=l.endTagDeriv()};w=function(a){var c,b,d;if("name"===a.name)c=a.text,b=a.a.ns,a={name:c,ns:b,hash:"{"+b+"}"+c,contains:function(a){return a.namespaceURI===b&&a.localName===c}};else if("choice"===a.name){c=[];b=[];r(c,b,a);a="";for(d=0;d<c.length;d+=1)a+="{"+b[d]+"}"+c[d]+",";a={hash:a,contains:function(a){var d;for(d=0;d<c.length;d+=1)if(c[d]===a.localName&&b[d]===a.namespaceURI)return!0;return! [...]
++{hash:"anyName",contains:function(){return!0}};return a};v=function P(d,e){var h,g;if("elementref"===d.name){h=d.id||0;d=e[h];if(void 0!==d.name){var k=d;h=e[k.id]={hash:"element"+k.id.toString()};k=q(w(k.e[0]),v(k.e[1],e));for(g in k)k.hasOwnProperty(g)&&(h[g]=k[g]);return h}return d}switch(d.name){case "empty":return x;case "notAllowed":return z;case "text":return R;case "choice":return f(P(d.e[0],e),P(d.e[1],e));case "interleave":h=P(d.e[0],e);for(g=1;g<d.e.length;g+=1)h=a(h,P(d.e[g] [...]
++case "group":return c(P(d.e[0],e),P(d.e[1],e));case "oneOrMore":return l(P(d.e[0],e));case "attribute":return B(w(d.e[0]),P(d.e[1],e));case "value":return u(d.text);case "data":return h=d.a&&d.a.type,void 0===h&&(h=""),y(h);case "list":return b()}throw"No support for "+d.name;};this.makePattern=function(a,c){var b={},d;for(d in c)c.hasOwnProperty(d)&&(b[d]=c[d]);return d=v(a,b)};this.validate=function(a,c){var b;a.currentNode=a.root;b=s(null,N,a);b.nullable?c(null):(runtime.log("Error i [...]
++b),c(["Error in Relax NG validation: "+b]))};this.init=function(a){N=a}};
++// Input 54
++runtime.loadClass("xmldom.RelaxNGParser");
++xmldom.RelaxNG2=function(){function g(b,e){this.message=function(){e&&(b+=e.nodeType===Node.ELEMENT_NODE?" Element ":" Node ",b+=e.nodeName,e.nodeValue&&(b+=" with value '"+e.nodeValue+"'"),b+=".");return b}}function k(b,e,g,d){return"empty"===b.name?null:m(b,e,g,d)}function e(b,e){if(2!==b.e.length)throw"Element with wrong # of elements: "+b.e.length;for(var m=e.currentNode,d=m?m.nodeType:0,f=null;d>Node.ELEMENT_NODE;){if(d!==Node.COMMENT_NODE&&(d!==Node.TEXT_NODE||!/^\s+$/.test(e.curr [...]
++d+".")];d=(m=e.nextSibling())?m.nodeType:0}if(!m)return[new g("Missing element "+b.names)];if(b.names&&-1===b.names.indexOf(q[m.namespaceURI]+":"+m.localName))return[new g("Found "+m.nodeName+" instead of "+b.names+".",m)];if(e.firstChild()){for(f=k(b.e[1],e,m);e.nextSibling();)if(d=e.currentNode.nodeType,!(e.currentNode&&e.currentNode.nodeType===Node.TEXT_NODE&&/^\s+$/.test(e.currentNode.nodeValue)||d===Node.COMMENT_NODE))return[new g("Spurious content.",e.currentNode)];if(e.parentNode [...]
++k(b.e[1],e,m);e.nextSibling();return f}var n,m,q;m=function(b,h,n,d){var f=b.name,a=null;if("text"===f)a:{for(var c=(b=h.currentNode)?b.nodeType:0;b!==n&&3!==c;){if(1===c){a=[new g("Element not allowed here.",b)];break a}c=(b=h.nextSibling())?b.nodeType:0}h.nextSibling();a=null}else if("data"===f)a=null;else if("value"===f)d!==b.text&&(a=[new g("Wrong value, should be '"+b.text+"', not '"+d+"'",n)]);else if("list"===f)a=null;else if("attribute"===f)a:{if(2!==b.e.length)throw"Attribute w [...]
++b.e.length;f=b.localnames.length;for(a=0;a<f;a+=1){d=n.getAttributeNS(b.namespaces[a],b.localnames[a]);""!==d||n.hasAttributeNS(b.namespaces[a],b.localnames[a])||(d=void 0);if(void 0!==c&&void 0!==d){a=[new g("Attribute defined too often.",n)];break a}c=d}a=void 0===c?[new g("Attribute not found: "+b.names,n)]:k(b.e[1],h,n,c)}else if("element"===f)a=e(b,h);else if("oneOrMore"===f){d=0;do c=h.currentNode,f=m(b.e[0],h,n),d+=1;while(!f&&c!==h.currentNode);1<d?(h.currentNode=c,a=null):a=f}e [...]
++f){if(2!==b.e.length)throw"Choice with wrong # of options: "+b.e.length;c=h.currentNode;if("empty"===b.e[0].name){if(f=m(b.e[1],h,n,d))h.currentNode=c;a=null}else{if(f=k(b.e[0],h,n,d))h.currentNode=c,f=m(b.e[1],h,n,d);a=f}}else if("group"===f){if(2!==b.e.length)throw"Group with wrong # of members: "+b.e.length;a=m(b.e[0],h,n)||m(b.e[1],h,n)}else if("interleave"===f)a:{c=b.e.length;d=[c];for(var p=c,l,q,B,w;0<p;){l=0;q=h.currentNode;for(a=0;a<c;a+=1)B=h.currentNode,!0!==d[a]&&d[a]!==B&&( [...]
++m(w,h,n))?(h.currentNode=B,void 0===d[a]&&(d[a]=!1)):B===h.currentNode||"oneOrMore"===w.name||"choice"===w.name&&("oneOrMore"===w.e[0].name||"oneOrMore"===w.e[1].name)?(l+=1,d[a]=B):(l+=1,d[a]=!0));if(q===h.currentNode&&l===p){a=null;break a}if(0===l){for(a=0;a<c;a+=1)if(!1===d[a]){a=[new g("Interleave does not match.",n)];break a}a=null;break a}for(a=p=0;a<c;a+=1)!0!==d[a]&&(p+=1)}a=null}else throw f+" not allowed in nonEmptyPattern.";return a};this.validate=function(b,e){b.currentNode [...]
++k(n.e[0],b,b.root);e(g)};this.init=function(b,e){n=b;q=e}};
++// Input 55
++runtime.loadClass("core.DomUtils");runtime.loadClass("gui.Avatar");runtime.loadClass("ops.OdtCursor");
++gui.Caret=function(g,k,e){function n(d){f&&r.parentNode&&(!a||d)&&(d&&void 0!==c&&runtime.clearTimeout(c),a=!0,b.style.opacity=d||"0"===b.style.opacity?"1":"0",c=runtime.setTimeout(function(){a=!1;n(!1)},500))}function m(a,c){var b=a.getBoundingClientRect(),d=0,f=0;b&&c&&(d=Math.max(b.top,c.top),f=Math.min(b.bottom,c.bottom));return f-d}function q(){var a;a=g.getSelectedRange().cloneRange();var c=g.getNode(),f,e=null;c.previousSibling&&(f=c.previousSibling.nodeType===Node.TEXT_NODE?c.pr [...]
++c.previousSibling.childNodes.length,a.setStart(c.previousSibling,0<f?f-1:0),a.setEnd(c.previousSibling,f),(f=a.getBoundingClientRect())&&f.height&&(e=f));c.nextSibling&&(a.setStart(c.nextSibling,0),a.setEnd(c.nextSibling,0<(c.nextSibling.nodeType===Node.TEXT_NODE?c.nextSibling.textContent.length:c.nextSibling.childNodes.length)?1:0),(f=a.getBoundingClientRect())&&f.height&&(!e||m(c,f)>m(c,e))&&(e=f));a=e;c=g.getOdtDocument().getOdfCanvas().getZoomLevel();d&&g.getSelectionType()===ops.Od [...]
++b.style.visibility="visible":b.style.visibility="hidden";a?(b.style.top="0",e=p.getBoundingClientRect(b),8>a.height&&(a={top:a.top-(8-a.height)/2,height:8}),b.style.height=p.adaptRangeDifferenceToZoomLevel(a.height,c)+"px",b.style.top=p.adaptRangeDifferenceToZoomLevel(a.top-e.top,c)+"px"):(b.style.height="1em",b.style.top="5%")}var b,h,r,d=!0,f=!1,a=!1,c,p=new core.DomUtils;this.handleUpdate=q;this.refreshCursorBlinking=function(){e||g.getSelectedRange().collapsed?(f=!0,n(!0)):(f=!1,b.s [...]
++"0")};this.setFocus=function(){f=!0;h.markAsFocussed(!0);n(!0)};this.removeFocus=function(){f=!1;h.markAsFocussed(!1);b.style.opacity="1"};this.show=function(){d=!0;q();h.markAsFocussed(!0)};this.hide=function(){d=!1;q();h.markAsFocussed(!1)};this.setAvatarImageUrl=function(a){h.setImageUrl(a)};this.setColor=function(a){b.style.borderColor=a;h.setColor(a)};this.getCursor=function(){return g};this.getFocusElement=function(){return b};this.toggleHandleVisibility=function(){h.isVisible()?h [...]
++this.showHandle=function(){h.show()};this.hideHandle=function(){h.hide()};this.ensureVisible=function(){var a,c,d,f,e=g.getOdtDocument().getOdfCanvas().getElement().parentNode,h;d=e.offsetWidth-e.clientWidth+5;f=e.offsetHeight-e.clientHeight+5;h=b.getBoundingClientRect();a=h.left-d;c=h.top-f;d=h.right+d;f=h.bottom+f;h=e.getBoundingClientRect();c<h.top?e.scrollTop-=h.top-c:f>h.bottom&&(e.scrollTop+=f-h.bottom);a<h.left?e.scrollLeft-=h.left-a:d>h.right&&(e.scrollLeft+=d-h.right);q()};this [...]
++a(c):(r.removeChild(b),a())})};(function(){var a=g.getOdtDocument().getDOM();b=a.createElementNS(a.documentElement.namespaceURI,"span");b.style.top="5%";r=g.getNode();r.appendChild(b);h=new gui.Avatar(r,k);q()})()};
++// Input 56
++gui.EventManager=function(g){function k(){var b=this,a=[];this.handlers=[];this.isSubscribed=!1;this.handleEvent=function(c){-1===a.indexOf(c)&&(a.push(c),b.handlers.forEach(function(a){a(c)}),runtime.setTimeout(function(){a.splice(a.indexOf(c),1)},0))}}function e(b){var a=b.scrollX,c=b.scrollY;this.restore=function(){b.scrollX===a&&b.scrollY===c||b.scrollTo(a,c)}}function n(b){var a=b.scrollTop,c=b.scrollLeft;this.restore=function(){if(b.scrollTop!==a||b.scrollLeft!==c)b.scrollTop=a,b. [...]
++c}}function m(b,a,c){var d="on"+a,e=!1;b.attachEvent&&(e=b.attachEvent(d,c));!e&&b.addEventListener&&(b.addEventListener(a,c,!1),e=!0);e&&!r[a]||!b.hasOwnProperty(d)||(b[d]=c)}function q(){return g.getDOM().activeElement===b}var b=g.getOdfCanvas().getElement(),h=runtime.getWindow(),r={beforecut:!0,beforepaste:!0},d;this.subscribe=function(f,a){var c=h&&d[f];c?(c.handlers.push(a),c.isSubscribed||(c.isSubscribed=!0,m(h,f,c.handleEvent),m(b,f,c.handleEvent))):m(b,f,a)};this.unsubscribe=fun [...]
++h&&d[f],e=c&&c.handlers.indexOf(a);c?-1!==e&&c.handlers.splice(e,1):(c=b,e="on"+f,c.detachEvent&&c.detachEvent(e,a),c.removeEventListener&&c.removeEventListener(f,a,!1),c[e]===a&&(c[e]=null))};this.hasFocus=q;this.focus=function(){var d;if(!q()){for(d=b;d&&!d.scrollTop&&!d.scrollLeft;)d=d.parentNode;d=d?new n(d):h?new e(h):null;b.focus();d&&d.restore()}};d={mousedown:new k,mouseup:new k}};
++// Input 57
++runtime.loadClass("gui.SelectionMover");gui.ShadowCursor=function(g){var k=g.getDOM().createRange(),e=!0;this.removeFromOdtDocument=function(){};this.getMemberId=function(){return gui.ShadowCursor.ShadowCursorMemberId};this.getSelectedRange=function(){return k};this.setSelectedRange=function(g,m){k=g;e=!1!==m};this.hasForwardSelection=function(){return e};this.getOdtDocument=function(){return g};this.getSelectionType=function(){return ops.OdtCursor.RangeSelection};k.setStart(g.getRootNo [...]
++gui.ShadowCursor.ShadowCursorMemberId="";(function(){return gui.ShadowCursor})();
++// Input 58
+/*
+
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.OpInsertText=function(){var g,l,c,m;this.init=function(f){g=f.memberid;l=f.timestamp;c=f.position;m=f.text};this.isEdit=!0;this.execute=function(f){var n,b,p,r=null,d=f.getDOM(),k,a=0,e,h;f.upgradeWhitespacesAtPosition(c);if(n=f.getTextNodeAtStep(c,g)){b=n.textNode;r=b.nextSibling;p=b.parentNode;k=f.getParagraphElement(b);for(h=0;h<m.length;h+=1)if(" "===m[h]&&(0===h||h===m.length-1||" "===m[h-1])||"\t"===m[h])0===a?(n.offset!==b.length&&(r=b.splitText(n.offset)),0<h&&b.appendData(m [...]
- h))):a<h&&(a=m.substring(a,h),p.insertBefore(d.createTextNode(a),r)),a=h+1,e=" "===m[h]?"text:s":"text:tab",e=d.createElementNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0",e),e.appendChild(d.createTextNode(m[h])),p.insertBefore(e,r);0===a?b.insertData(n.offset,m):a<m.length&&(n=m.substring(a),p.insertBefore(d.createTextNode(n),r));p=b.parentNode;r=b.nextSibling;p.removeChild(b);p.insertBefore(b,r);0===b.length&&b.parentNode.removeChild(b);f.emit(ops.OdtDocument.signalStepsInserted, [...]
- length:m.length});0<c&&(1<c&&f.downgradeWhitespacesAtPosition(c-2),f.downgradeWhitespacesAtPosition(c-1));f.downgradeWhitespacesAtPosition(c);f.downgradeWhitespacesAtPosition(c+m.length-1);f.downgradeWhitespacesAtPosition(c+m.length);f.getOdfCanvas().refreshSize();f.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:k,memberId:g,timeStamp:l});f.getOdfCanvas().rerenderAnnotations();return!0}return!1};this.spec=function(){return{optype:"InsertText",memberid:g,timestamp:l,positi [...]
- // Input 54
++gui.UndoManager=function(){};gui.UndoManager.prototype.subscribe=function(g,k){};gui.UndoManager.prototype.unsubscribe=function(g,k){};gui.UndoManager.prototype.setOdtDocument=function(g){};gui.UndoManager.prototype.saveInitialState=function(){};gui.UndoManager.prototype.resetInitialState=function(){};gui.UndoManager.prototype.setPlaybackFunction=function(g){};gui.UndoManager.prototype.hasUndoStates=function(){};gui.UndoManager.prototype.hasRedoStates=function(){};
++gui.UndoManager.prototype.moveForward=function(g){};gui.UndoManager.prototype.moveBackward=function(g){};gui.UndoManager.prototype.onOperationExecuted=function(g){};gui.UndoManager.signalUndoStackChanged="undoStackChanged";gui.UndoManager.signalUndoStateCreated="undoStateCreated";gui.UndoManager.signalUndoStateModified="undoStateModified";(function(){return gui.UndoManager})();
++// Input 59
+/*
+
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.OdfUtils");runtime.loadClass("core.DomUtils");
- ops.OpRemoveText=function(){function g(c){function d(a){return p.hasOwnProperty(a.namespaceURI)||"br"===a.localName&&n.isLineBreak(a.parentNode)||a.nodeType===Node.TEXT_NODE&&p.hasOwnProperty(a.parentNode.namespaceURI)}function f(a){if(n.isCharacterElement(a))return!1;if(a.nodeType===Node.TEXT_NODE)return 0===a.textContent.length;for(a=a.firstChild;a;){if(p.hasOwnProperty(a.namespaceURI)||!f(a))return!1;a=a.nextSibling}return!0}function a(e){var h;e.nodeType===Node.TEXT_NODE?(h=e.parent [...]
- h=b.removeUnwantedNodes(e,d);return!n.isParagraph(h)&&h!==c&&f(h)?a(h):h}this.isEmpty=f;this.mergeChildrenIntoParent=a}var l,c,m,f,n,b,p={};this.init=function(g){runtime.assert(0<=g.length,"OpRemoveText only supports positive lengths");l=g.memberid;c=g.timestamp;m=parseInt(g.position,10);f=parseInt(g.length,10);n=new odf.OdfUtils;b=new core.DomUtils;p[odf.Namespaces.dbns]=!0;p[odf.Namespaces.dcns]=!0;p[odf.Namespaces.dr3dns]=!0;p[odf.Namespaces.drawns]=!0;p[odf.Namespaces.chartns]=!0;p[ [...]
- !0;p[odf.Namespaces.numberns]=!0;p[odf.Namespaces.officens]=!0;p[odf.Namespaces.presentationns]=!0;p[odf.Namespaces.stylens]=!0;p[odf.Namespaces.svgns]=!0;p[odf.Namespaces.tablens]=!0;p[odf.Namespaces.textns]=!0};this.isEdit=!0;this.execute=function(p){var d,k,a,e,h=p.getCursor(l),q=new g(p.getRootNode());p.upgradeWhitespacesAtPosition(m);p.upgradeWhitespacesAtPosition(m+f);k=p.convertCursorToDomRange(m,f);b.splitBoundaries(k);d=p.getParagraphElement(k.startContainer);a=n.getTextElement [...]
- e=n.getParagraphElements(k);k.detach();a.forEach(function(a){q.mergeChildrenIntoParent(a)});k=e.reduce(function(a,b){var c,e=!1,d=a,h=b,f,k=null;q.isEmpty(a)&&(e=!0,b.parentNode!==a.parentNode&&(f=b.parentNode,a.parentNode.insertBefore(b,a.nextSibling)),h=a,d=b,k=d.getElementsByTagNameNS("urn:webodf:names:editinfo","editinfo")[0]||d.firstChild);for(;h.hasChildNodes();)c=e?h.lastChild:h.firstChild,h.removeChild(c),"editinfo"!==c.localName&&d.insertBefore(c,k);f&&q.isEmpty(f)&&q.mergeChil [...]
- q.mergeChildrenIntoParent(h);return d});p.emit(ops.OdtDocument.signalStepsRemoved,{position:m,length:f});p.downgradeWhitespacesAtPosition(m);p.fixCursorPositions();p.getOdfCanvas().refreshSize();p.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:k||d,memberId:l,timeStamp:c});h&&(h.resetSelectionType(),p.emit(ops.OdtDocument.signalCursorMoved,h));p.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"RemoveText",memberid:l,timestamp:c,position:m [...]
- // Input 55
++gui.UndoStateRules=function(){function g(e){return e.spec().optype}function k(e){return e.isEdit}this.getOpType=g;this.isEditOperation=k;this.isPartOfOperationSet=function(e,n){if(e.isEdit){if(0===n.length)return!0;var m;if(m=n[n.length-1].isEdit)a:{m=n.filter(k);var q=g(e),b;b:switch(q){case "RemoveText":case "InsertText":b=!0;break b;default:b=!1}if(b&&q===g(m[0])){if(1===m.length){m=!0;break a}q=m[m.length-2].spec().position;m=m[m.length-1].spec().position;b=e.spec().position;if(m=== [...]
++!0;break a}}m=!1}return m}return!0}};
++// Input 60
+/*
+
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2012 KO GmbH <aditya.bhatt at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.OpSplitParagraph=function(){var g,l,c,m;this.init=function(f){g=f.memberid;l=f.timestamp;c=f.position;m=new odf.OdfUtils};this.isEdit=!0;this.execute=function(f){var n,b,p,r,d,k,a;f.upgradeWhitespacesAtPosition(c);n=f.getTextNodeAtStep(c,g);if(!n)return!1;b=f.getParagraphElement(n.textNode);if(!b)return!1;p=m.isListItem(b.parentNode)?b.parentNode:b;0===n.offset?(a=n.textNode.previousSibling,k=null):(a=n.textNode,k=n.offset>=n.textNode.length?null:n.textNode.splitText(n.offset));for( [...]
- p;){r=r.parentNode;d=r.cloneNode(!1);k&&d.appendChild(k);if(a)for(;a&&a.nextSibling;)d.appendChild(a.nextSibling);else for(;r.firstChild;)d.appendChild(r.firstChild);r.parentNode.insertBefore(d,r.nextSibling);a=r;k=d}m.isListItem(k)&&(k=k.childNodes[0]);0===n.textNode.length&&n.textNode.parentNode.removeChild(n.textNode);f.emit(ops.OdtDocument.signalStepsInserted,{position:c,length:1});f.fixCursorPositions();f.getOdfCanvas().refreshSize();f.emit(ops.OdtDocument.signalParagraphChanged,{p [...]
- memberId:g,timeStamp:l});f.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:k,memberId:g,timeStamp:l});f.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"SplitParagraph",memberid:g,timestamp:l,position:c}}};
- // Input 56
++ops.EditInfo=function(g,k){function e(){var e=[],b;for(b in m)m.hasOwnProperty(b)&&e.push({memberid:b,time:m[b].time});e.sort(function(b,e){return b.time-e.time});return e}var n,m={};this.getNode=function(){return n};this.getOdtDocument=function(){return k};this.getEdits=function(){return m};this.getSortedEdits=function(){return e()};this.addEdit=function(e,b){m[e]={time:b}};this.clearEdits=function(){m={}};this.destroy=function(e){g.parentNode&&g.removeChild(n);e()};n=k.getDOM().create [...]
++"editinfo");g.insertBefore(n,g.firstChild)};
++// Input 61
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.OpSetParagraphStyle=function(){var g,l,c,m;this.init=function(f){g=f.memberid;l=f.timestamp;c=f.position;m=f.styleName};this.isEdit=!0;this.execute=function(f){var n;n=f.getIteratorAtPosition(c);return(n=f.getParagraphElement(n.container()))?(""!==m?n.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0","text:style-name",m):n.removeAttributeNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0","style-name"),f.getOdfCanvas().refreshSize(),f.emit(ops.OdtDocument.signalParagra [...]
- {paragraphElement:n,timeStamp:l,memberId:g}),f.getOdfCanvas().rerenderAnnotations(),!0):!1};this.spec=function(){return{optype:"SetParagraphStyle",memberid:g,timestamp:l,position:c,styleName:m}}};
- // Input 57
++runtime.loadClass("core.DomUtils");
++ops.OpAddAnnotation=function(){function g(b,e,d){var f=b.getTextNodeAtStep(d,k);f&&(b=f.textNode,d=b.parentNode,f.offset!==b.length&&b.splitText(f.offset),d.insertBefore(e,b.nextSibling),0===b.length&&d.removeChild(b))}var k,e,n,m,q,b;this.init=function(b){k=b.memberid;e=parseInt(b.timestamp,10);n=parseInt(b.position,10);m=parseInt(b.length,10)||0;q=b.name};this.isEdit=!0;this.execute=function(h){var r={},d=h.getCursor(k),f,a;a=new core.DomUtils;b=h.getDOM();var c=new Date(e),p,l,u,B;f= [...]
++"office:annotation");f.setAttributeNS(odf.Namespaces.officens,"office:name",q);p=b.createElementNS(odf.Namespaces.dcns,"dc:creator");p.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",k);p.textContent=h.getMember(k).getProperties().fullName;l=b.createElementNS(odf.Namespaces.dcns,"dc:date");l.appendChild(b.createTextNode(c.toISOString()));c=b.createElementNS(odf.Namespaces.textns,"text:list");u=b.createElementNS(odf.Namespaces.textns,"text:list-item");B=b.createElementNS(o [...]
++"text:p");u.appendChild(B);c.appendChild(u);f.appendChild(p);f.appendChild(l);f.appendChild(c);r.node=f;if(!r.node)return!1;if(m){f=b.createElementNS(odf.Namespaces.officens,"office:annotation-end");f.setAttributeNS(odf.Namespaces.officens,"office:name",q);r.end=f;if(!r.end)return!1;g(h,r.end,n+m)}g(h,r.node,n);h.emit(ops.OdtDocument.signalStepsInserted,{position:n,length:m});d&&(f=b.createRange(),a=a.getElementsByTagNameNS(r.node,odf.Namespaces.textns,"p")[0],f.selectNodeContents(a),d. [...]
++h.emit(ops.OdtDocument.signalCursorMoved,d));h.getOdfCanvas().addAnnotation(r);h.fixCursorPositions();return!0};this.spec=function(){return{optype:"AddAnnotation",memberid:k,timestamp:e,position:n,length:m,name:q}}};
++// Input 62
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("odf.Namespaces");
- ops.OpUpdateParagraphStyle=function(){function g(b,c){var d,f,a=c?c.split(","):[];for(d=0;d<a.length;d+=1)f=a[d].split(":"),b.removeAttributeNS(odf.Namespaces.resolvePrefix(f[0]),f[1])}var l,c,m,f,n,b=odf.Namespaces.stylens;this.init=function(b){l=b.memberid;c=b.timestamp;m=b.styleName;f=b.setProperties;n=b.removedProperties};this.isEdit=!0;this.execute=function(c){var l=c.getFormatting(),d,k,a;return(d=""!==m?c.getParagraphStyleElement(m):l.getDefaultStyleElement("paragraph"))?(k=d.get [...]
- "paragraph-properties")[0],a=d.getElementsByTagNameNS(b,"text-properties")[0],f&&l.updateStyle(d,f),n&&(n["style:paragraph-properties"]&&(g(k,n["style:paragraph-properties"].attributes),0===k.attributes.length&&d.removeChild(k)),n["style:text-properties"]&&(g(a,n["style:text-properties"].attributes),0===a.attributes.length&&d.removeChild(a)),g(d,n.attributes)),c.getOdfCanvas().refreshCSS(),c.emit(ops.OdtDocument.signalParagraphStyleModified,m),c.getOdfCanvas().rerenderAnnotations(),!0): [...]
- function(){return{optype:"UpdateParagraphStyle",memberid:l,timestamp:c,styleName:m,setProperties:f,removedProperties:n}}};
- // Input 58
++ops.OpAddCursor=function(){var g,k;this.init=function(e){g=e.memberid;k=e.timestamp};this.isEdit=!1;this.execute=function(e){var k=e.getCursor(g);if(k)return!1;k=new ops.OdtCursor(g,e);e.addCursor(k);e.emit(ops.OdtDocument.signalCursorAdded,k);return!0};this.spec=function(){return{optype:"AddCursor",memberid:g,timestamp:k}}};
++// Input 63
++/*
++
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ This file is part of WebODF.
++
++ WebODF is free software: you can redistribute it and/or modify it
++ under the terms of the GNU Affero General Public License (GNU AGPL)
++ as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version.
++
++ WebODF is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU Affero General Public License for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
++ @licend
++
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++runtime.loadClass("ops.Member");ops.OpAddMember=function(){var g,k,e;this.init=function(n){g=n.memberid;k=parseInt(n.timestamp,10);e=n.setProperties};this.isEdit=!1;this.execute=function(k){if(k.getMember(g))return!1;var m=new ops.Member(g,e);k.addMember(m);k.emit(ops.OdtDocument.signalMemberAdded,m);return!0};this.spec=function(){return{optype:"AddMember",memberid:g,timestamp:k,setProperties:e}}};
++// Input 64
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+runtime.loadClass("odf.Namespaces");
- ops.OpAddStyle=function(){var g,l,c,m,f,n,b=odf.Namespaces.stylens;this.init=function(b){g=b.memberid;l=b.timestamp;c=b.styleName;m=b.styleFamily;f="true"===b.isAutomaticStyle||!0===b.isAutomaticStyle;n=b.setProperties};this.isEdit=!0;this.execute=function(g){var l=g.getOdfCanvas().odfContainer(),d=g.getFormatting(),k=g.getDOM().createElementNS(b,"style:style");if(!k)return!1;n&&d.updateStyle(k,n);k.setAttributeNS(b,"style:family",m);k.setAttributeNS(b,"style:name",c);f?l.rootElement.au [...]
- l.rootElement.styles.appendChild(k);g.getOdfCanvas().refreshCSS();f||g.emit(ops.OdtDocument.signalCommonStyleCreated,{name:c,family:m});return!0};this.spec=function(){return{optype:"AddStyle",memberid:g,timestamp:l,styleName:c,styleFamily:m,isAutomaticStyle:f,setProperties:n}}};
- // Input 59
++ops.OpAddStyle=function(){var g,k,e,n,m,q,b=odf.Namespaces.stylens;this.init=function(b){g=b.memberid;k=b.timestamp;e=b.styleName;n=b.styleFamily;m="true"===b.isAutomaticStyle||!0===b.isAutomaticStyle;q=b.setProperties};this.isEdit=!0;this.execute=function(g){var k=g.getOdfCanvas().odfContainer(),d=g.getFormatting(),f=g.getDOM().createElementNS(b,"style:style");if(!f)return!1;q&&d.updateStyle(f,q);f.setAttributeNS(b,"style:family",n);f.setAttributeNS(b,"style:name",e);m?k.rootElement.au [...]
++k.rootElement.styles.appendChild(f);g.getOdfCanvas().refreshCSS();m||g.emit(ops.OdtDocument.signalCommonStyleCreated,{name:e,family:n});return!0};this.spec=function(){return{optype:"AddStyle",memberid:g,timestamp:k,styleName:e,styleFamily:n,isAutomaticStyle:m,setProperties:q}}};
++// Input 65
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.OpRemoveStyle=function(){var g,l,c,m;this.init=function(f){g=f.memberid;l=f.timestamp;c=f.styleName;m=f.styleFamily};this.isEdit=!0;this.execute=function(f){var g=f.getStyleElement(c,m);if(!g)return!1;g.parentNode.removeChild(g);f.getOdfCanvas().refreshCSS();f.emit(ops.OdtDocument.signalCommonStyleDeleted,{name:c,family:m});return!0};this.spec=function(){return{optype:"RemoveStyle",memberid:g,timestamp:l,styleName:c,styleFamily:m}}};
- // Input 60
++runtime.loadClass("gui.StyleHelper");runtime.loadClass("odf.OdfUtils");
++ops.OpApplyDirectStyling=function(){function g(b){var e=0<=m?n+m:n,d=b.getIteratorAtPosition(0<=m?n:n+m),e=m?b.getIteratorAtPosition(e):d;b=b.getDOM().createRange();b.setStart(d.container(),d.unfilteredDomOffset());b.setEnd(e.container(),e.unfilteredDomOffset());return b}var k,e,n,m,q,b=new odf.OdfUtils;this.init=function(b){k=b.memberid;e=b.timestamp;n=parseInt(b.position,10);m=parseInt(b.length,10);q=b.setProperties};this.isEdit=!0;this.execute=function(h){var m=g(h),d=b.getImpactedPa [...]
++(new gui.StyleHelper(h.getFormatting())).applyStyle(k,m,q);m.detach();h.getOdfCanvas().refreshCSS();h.fixCursorPositions();d.forEach(function(b){h.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:b,memberId:k,timeStamp:e})});h.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"ApplyDirectStyling",memberid:k,timestamp:e,position:n,length:m,setProperties:q}}};
++// Input 66
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.OpAddAnnotation=function(){function g(b,c,f){var d=b.getTextNodeAtStep(f,l);d&&(b=d.textNode,f=b.parentNode,d.offset!==b.length&&b.splitText(d.offset),f.insertBefore(c,b.nextSibling),0===b.length&&f.removeChild(b))}var l,c,m,f,n;this.init=function(b){l=b.memberid;c=parseInt(b.timestamp,10);m=parseInt(b.position,10);f=parseInt(b.length,10)||0;n=b.name};this.isEdit=!0;this.execute=function(b){var p={},r=b.getPositionFilter(),d=b.getCursor(l),k=b.getCursorPosition(l),k=m-k-1,a=new Date [...]
- u,x;x=b.getDOM();e=x.createElementNS(odf.Namespaces.officens,"office:annotation");e.setAttributeNS(odf.Namespaces.officens,"office:name",n);h=x.createElementNS(odf.Namespaces.dcns,"dc:creator");h.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",l);h.textContent=b.getMember(l).getProperties().fullName;q=x.createElementNS(odf.Namespaces.dcns,"dc:date");q.appendChild(x.createTextNode(a.toISOString()));a=x.createElementNS(odf.Namespaces.textns,"text:list");u=x.createElementNS( [...]
- "text:list-item");x=x.createElementNS(odf.Namespaces.textns,"text:p");u.appendChild(x);a.appendChild(u);e.appendChild(h);e.appendChild(q);e.appendChild(a);p.node=e;if(!p.node)return!1;if(f){e=b.getDOM().createElementNS(odf.Namespaces.officens,"office:annotation-end");e.setAttributeNS(odf.Namespaces.officens,"office:name",n);p.end=e;if(!p.end)return!1;g(b,p.end,m+f)}g(b,p.node,m);b.emit(ops.OdtDocument.signalStepsInserted,{position:m,length:f});d&&(r=d.getStepCounter().countSteps(k,r),d. [...]
- b.emit(ops.OdtDocument.signalCursorMoved,d));b.getOdfCanvas().addAnnotation(p);b.fixCursorPositions();return!0};this.spec=function(){return{optype:"AddAnnotation",memberid:l,timestamp:c,position:m,length:f,name:n}}};
- // Input 61
++ops.OpInsertImage=function(){var g,k,e,n,m,q,b,h,r=odf.Namespaces.drawns,d=odf.Namespaces.svgns,f=odf.Namespaces.textns,a=odf.Namespaces.xlinkns;this.init=function(a){g=a.memberid;k=a.timestamp;e=a.position;n=a.filename;m=a.frameWidth;q=a.frameHeight;b=a.frameStyleName;h=a.frameName};this.isEdit=!0;this.execute=function(c){var p=c.getOdfCanvas(),l=c.getTextNodeAtStep(e,g),u,B;if(!l)return!1;u=l.textNode;B=c.getParagraphElement(u);var l=l.offset!==u.length?u.splitText(l.offset):u.nextSib [...]
++y=w.createElementNS(r,"draw:image"),w=w.createElementNS(r,"draw:frame");y.setAttributeNS(a,"xlink:href",n);y.setAttributeNS(a,"xlink:type","simple");y.setAttributeNS(a,"xlink:show","embed");y.setAttributeNS(a,"xlink:actuate","onLoad");w.setAttributeNS(r,"draw:style-name",b);w.setAttributeNS(r,"draw:name",h);w.setAttributeNS(f,"text:anchor-type","as-char");w.setAttributeNS(d,"svg:width",m);w.setAttributeNS(d,"svg:height",q);w.appendChild(y);u.parentNode.insertBefore(w,l);c.emit(ops.OdtDo [...]
++{position:e,length:1});0===u.length&&u.parentNode.removeChild(u);p.addCssForFrameWithImage(w);p.refreshCSS();c.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:B,memberId:g,timeStamp:k});p.rerenderAnnotations();return!0};this.spec=function(){return{optype:"InsertImage",memberid:g,timestamp:k,filename:n,position:e,frameWidth:m,frameHeight:q,frameStyleName:b,frameName:h}}};
++// Input 67
+/*
+
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("odf.Namespaces");runtime.loadClass("core.DomUtils");
- ops.OpRemoveAnnotation=function(){var g,l,c,m,f;this.init=function(n){g=n.memberid;l=n.timestamp;c=parseInt(n.position,10);m=parseInt(n.length,10);f=new core.DomUtils};this.isEdit=!0;this.execute=function(g){for(var b=g.getIteratorAtPosition(c).container(),l,r,d;b.namespaceURI!==odf.Namespaces.officens||"annotation"!==b.localName;)b=b.parentNode;if(null===b)return!1;(l=b.getAttributeNS(odf.Namespaces.officens,"name"))&&(r=f.getElementsByTagNameNS(g.getRootNode(),odf.Namespaces.officens, [...]
- b.getAttributeNS(odf.Namespaces.officens,"name")})[0]||null);g.getOdfCanvas().forgetAnnotations();for(d=f.getElementsByTagNameNS(b,"urn:webodf:names:cursor","cursor");d.length;)b.parentNode.insertBefore(d.pop(),b);b.parentNode.removeChild(b);r&&r.parentNode.removeChild(r);g.emit(ops.OdtDocument.signalStepsRemoved,{position:0<c?c-1:c,length:m});g.fixCursorPositions();g.getOdfCanvas().refreshAnnotations();return!0};this.spec=function(){return{optype:"RemoveAnnotation",memberid:g,timestamp [...]
- length:m}}};
- // Input 62
- /*
-
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- This file is part of WebODF.
-
- WebODF is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License (GNU AGPL)
- as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version.
-
- WebODF is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with WebODF. If not, see <http://www.gnu.org/licenses/>.
- @licend
-
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- runtime.loadClass("ops.Member");ops.OpAddMember=function(){var g,l,c;this.init=function(m){g=m.memberid;l=parseInt(m.timestamp,10);c=m.setProperties};this.isEdit=!1;this.execute=function(l){if(l.getMember(g))return!1;var f=new ops.Member(g,c);l.addMember(f);l.emit(ops.OdtDocument.signalMemberAdded,f);return!0};this.spec=function(){return{optype:"AddMember",memberid:g,timestamp:l,setProperties:c}}};
- // Input 63
- /*
-
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- This file is part of WebODF.
-
- WebODF is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License (GNU AGPL)
- as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version.
-
- WebODF is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with WebODF. If not, see <http://www.gnu.org/licenses/>.
- @licend
-
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- runtime.loadClass("ops.Member");runtime.loadClass("xmldom.XPath");
- ops.OpUpdateMember=function(){function g(){for(var b=new xmldom.XPath,c="//dc:creator[@editinfo:memberid='"+l+"']",b=b.getODFElementsWithXPath(n.getRootNode(),c,function(b){return"editinfo"===b?"urn:webodf:names:editinfo":odf.Namespaces.resolvePrefix(b)}),c=0;c<b.length;c+=1)b[c].textContent=m.fullName}var l,c,m,f,n;this.init=function(b){l=b.memberid;c=parseInt(b.timestamp,10);m=b.setProperties;f=b.removedProperties};this.isEdit=!1;this.execute=function(b){n=b;var c=b.getMember(l);if(!c [...]
- f&&c.removeProperties(f);m&&(c.setProperties(m),m.fullName&&g());b.emit(ops.OdtDocument.signalMemberUpdated,c);return!0};this.spec=function(){return{optype:"UpdateMember",memberid:l,timestamp:c,setProperties:m,removedProperties:f}}};
- // Input 64
++ops.OpInsertTable=function(){function g(b,a){var c;if(1===d.length)c=d[0];else if(3===d.length)switch(b){case 0:c=d[0];break;case n-1:c=d[2];break;default:c=d[1]}else c=d[b];if(1===c.length)return c[0];if(3===c.length)switch(a){case 0:return c[0];case m-1:return c[2];default:return c[1]}return c[a]}var k,e,n,m,q,b,h,r,d;this.init=function(f){k=f.memberid;e=f.timestamp;q=f.position;n=f.initialRows;m=f.initialColumns;b=f.tableName;h=f.tableStyleName;r=f.tableColumnStyleName;d=f.tableCellS [...]
++this.isEdit=!0;this.execute=function(d){var a=d.getTextNodeAtStep(q),c=d.getRootNode();if(a){var p=d.getDOM(),l=p.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table"),u=p.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table-column"),B,w,y,v;h&&l.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:style-name",h);b&&l.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:name",b);u.setAttributeNS(" [...]
++"table:number-columns-repeated",m);r&&u.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:style-name",r);l.appendChild(u);for(y=0;y<n;y+=1){u=p.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table-row");for(v=0;v<m;v+=1)B=p.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table-cell"),(w=g(y,v))&&B.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:style-name",w),w=p.createElementNS("urn:oasis:n [...]
++"text:p"),B.appendChild(w),u.appendChild(B);l.appendChild(u)}a=d.getParagraphElement(a.textNode);c.insertBefore(l,a.nextSibling);d.emit(ops.OdtDocument.signalStepsInserted,{position:q,length:m*n+1});d.getOdfCanvas().refreshSize();d.emit(ops.OdtDocument.signalTableAdded,{tableElement:l,memberId:k,timeStamp:e});d.getOdfCanvas().rerenderAnnotations();return!0}return!1};this.spec=function(){return{optype:"InsertTable",memberid:k,timestamp:e,position:q,initialRows:n,initialColumns:m,tableNam [...]
++tableColumnStyleName:r,tableCellStyleMatrix:d}}};
++// Input 68
+/*
+
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
- This file is part of WebODF.
-
- WebODF is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License (GNU AGPL)
- as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version.
-
- WebODF is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
- along with WebODF. If not, see <http://www.gnu.org/licenses/>.
- @licend
-
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
- */
- runtime.loadClass("ops.Member");ops.OpRemoveMember=function(){var g,l;this.init=function(c){g=c.memberid;l=parseInt(c.timestamp,10)};this.isEdit=!1;this.execute=function(c){if(!c.getMember(g))return!1;c.removeMember(g);c.emit(ops.OdtDocument.signalMemberRemoved,g);return!0};this.spec=function(){return{optype:"RemoveMember",memberid:g,timestamp:l}}};
- // Input 65
- /*
-
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
-
- @licstart
- This file is part of WebODF.
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
- WebODF is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License (GNU AGPL)
- as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version.
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
+
- WebODF is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
+
- You should have received a copy of the GNU Affero General Public License
- along with WebODF. If not, see <http://www.gnu.org/licenses/>.
++ This license applies to this entire compilation.
+ @licend
-
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.OpUpdateMetadata=function(){var g,l,c,m;this.init=function(f){g=f.memberid;l=parseInt(f.timestamp,10);c=f.setProperties;m=f.removedProperties};this.isEdit=!0;this.execute=function(f){f=f.getOdfCanvas().odfContainer().getMetadataManager();var g=[],b=["dc:date","dc:creator","meta:editing-cycles"];c&&b.forEach(function(b){if(c[b])return!1});m&&(b.forEach(function(b){if(-1!==g.indexOf(b))return!1}),g=m.attributes.split(","));f.setMetadata(c,g);return!0};this.spec=function(){return{optyp [...]
- memberid:g,timestamp:l,setProperties:c,removedProperties:m}}};
- // Input 66
++ops.OpInsertText=function(){var g,k,e,n;this.init=function(m){g=m.memberid;k=m.timestamp;e=m.position;n=m.text};this.isEdit=!0;this.execute=function(m){var q,b,h,r=null,d=m.getDOM(),f,a=0,c,p;m.upgradeWhitespacesAtPosition(e);if(q=m.getTextNodeAtStep(e,g)){b=q.textNode;r=b.nextSibling;h=b.parentNode;f=m.getParagraphElement(b);for(p=0;p<n.length;p+=1)if(" "===n[p]&&(0===p||p===n.length-1||" "===n[p-1])||"\t"===n[p])0===a?(q.offset!==b.length&&(r=b.splitText(q.offset)),0<p&&b.appendData(n [...]
++p))):a<p&&(a=n.substring(a,p),h.insertBefore(d.createTextNode(a),r)),a=p+1,c=" "===n[p]?"text:s":"text:tab",c=d.createElementNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0",c),c.appendChild(d.createTextNode(n[p])),h.insertBefore(c,r);0===a?b.insertData(q.offset,n):a<n.length&&(q=n.substring(a),h.insertBefore(d.createTextNode(q),r));h=b.parentNode;r=b.nextSibling;h.removeChild(b);h.insertBefore(b,r);0===b.length&&b.parentNode.removeChild(b);m.emit(ops.OdtDocument.signalStepsInserted, [...]
++length:n.length});0<e&&(1<e&&m.downgradeWhitespacesAtPosition(e-2),m.downgradeWhitespacesAtPosition(e-1));m.downgradeWhitespacesAtPosition(e);m.downgradeWhitespacesAtPosition(e+n.length-1);m.downgradeWhitespacesAtPosition(e+n.length);m.getOdfCanvas().refreshSize();m.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:f,memberId:g,timeStamp:k});m.getOdfCanvas().rerenderAnnotations();return!0}return!1};this.spec=function(){return{optype:"InsertText",memberid:g,timestamp:k,positi [...]
++// Input 69
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("ops.OpAddMember");runtime.loadClass("ops.OpUpdateMember");runtime.loadClass("ops.OpRemoveMember");runtime.loadClass("ops.OpAddCursor");runtime.loadClass("ops.OpApplyDirectStyling");runtime.loadClass("ops.OpRemoveCursor");runtime.loadClass("ops.OpMoveCursor");runtime.loadClass("ops.OpSetBlob");runtime.loadClass("ops.OpRemoveBlob");runtime.loadClass("ops.OpInsertImage");runtime.loadClass("ops.OpInsertTable");runtime.loadClass("ops.OpInsertText");runtime.loadClass("ops.O [...]
- runtime.loadClass("ops.OpSplitParagraph");runtime.loadClass("ops.OpSetParagraphStyle");runtime.loadClass("ops.OpUpdateParagraphStyle");runtime.loadClass("ops.OpAddStyle");runtime.loadClass("ops.OpRemoveStyle");runtime.loadClass("ops.OpAddAnnotation");runtime.loadClass("ops.OpRemoveAnnotation");runtime.loadClass("ops.OpUpdateMetadata");
- ops.OperationFactory=function(){function g(c){return function(){return new c}}var l;this.register=function(c,g){l[c]=g};this.create=function(c){var g=null,f=l[c.optype];f&&(g=f(c),g.init(c));return g};l={AddMember:g(ops.OpAddMember),UpdateMember:g(ops.OpUpdateMember),RemoveMember:g(ops.OpRemoveMember),AddCursor:g(ops.OpAddCursor),ApplyDirectStyling:g(ops.OpApplyDirectStyling),SetBlob:g(ops.OpSetBlob),RemoveBlob:g(ops.OpRemoveBlob),InsertImage:g(ops.OpInsertImage),InsertTable:g(ops.OpIns [...]
- InsertText:g(ops.OpInsertText),RemoveText:g(ops.OpRemoveText),SplitParagraph:g(ops.OpSplitParagraph),SetParagraphStyle:g(ops.OpSetParagraphStyle),UpdateParagraphStyle:g(ops.OpUpdateParagraphStyle),AddStyle:g(ops.OpAddStyle),RemoveStyle:g(ops.OpRemoveStyle),MoveCursor:g(ops.OpMoveCursor),RemoveCursor:g(ops.OpRemoveCursor),AddAnnotation:g(ops.OpAddAnnotation),RemoveAnnotation:g(ops.OpRemoveAnnotation),UpdateMetadata:g(ops.OpUpdateMetadata)}};
- // Input 67
++ops.OpMoveCursor=function(){var g,k,e,n,m;this.init=function(q){g=q.memberid;k=q.timestamp;e=q.position;n=q.length||0;m=q.selectionType||ops.OdtCursor.RangeSelection};this.isEdit=!1;this.execute=function(k){var b=k.getCursor(g),h;if(!b)return!1;h=k.convertCursorToDomRange(e,n);b.setSelectedRange(h,0<=n);b.setSelectionType(m);k.emit(ops.OdtDocument.signalCursorMoved,b);return!0};this.spec=function(){return{optype:"MoveCursor",memberid:g,timestamp:k,position:e,length:n,selectionType:m}}};
++// Input 70
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.Cursor");runtime.loadClass("core.DomUtils");runtime.loadClass("core.PositionIterator");runtime.loadClass("core.PositionFilter");runtime.loadClass("core.LoopWatchDog");runtime.loadClass("odf.OdfUtils");
- gui.SelectionMover=function(g,l){function c(){v.setUnfilteredPosition(g.getNode(),0);return v}function m(a,b){var c,e=null;a&&(c=b?a[a.length-1]:a[0]);c&&(e={top:c.top,left:b?c.right:c.left,bottom:c.bottom});return e}function f(a,b,c,e){var d=a.nodeType;c.setStart(a,b);c.collapse(!e);e=m(c.getClientRects(),!0===e);!e&&0<b&&(c.setStart(a,b-1),c.setEnd(a,b),e=m(c.getClientRects(),!0));e||(d===Node.ELEMENT_NODE&&a.childNodes[b-1]?e=f(a,b-1,c,!0):a.nodeType===Node.TEXT_NODE&&0<b?e=f(a,b-1,c [...]
- e=f(a.previousSibling,a.previousSibling.nodeType===Node.TEXT_NODE?a.previousSibling.textContent.length:a.previousSibling.childNodes.length,c,!0):a.parentNode&&a.parentNode!==l?e=f(a.parentNode,0,c,!1):(c.selectNode(l),e=m(c.getClientRects(),!1)));runtime.assert(Boolean(e),"No visible rectangle found");return e}function n(a,b,e){var d=a,h=c(),k,m=l.ownerDocument.createRange(),q=g.getSelectedRange()?g.getSelectedRange().cloneRange():l.ownerDocument.createRange(),n;for(k=f(h.container(),h. [...]
- m);0<d&&e();)d-=1;b?(b=h.container(),h=h.unfilteredDomOffset(),-1===x.comparePoints(q.startContainer,q.startOffset,b,h)?(q.setStart(b,h),n=!1):q.setEnd(b,h)):(q.setStart(h.container(),h.unfilteredDomOffset()),q.collapse(!0));g.setSelectedRange(q,n);h=c();q=f(h.container(),h.unfilteredDomOffset(),m);if(q.top===k.top||void 0===y)y=q.left;runtime.clearTimeout(w);w=runtime.setTimeout(function(){y=void 0},2E3);m.detach();return a-d}function b(a){var b=c();return a.acceptPosition(b)===t&&(b.s [...]
- 0),a.acceptPosition(b)===t)?!0:!1}function p(a,b,c){for(var e=new core.LoopWatchDog(1E4),d=0,h=0,f=0<=b?1:-1,k=0<=b?a.nextPosition:a.previousPosition;0!==b&&k();)e.check(),h+=f,c.acceptPosition(a)===t&&(b-=f,d+=h,h=0);return d}function r(a,b,e){for(var d=c(),h=new core.LoopWatchDog(1E4),f=0,k=0;0<a&&d.nextPosition();)h.check(),e.acceptPosition(d)===t&&(f+=1,b.acceptPosition(d)===t&&(k+=f,f=0,a-=1));return k}function d(a,b,e){for(var d=c(),h=new core.LoopWatchDog(1E4),f=0,k=0;0<a&&d.prev [...]
- e.acceptPosition(d)===t&&(f+=1,b.acceptPosition(d)===t&&(k+=f,f=0,a-=1));return k}function k(a,b){var e=c();return p(e,a,b)}function a(a,b,e){var d=c(),h=u.getParagraphElement(d.getCurrentNode()),f=0;d.setUnfilteredPosition(a,b);e.acceptPosition(d)!==t&&(f=p(d,-1,e),0===f||h&&h!==u.getParagraphElement(d.getCurrentNode()))&&(d.setUnfilteredPosition(a,b),f=p(d,1,e));return f}function e(a,b){var e=c(),d=0,h=0,k=0>a?-1:1;for(a=Math.abs(a);0<a;){for(var g=b,m=k,q=e,n=q.container(),p=0,r=null [...]
- u=10,v=void 0,x=0,Y=void 0,V=void 0,G=void 0,v=void 0,I=l.ownerDocument.createRange(),ha=new core.LoopWatchDog(1E4),v=f(n,q.unfilteredDomOffset(),I),Y=v.top,V=void 0===y?v.left:y,G=Y;!0===(0>m?q.previousPosition():q.nextPosition());)if(ha.check(),g.acceptPosition(q)===t&&(p+=1,n=q.container(),v=f(n,q.unfilteredDomOffset(),I),v.top!==Y)){if(v.top!==G&&G!==Y)break;G=v.top;v=Math.abs(V-v.left);if(null===r||v<u)r=n,w=q.unfilteredDomOffset(),u=v,x=p}null!==r?(q.setUnfilteredPosition(r,w),p=x [...]
- d+=p;if(0===d)break;h+=d;a-=1}return h*k}function h(a,b){var e,d,h,k,g=c(),m=u.getParagraphElement(g.getCurrentNode()),q=0,n=l.ownerDocument.createRange();0>a?(e=g.previousPosition,d=-1):(e=g.nextPosition,d=1);for(h=f(g.container(),g.unfilteredDomOffset(),n);e.call(g);)if(b.acceptPosition(g)===t){if(u.getParagraphElement(g.getCurrentNode())!==m)break;k=f(g.container(),g.unfilteredDomOffset(),n);if(k.bottom!==h.bottom&&(h=k.top>=h.top&&k.bottom<h.bottom||k.top<=h.top&&k.bottom>h.bottom,! [...]
- d;h=k}n.detach();return q}function q(a,b,e){runtime.assert(null!==a,"SelectionMover.countStepsToPosition called with element===null");var d=c(),h=d.container(),f=d.unfilteredDomOffset(),k=0,g=new core.LoopWatchDog(1E4);for(d.setUnfilteredPosition(a,b);e.acceptPosition(d)!==t&&d.previousPosition();)g.check();a=d.container();runtime.assert(Boolean(a),"SelectionMover.countStepsToPosition: positionIterator.container() returned null");b=d.unfilteredDomOffset();for(d.setUnfilteredPosition(h,f [...]
- t&&d.previousPosition();)g.check();h=x.comparePoints(a,b,d.container(),d.unfilteredDomOffset());if(0>h)for(;d.nextPosition()&&(g.check(),e.acceptPosition(d)===t&&(k+=1),d.container()!==a||d.unfilteredDomOffset()!==b););else if(0<h)for(;d.previousPosition()&&(g.check(),e.acceptPosition(d)!==t||(k-=1,d.container()!==a||d.unfilteredDomOffset()!==b)););return k}var u,x,v,y,w,t=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.movePointForward=function(a,b){return n(a,b||!1,v.nextPosition) [...]
- function(a,b){return n(a,b||!1,v.previousPosition)};this.getStepCounter=function(){return{countSteps:k,convertForwardStepsBetweenFilters:r,convertBackwardStepsBetweenFilters:d,countLinesSteps:e,countStepsToLineBoundary:h,countStepsToPosition:q,isPositionWalkable:b,countPositionsToNearestStep:a}};(function(){u=new odf.OdfUtils;x=new core.DomUtils;v=gui.SelectionMover.createPositionIterator(l);var a=l.ownerDocument.createRange();a.setStart(v.container(),v.unfilteredDomOffset());a.collapse [...]
- gui.SelectionMover.createPositionIterator=function(g){var l=new function(){this.acceptNode=function(c){return c&&"urn:webodf:names:cursor"!==c.namespaceURI&&"urn:webodf:names:editinfo"!==c.namespaceURI?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT}};return new core.PositionIterator(g,5,l,!1)};(function(){return gui.SelectionMover})();
- // Input 68
++runtime.loadClass("odf.Namespaces");runtime.loadClass("core.DomUtils");
++ops.OpRemoveAnnotation=function(){var g,k,e,n,m;this.init=function(q){g=q.memberid;k=q.timestamp;e=parseInt(q.position,10);n=parseInt(q.length,10);m=new core.DomUtils};this.isEdit=!0;this.execute=function(g){for(var b=g.getIteratorAtPosition(e).container(),h,k,d;b.namespaceURI!==odf.Namespaces.officens||"annotation"!==b.localName;)b=b.parentNode;if(null===b)return!1;(h=b.getAttributeNS(odf.Namespaces.officens,"name"))&&(k=m.getElementsByTagNameNS(g.getRootNode(),odf.Namespaces.officens, [...]
++b.getAttributeNS(odf.Namespaces.officens,"name")})[0]||null);g.getOdfCanvas().forgetAnnotations();for(d=m.getElementsByTagNameNS(b,"urn:webodf:names:cursor","cursor");d.length;)b.parentNode.insertBefore(d.pop(),b);b.parentNode.removeChild(b);k&&k.parentNode.removeChild(k);g.emit(ops.OdtDocument.signalStepsRemoved,{position:0<e?e-1:e,length:n});g.fixCursorPositions();g.getOdfCanvas().refreshAnnotations();return!0};this.spec=function(){return{optype:"RemoveAnnotation",memberid:g,timestamp [...]
++length:n}}};
++// Input 71
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.DomUtils");runtime.loadClass("core.PositionFilter");runtime.loadClass("odf.OdfUtils");
- (function(){function g(c,g,f){function n(a,b){function c(a){for(var b=0;a&&a.previousSibling;)b+=1,a=a.previousSibling;return b}this.steps=a;this.node=b;this.setIteratorPosition=function(a){a.setUnfilteredPosition(b.parentNode,c(b));do if(g.acceptPosition(a)===u)break;while(a.nextPosition())}}function b(a){return a.nodeType===Node.ELEMENT_NODE&&a.getAttributeNS(d,"nodeId")}function p(a){var b=l;a.setAttributeNS(d,"nodeId",b.toString());l+=1;return b}function r(e,h){var f,k=null;for(e=e. [...]
- e;!k&&e&&e!==c;)(f=b(e))&&(k=a[f])&&k.node!==e&&(runtime.log("Cloned node detected. Creating new bookmark"),k=null,e.removeAttributeNS(d,"nodeId")),e=e.parentNode;return k}var d="urn:webodf:names:steps",k={},a={},e=new odf.OdfUtils,h=new core.DomUtils,q,u=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.updateCache=function(c,d,h,g){var l;0===h&&e.isParagraph(d)?(l=!0,g||(c+=1)):d.hasChildNodes()&&d.childNodes[h]&&(d=d.childNodes[h],(l=e.isParagraph(d))&&(c+=1));l&&(h=b(d)||p(d),(g=a [...]
- d?g.steps=c:(runtime.log("Cloned node detected. Creating new bookmark"),h=p(d),g=a[h]=new n(c,d)):g=a[h]=new n(c,d),h=g,c=Math.ceil(h.steps/f)*f,d=k[c],!d||h.steps>d.steps)&&(k[c]=h)};this.setToClosestStep=function(a,b){for(var c=Math.floor(a/f)*f,e;!e&&0!==c;)e=k[c],c-=f;e=e||q;e.setIteratorPosition(b);return e.steps};this.setToClosestDomPoint=function(a,b,e){var d;if(a===c&&0===b)d=q;else if(a===c&&b===c.childNodes.length)d=Object.keys(k).map(function(a){return k[a]}).reduce(function( [...]
- a.steps?b:a},q);else if(d=r(a,b),!d)for(e.setUnfilteredPosition(a,b);!d&&e.previousNode();)d=r(e.container(),e.unfilteredDomOffset());d=d||q;d.setIteratorPosition(e);return d.steps};this.updateCacheAtPoint=function(e,d){var g={};Object.keys(a).map(function(b){return a[b]}).filter(function(a){return a.steps>e}).forEach(function(e){var l=Math.ceil(e.steps/f)*f,m,q;if(h.containsNode(c,e.node)){if(d(e),m=Math.ceil(e.steps/f)*f,q=g[m],!q||e.steps>q.steps)g[m]=e}else delete a[b(e.node)];k[l]= [...]
- Object.keys(g).forEach(function(a){k[a]=g[a]})};q=new function(a,b){this.steps=a;this.node=b;this.setIteratorPosition=function(a){a.setUnfilteredPosition(b,0);do if(g.acceptPosition(a)===u)break;while(a.nextPosition())}}(0,c)}var l=0;ops.StepsTranslator=function(c,l,f,n){function b(){var a=c();a!==p&&(runtime.log("Undo detected. Resetting steps cache"),p=a,r=new g(p,f,n),k=l(p))}var p=c(),r=new g(p,f,n),d=new core.DomUtils,k=l(c()),a=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.c [...]
- function(c){var d,g;0>c&&(runtime.log("warn","Requested steps were negative ("+c+")"),c=0);b();for(d=r.setToClosestStep(c,k);d<c&&k.nextPosition();)(g=f.acceptPosition(k)===a)&&(d+=1),r.updateCache(d,k.container(),k.unfilteredDomOffset(),g);d!==c&&runtime.log("warn","Requested "+c+" steps but only "+d+" are available");return{node:k.container(),offset:k.unfilteredDomOffset()}};this.convertDomPointToSteps=function(c,h,g){var l,m,n=0;b();d.containsNode(p,c)||(l=0>d.comparePoints(p,0,c,h), [...]
- p.childNodes.length);k.setUnfilteredPosition(c,h);l=k.container();m=k.unfilteredDomOffset();g&&f.acceptPosition(k)!==a&&(n=1);c=r.setToClosestDomPoint(c,h,k);if(0>d.comparePoints(k.container(),k.unfilteredDomOffset(),l,m))return 0<c&&!g?c-1:c;for(;(k.container()!==l||k.unfilteredDomOffset()!==m)&&k.nextPosition();)(g=f.acceptPosition(k)===a)&&(c+=1),r.updateCache(c,k.container(),k.unfilteredDomOffset(),g);return c+n};this.prime=function(){var c,d;b();for(c=r.setToClosestStep(0,k);k.next [...]
- f.acceptPosition(k)===a)&&(c+=1),r.updateCache(c,k.container(),k.unfilteredDomOffset(),d)};this.handleStepsInserted=function(a){b();r.updateCacheAtPoint(a.position,function(b){b.steps+=a.length})};this.handleStepsRemoved=function(a){b();r.updateCacheAtPoint(a.position,function(b){b.steps-=a.length;0>b.steps&&(b.steps=0)})}};return ops.StepsTranslator})();
- // Input 69
++ops.OpRemoveBlob=function(){var g,k,e;this.init=function(n){g=n.memberid;k=n.timestamp;e=n.filename};this.isEdit=!0;this.execute=function(g){g.getOdfCanvas().odfContainer().removeBlob(e);return!0};this.spec=function(){return{optype:"RemoveBlob",memberid:g,timestamp:k,filename:e}}};
++// Input 72
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.PositionFilter");runtime.loadClass("odf.OdfUtils");
- ops.TextPositionFilter=function(g){function l(f,g,d){var k,a;if(g&&(k=c.lookLeftForCharacter(g),1===k||2===k&&(c.scanRightForAnyCharacter(d)||c.scanRightForAnyCharacter(c.nextNode(f)))))return n;k=null===g&&c.isParagraph(f);a=c.lookRightForCharacter(d);if(k)return a?n:c.scanRightForAnyCharacter(d)?b:n;if(!a)return b;g=g||c.previousNode(f);return c.scanLeftForAnyCharacter(g)?b:n}var c=new odf.OdfUtils,m=Node.ELEMENT_NODE,f=Node.TEXT_NODE,n=core.PositionFilter.FilterResult.FILTER_ACCEPT,b [...]
- this.acceptPosition=function(p){var r=p.container(),d=r.nodeType,k,a,e;if(d!==m&&d!==f)return b;if(d===f){if(!c.isGroupingElement(r.parentNode)||c.isWithinTrackedChanges(r.parentNode,g()))return b;d=p.unfilteredDomOffset();k=r.data;runtime.assert(d!==k.length,"Unexpected offset.");if(0<d){p=k[d-1];if(!c.isODFWhitespace(p))return n;if(1<d)if(p=k[d-2],!c.isODFWhitespace(p))a=n;else{if(!c.isODFWhitespace(k.substr(0,d)))return b}else e=c.previousNode(r),c.scanLeftForNonSpace(e)&&(a=n);if(a= [...]
- d)?b:n;a=k[d];return c.isODFWhitespace(a)?b:c.scanLeftForAnyCharacter(c.previousNode(r))?b:n}e=p.leftNode();a=r;r=r.parentNode;a=l(r,e,a)}else!c.isGroupingElement(r)||c.isWithinTrackedChanges(r,g())?a=b:(e=p.leftNode(),a=p.rightNode(),a=l(r,e,a));return a}};
- // Input 70
++ops.OpRemoveCursor=function(){var g,k;this.init=function(e){g=e.memberid;k=e.timestamp};this.isEdit=!1;this.execute=function(e){return e.removeCursor(g)?!0:!1};this.spec=function(){return{optype:"RemoveCursor",memberid:g,timestamp:k}}};
++// Input 73
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ This file is part of WebODF.
+
+ WebODF is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License (GNU AGPL)
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ WebODF is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ @licend
+
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.OperationTransformMatrix=function(){function g(a){a.position+=a.length;a.length*=-1}function l(a){var b=0>a.length;b&&g(a);return b}function c(a,b){var c=[];a&&["style:parent-style-name","style:next-style-name"].forEach(function(d){a[d]===b&&c.push(d)});return c}function m(a,b){a&&["style:parent-style-name","style:next-style-name"].forEach(function(c){a[c]===b&&delete a[c]})}function f(a){var b={};Object.keys(a).forEach(function(c){b[c]="object"===typeof a[c]?f(a[c]):a[c]});return b [...]
- b,c,d){var f,k,g=!1,l=!1,m,n,p=d&&d.attributes?d.attributes.split(","):[];a&&(c||0<p.length)&&Object.keys(a).forEach(function(b){f=a[b];"object"!==typeof f&&(m=c&&c[b],void 0!==m?(delete a[b],l=!0,m===f&&(delete c[b],g=!0)):p&&-1!==p.indexOf(b)&&(delete a[b],l=!0))});if(b&&b.attributes&&(c||0<p.length)){n=b.attributes.split(",");for(d=0;d<n.length;d+=1)if(k=n[d],c&&void 0!==c[k]||p&&-1!==p.indexOf(k))n.splice(d,1),d-=1,l=!0;0<n.length?b.attributes=n.join(","):delete b.attributes}return{ [...]
- minorChanged:l}}function b(a){for(var b in a)if(a.hasOwnProperty(b))return!0;return!1}function p(a){for(var b in a)if(a.hasOwnProperty(b)&&("attributes"!==b||0<a.attributes.length))return!0;return!1}function r(a,c,d){var f=a.setProperties?a.setProperties[d]:null,k=a.removedProperties?a.removedProperties[d]:null,g=c.setProperties?c.setProperties[d]:null,l=c.removedProperties?c.removedProperties[d]:null,m;m=n(f,k,g,l);f&&!b(f)&&delete a.setProperties[d];k&&!p(k)&&delete a.removedPropertie [...]
- delete c.setProperties[d];l&&!p(l)&&delete c.removedProperties[d];return m}function d(a,b){return{opSpecsA:[a],opSpecsB:[b]}}var k={AddCursor:{AddCursor:d,AddMember:d,AddStyle:d,ApplyDirectStyling:d,InsertText:d,MoveCursor:d,RemoveCursor:d,RemoveMember:d,RemoveStyle:d,RemoveText:d,SetParagraphStyle:d,SplitParagraph:d,UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:d},AddMember:{AddStyle:d,InsertText:d,MoveCursor:d,RemoveCursor:d,RemoveStyle:d,RemoveText:d,SetParagraphStyle:d,SplitP [...]
- UpdateMetadata:d,UpdateParagraphStyle:d},AddStyle:{AddStyle:d,ApplyDirectStyling:d,InsertText:d,MoveCursor:d,RemoveCursor:d,RemoveMember:d,RemoveStyle:function(a,b){var d,f=[a],k=[b];a.styleFamily===b.styleFamily&&(d=c(a.setProperties,b.styleName),0<d.length&&(d={optype:"UpdateParagraphStyle",memberid:b.memberid,timestamp:b.timestamp,styleName:a.styleName,removedProperties:{attributes:d.join(",")}},k.unshift(d)),m(a.setProperties,b.styleName));return{opSpecsA:f,opSpecsB:k}},RemoveText:d [...]
- SplitParagraph:d,UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:d},ApplyDirectStyling:{ApplyDirectStyling:function(a,c,d){var k,g,l,m,n,p,t,s;m=[a];l=[c];if(!(a.position+a.length<=c.position||a.position>=c.position+c.length)){k=d?a:c;g=d?c:a;if(a.position!==c.position||a.length!==c.length)p=f(k),t=f(g);c=r(g,k,"style:text-properties");if(c.majorChanged||c.minorChanged)l=[],a=[],m=k.position+k.length,n=g.position+g.length,g.position<k.position?c.minorChanged&&(s=f(t),s.length=k.pos [...]
- a.push(s),g.position=k.position,g.length=n-g.position):k.position<g.position&&c.majorChanged&&(s=f(p),s.length=g.position-k.position,l.push(s),k.position=g.position,k.length=m-k.position),n>m?c.minorChanged&&(p=t,p.position=m,p.length=n-m,a.push(p),g.length=m-g.position):m>n&&c.majorChanged&&(p.position=n,p.length=m-n,l.push(p),k.length=n-k.position),k.setProperties&&b(k.setProperties)&&l.push(k),g.setProperties&&b(g.setProperties)&&a.push(g),d?(m=l,l=a):m=a}return{opSpecsA:m,opSpecsB:l [...]
- b){b.position<=a.position?a.position+=b.text.length:b.position<=a.position+a.length&&(a.length+=b.text.length);return{opSpecsA:[a],opSpecsB:[b]}},MoveCursor:d,RemoveCursor:d,RemoveStyle:d,RemoveText:function(a,b){var c=a.position+a.length,d=b.position+b.length,f=[a],k=[b];d<=a.position?a.position-=b.length:b.position<c&&(a.position<b.position?a.length=d<c?a.length-b.length:b.position-a.position:(a.position=b.position,d<c?a.length=c-d:f=[]));return{opSpecsA:f,opSpecsB:k}},SetParagraphSty [...]
- b){b.position<a.position?a.position+=1:b.position<a.position+a.length&&(a.length+=1);return{opSpecsA:[a],opSpecsB:[b]}},UpdateMetadata:d,UpdateParagraphStyle:d},InsertText:{InsertText:function(a,b,c){if(a.position<b.position)b.position+=a.text.length;else if(a.position>b.position)a.position+=b.text.length;else return c?b.position+=a.text.length:a.position+=b.text.length,null;return{opSpecsA:[a],opSpecsB:[b]}},MoveCursor:function(a,b){var c=l(b);a.position<b.position?b.position+=a.text.l [...]
- b.position+b.length&&(b.length+=a.text.length);c&&g(b);return{opSpecsA:[a],opSpecsB:[b]}},RemoveCursor:d,RemoveMember:d,RemoveStyle:d,RemoveText:function(a,b){var c;c=b.position+b.length;var d=[a],f=[b];c<=a.position?a.position-=b.length:a.position<=b.position?b.position+=a.text.length:(b.length=a.position-b.position,c={optype:"RemoveText",memberid:b.memberid,timestamp:b.timestamp,position:a.position+a.text.length,length:c-a.position},f.unshift(c),a.position=b.position);return{opSpecsA: [...]
- SplitParagraph:function(a,b,c){if(a.position<b.position)b.position+=a.text.length;else if(a.position>b.position)a.position+=1;else return c?b.position+=a.text.length:a.position+=1,null;return{opSpecsA:[a],opSpecsB:[b]}},UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:d},MoveCursor:{MoveCursor:d,RemoveCursor:function(a,b){return{opSpecsA:a.memberid===b.memberid?[]:[a],opSpecsB:[b]}},RemoveMember:d,RemoveStyle:d,RemoveText:function(a,b){var c=l(a),d=a.position+a.length,f=b.position+b [...]
- a.position?a.position-=b.length:b.position<d&&(a.position<b.position?a.length=f<d?a.length-b.length:b.position-a.position:(a.position=b.position,a.length=f<d?d-f:0));c&&g(a);return{opSpecsA:[a],opSpecsB:[b]}},SetParagraphStyle:d,SplitParagraph:function(a,b){var c=l(a);b.position<a.position?a.position+=1:b.position<a.position+a.length&&(a.length+=1);c&&g(a);return{opSpecsA:[a],opSpecsB:[b]}},UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:d},RemoveCursor:{RemoveCursor:function(a,b){ [...]
- b.memberid;return{opSpecsA:c?[]:[a],opSpecsB:c?[]:[b]}},RemoveMember:d,RemoveStyle:d,RemoveText:d,SetParagraphStyle:d,SplitParagraph:d,UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:d},RemoveMember:{RemoveStyle:d,RemoveText:d,SetParagraphStyle:d,SplitParagraph:d,UpdateMetadata:d,UpdateParagraphStyle:d},RemoveStyle:{RemoveStyle:function(a,b){var c=a.styleName===b.styleName&&a.styleFamily===b.styleFamily;return{opSpecsA:c?[]:[a],opSpecsB:c?[]:[b]}},RemoveText:d,SetParagraphStyle:fun [...]
- d=[a],f=[b];"paragraph"===a.styleFamily&&a.styleName===b.styleName&&(c={optype:"SetParagraphStyle",memberid:a.memberid,timestamp:a.timestamp,position:b.position,styleName:""},d.unshift(c),b.styleName="");return{opSpecsA:d,opSpecsB:f}},SplitParagraph:d,UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:function(a,b){var d,f=[a],k=[b];"paragraph"===a.styleFamily&&(d=c(b.setProperties,a.styleName),0<d.length&&(d={optype:"UpdateParagraphStyle",memberid:a.memberid,timestamp:a.timestamp,sty [...]
- removedProperties:{attributes:d.join(",")}},f.unshift(d)),a.styleName===b.styleName?k=[]:m(b.setProperties,a.styleName));return{opSpecsA:f,opSpecsB:k}}},RemoveText:{RemoveText:function(a,b){var c=a.position+a.length,d=b.position+b.length,f=[a],k=[b];d<=a.position?a.position-=b.length:c<=b.position?b.position-=a.length:b.position<c&&(a.position<b.position?(a.length=d<c?a.length-b.length:b.position-a.position,c<d?(b.position=a.position,b.length=d-c):k=[]):(c<d?b.length-=a.length:b.positio [...]
- b.length=a.position-b.position:k=[],d<c?(a.position=b.position,a.length=c-d):f=[]));return{opSpecsA:f,opSpecsB:k}},SplitParagraph:function(a,b){var c=a.position+a.length,d=[a],f=[b];b.position<=a.position?a.position+=1:b.position<c&&(a.length=b.position-a.position,c={optype:"RemoveText",memberid:a.memberid,timestamp:a.timestamp,position:b.position+1,length:c-b.position},d.unshift(c));a.position+a.length<=b.position?b.position-=a.length:a.position<b.position&&(b.position=a.position);retu [...]
- opSpecsB:f}},UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:d},SetParagraphStyle:{UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:d},SplitParagraph:{SplitParagraph:function(a,b,c){if(a.position<b.position)b.position+=1;else if(a.position>b.position)a.position+=1;else if(a.position===b.position)return c?b.position+=1:a.position+=1,null;return{opSpecsA:[a],opSpecsB:[b]}},UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:d},UpdateMember:{UpdateMetadata:d,UpdateParagraphStyle: [...]
- c,d){var f,k=[a],g=[c];f=d?a:c;a=d?c:a;n(a.setProperties||null,a.removedProperties||null,f.setProperties||null,f.removedProperties||null);f.setProperties&&b(f.setProperties)||f.removedProperties&&p(f.removedProperties)||(d?k=[]:g=[]);a.setProperties&&b(a.setProperties)||a.removedProperties&&p(a.removedProperties)||(d?g=[]:k=[]);return{opSpecsA:k,opSpecsB:g}},UpdateParagraphStyle:d},UpdateParagraphStyle:{UpdateParagraphStyle:function(a,c,d){var f,k=[a],g=[c];a.styleName===c.styleName&&(f [...]
- c:a,r(a,f,"style:paragraph-properties"),r(a,f,"style:text-properties"),n(a.setProperties||null,a.removedProperties||null,f.setProperties||null,f.removedProperties||null),f.setProperties&&b(f.setProperties)||f.removedProperties&&p(f.removedProperties)||(d?k=[]:g=[]),a.setProperties&&b(a.setProperties)||a.removedProperties&&p(a.removedProperties)||(d?g=[]:k=[]));return{opSpecsA:k,opSpecsB:g}}}};this.passUnchanged=d;this.extendTransformations=function(a){Object.keys(a).forEach(function(b){ [...]
- d,f=k.hasOwnProperty(b);runtime.log((f?"Extending":"Adding")+" map for optypeA: "+b);f||(k[b]={});d=k[b];Object.keys(c).forEach(function(a){var f=d.hasOwnProperty(a);runtime.assert(b<=a,"Wrong order:"+b+", "+a);runtime.log(" "+(f?"Overwriting":"Adding")+" entry for optypeB: "+a);d[a]=c[a]})})};this.transformOpspecVsOpspec=function(a,b){var c=a.optype<=b.optype,d;runtime.log("Crosstransforming:");runtime.log(runtime.toJson(a));runtime.log(runtime.toJson(b));c||(d=a,a=b,b=d);(d=(d=k[a.op [...]
- (d=d(a,b,!c),c||null===d||(d={opSpecsA:d.opSpecsB,opSpecsB:d.opSpecsA})):d=null;runtime.log("result:");d?(runtime.log(runtime.toJson(d.opSpecsA)),runtime.log(runtime.toJson(d.opSpecsB))):runtime.log("null");return d}};
- // Input 71
++runtime.loadClass("ops.Member");ops.OpRemoveMember=function(){var g,k;this.init=function(e){g=e.memberid;k=parseInt(e.timestamp,10)};this.isEdit=!1;this.execute=function(e){if(!e.getMember(g))return!1;e.removeMember(g);e.emit(ops.OdtDocument.signalMemberRemoved,g);return!0};this.spec=function(){return{optype:"RemoveMember",memberid:g,timestamp:k}}};
++// Input 74
+/*
+
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
- This file is part of WebODF.
++ The JavaScript code in this page is free software: you can redistribute it
++ and/or modify it under the terms of the GNU Affero General Public License
++ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version. The code is distributed
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
- WebODF is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License (GNU AGPL)
- as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version.
++ You should have received a copy of the GNU Affero General Public License
++ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
- WebODF is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
++ As additional permission under GNU AGPL version 3 section 7, you
++ may distribute non-source (e.g., minimized or compacted) forms of
++ that code without the copy of the GNU GPL normally required by
++ section 4, provided you include this license notice and a URL
++ through which recipients can access the Corresponding Source.
+
- You should have received a copy of the GNU Affero General Public License
- along with WebODF. If not, see <http://www.gnu.org/licenses/>.
- @licend
++ As a special exception to the AGPL, any HTML file which merely makes function
++ calls to this code, and for that purpose includes it by reference shall be
++ deemed a separate work for copyright law purposes. In addition, the copyright
++ holders of this code give you permission to combine this code with free
++ software libraries that are released under the GNU LGPL. You may copy and
++ distribute such a system following the terms of the GNU AGPL for this code
++ and the LGPL for the libraries. If you modify this code, you may extend this
++ exception to your version of the code, but you are not obligated to do so.
++ If you do not wish to do so, delete this exception statement from your
++ version.
+
++ This license applies to this entire compilation.
++ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("ops.OperationFactory");runtime.loadClass("ops.OperationTransformMatrix");
- ops.OperationTransformer=function(){function g(f){var g=[];f.forEach(function(b){g.push(c.create(b))});return g}function l(c,g){for(var b,p,r=[],d=[];0<c.length&&g;){b=c.shift();b=m.transformOpspecVsOpspec(b,g);if(!b)return null;r=r.concat(b.opSpecsA);if(0===b.opSpecsB.length){r=r.concat(c);g=null;break}for(;1<b.opSpecsB.length;){p=l(c,b.opSpecsB.shift());if(!p)return null;d=d.concat(p.opSpecsB);c=p.opSpecsA}g=b.opSpecsB.pop()}g&&d.push(g);return{opSpecsA:r,opSpecsB:d}}var c,m=new ops.O [...]
- this.setOperationFactory=function(f){c=f};this.getOperationTransformMatrix=function(){return m};this.transform=function(c,m){for(var b,p=[];0<m.length;){b=l(c,m.shift());if(!b)return null;c=b.opSpecsA;p=p.concat(b.opSpecsB)}return{opsA:g(c),opsB:g(p)}}};
- // Input 72
- runtime.loadClass("core.Cursor");runtime.loadClass("gui.SelectionMover");
- ops.OdtCursor=function(g,l){var c=this,m={},f,n,b;this.removeFromOdtDocument=function(){b.remove()};this.move=function(b,f){var d=0;0<b?d=n.movePointForward(b,f):0>=b&&(d=-n.movePointBackward(-b,f));c.handleUpdate();return d};this.handleUpdate=function(){};this.getStepCounter=function(){return n.getStepCounter()};this.getMemberId=function(){return g};this.getNode=function(){return b.getNode()};this.getAnchorNode=function(){return b.getAnchorNode()};this.getSelectedRange=function(){retur [...]
- this.setSelectedRange=function(f,g){b.setSelectedRange(f,g);c.handleUpdate()};this.hasForwardSelection=function(){return b.hasForwardSelection()};this.getOdtDocument=function(){return l};this.getSelectionType=function(){return f};this.setSelectionType=function(b){m.hasOwnProperty(b)?f=b:runtime.log("Invalid selection type: "+b)};this.resetSelectionType=function(){c.setSelectionType(ops.OdtCursor.RangeSelection)};b=new core.Cursor(l.getDOM(),g);n=new gui.SelectionMover(b,l.getRootNode()) [...]
- !0;m[ops.OdtCursor.RegionSelection]=!0;c.resetSelectionType()};ops.OdtCursor.RangeSelection="Range";ops.OdtCursor.RegionSelection="Region";(function(){return ops.OdtCursor})();
- // Input 73
++ops.OpRemoveStyle=function(){var g,k,e,n;this.init=function(m){g=m.memberid;k=m.timestamp;e=m.styleName;n=m.styleFamily};this.isEdit=!0;this.execute=function(g){var k=g.getStyleElement(e,n);if(!k)return!1;k.parentNode.removeChild(k);g.getOdfCanvas().refreshCSS();g.emit(ops.OdtDocument.signalCommonStyleDeleted,{name:e,family:n});return!0};this.spec=function(){return{optype:"RemoveStyle",memberid:g,timestamp:k,styleName:e,styleFamily:n}}};
++// Input 75
+/*
+
- Copyright (C) 2012 KO GmbH <aditya.bhatt at kogmbh.com>
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.EditInfo=function(g,l){function c(){var c=[],b;for(b in f)f.hasOwnProperty(b)&&c.push({memberid:b,time:f[b].time});c.sort(function(b,c){return b.time-c.time});return c}var m,f={};this.getNode=function(){return m};this.getOdtDocument=function(){return l};this.getEdits=function(){return f};this.getSortedEdits=function(){return c()};this.addEdit=function(c,b){f[c]={time:b}};this.clearEdits=function(){f={}};this.destroy=function(c){g.parentNode&&g.removeChild(m);c()};m=l.getDOM().create [...]
- "editinfo");g.insertBefore(m,g.firstChild)};
- // Input 74
- runtime.loadClass("gui.SelectionMover");gui.ShadowCursor=function(g){var l=g.getDOM().createRange(),c=!0;this.removeFromOdtDocument=function(){};this.getMemberId=function(){return gui.ShadowCursor.ShadowCursorMemberId};this.getSelectedRange=function(){return l};this.setSelectedRange=function(g,f){l=g;c=!1!==f};this.hasForwardSelection=function(){return c};this.getOdtDocument=function(){return g};this.getSelectionType=function(){return ops.OdtCursor.RangeSelection};l.setStart(g.getRootNo [...]
- gui.ShadowCursor.ShadowCursorMemberId="";(function(){return gui.ShadowCursor})();
- // Input 75
- gui.Avatar=function(g,l){var c=this,m,f,n;this.setColor=function(b){f.style.borderColor=b};this.setImageUrl=function(b){c.isVisible()?f.src=b:n=b};this.isVisible=function(){return"block"===m.style.display};this.show=function(){n&&(f.src=n,n=void 0);m.style.display="block"};this.hide=function(){m.style.display="none"};this.markAsFocussed=function(b){m.className=b?"active":""};this.destroy=function(b){g.removeChild(m);b()};(function(){var b=g.ownerDocument,c=b.documentElement.namespaceURI [...]
- "div");f=b.createElementNS(c,"img");f.width=64;f.height=64;m.appendChild(f);m.style.width="64px";m.style.height="70px";m.style.position="absolute";m.style.top="-80px";m.style.left="-34px";m.style.display=l?"block":"none";g.appendChild(m)})()};
++runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.OdfUtils");runtime.loadClass("core.DomUtils");
++ops.OpRemoveText=function(){function g(e){function d(a){return h.hasOwnProperty(a.namespaceURI)||"br"===a.localName&&q.isLineBreak(a.parentNode)||a.nodeType===Node.TEXT_NODE&&h.hasOwnProperty(a.parentNode.namespaceURI)}function f(a){if(q.isCharacterElement(a))return!1;if(a.nodeType===Node.TEXT_NODE)return 0===a.textContent.length;for(a=a.firstChild;a;){if(h.hasOwnProperty(a.namespaceURI)||!f(a))return!1;a=a.nextSibling}return!0}function a(c){var g;c.nodeType===Node.TEXT_NODE?(g=c.parent [...]
++g=b.removeUnwantedNodes(c,d);return!q.isParagraph(g)&&g!==e&&f(g)?a(g):g}this.isEmpty=f;this.mergeChildrenIntoParent=a}var k,e,n,m,q,b,h={};this.init=function(g){runtime.assert(0<=g.length,"OpRemoveText only supports positive lengths");k=g.memberid;e=g.timestamp;n=parseInt(g.position,10);m=parseInt(g.length,10);q=new odf.OdfUtils;b=new core.DomUtils;h[odf.Namespaces.dbns]=!0;h[odf.Namespaces.dcns]=!0;h[odf.Namespaces.dr3dns]=!0;h[odf.Namespaces.drawns]=!0;h[odf.Namespaces.chartns]=!0;h[ [...]
++!0;h[odf.Namespaces.numberns]=!0;h[odf.Namespaces.officens]=!0;h[odf.Namespaces.presentationns]=!0;h[odf.Namespaces.stylens]=!0;h[odf.Namespaces.svgns]=!0;h[odf.Namespaces.tablens]=!0;h[odf.Namespaces.textns]=!0};this.isEdit=!0;this.execute=function(h){var d,f,a,c,p=h.getCursor(k),l=new g(h.getRootNode());h.upgradeWhitespacesAtPosition(n);h.upgradeWhitespacesAtPosition(n+m);f=h.convertCursorToDomRange(n,m);b.splitBoundaries(f);d=h.getParagraphElement(f.startContainer);a=q.getTextElement [...]
++c=q.getParagraphElements(f);f.detach();a.forEach(function(a){l.mergeChildrenIntoParent(a)});f=c.reduce(function(a,c){var b,d=!1,f=a,e=c,g,h=null;l.isEmpty(a)&&(d=!0,c.parentNode!==a.parentNode&&(g=c.parentNode,a.parentNode.insertBefore(c,a.nextSibling)),e=a,f=c,h=f.getElementsByTagNameNS("urn:webodf:names:editinfo","editinfo")[0]||f.firstChild);for(;e.hasChildNodes();)b=d?e.lastChild:e.firstChild,e.removeChild(b),"editinfo"!==b.localName&&f.insertBefore(b,h);g&&l.isEmpty(g)&&l.mergeChil [...]
++l.mergeChildrenIntoParent(e);return f});h.emit(ops.OdtDocument.signalStepsRemoved,{position:n,length:m});h.downgradeWhitespacesAtPosition(n);h.fixCursorPositions();h.getOdfCanvas().refreshSize();h.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:f||d,memberId:k,timeStamp:e});p&&(p.resetSelectionType(),h.emit(ops.OdtDocument.signalCursorMoved,p));h.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"RemoveText",memberid:k,timestamp:e,position:n [...]
+// Input 76
- runtime.loadClass("core.DomUtils");runtime.loadClass("gui.Avatar");runtime.loadClass("ops.OdtCursor");
- gui.Caret=function(g,l,c){function m(c){k&&r.parentNode&&(!a||c)&&(c&&void 0!==e&&runtime.clearTimeout(e),a=!0,b.style.opacity=c||"0"===b.style.opacity?"1":"0",e=runtime.setTimeout(function(){a=!1;m(!1)},500))}function f(a,b){var c=a.getBoundingClientRect(),d=0,e=0;c&&b&&(d=Math.max(c.top,b.top),e=Math.min(c.bottom,b.bottom));return e-d}function n(){var a;a=g.getSelectedRange().cloneRange();var c=g.getNode(),e,k=null;c.previousSibling&&(e=c.previousSibling.nodeType===Node.TEXT_NODE?c.pr [...]
- c.previousSibling.childNodes.length,a.setStart(c.previousSibling,0<e?e-1:0),a.setEnd(c.previousSibling,e),(e=a.getBoundingClientRect())&&e.height&&(k=e));c.nextSibling&&(a.setStart(c.nextSibling,0),a.setEnd(c.nextSibling,0<(c.nextSibling.nodeType===Node.TEXT_NODE?c.nextSibling.textContent.length:c.nextSibling.childNodes.length)?1:0),(e=a.getBoundingClientRect())&&e.height&&(!k||f(c,e)>f(c,k))&&(k=e));a=k;c=g.getOdtDocument().getOdfCanvas().getZoomLevel();d&&g.getSelectionType()===ops.Od [...]
- b.style.visibility="visible":b.style.visibility="hidden";a?(b.style.top="0",k=h.getBoundingClientRect(b),8>a.height&&(a={top:a.top-(8-a.height)/2,height:8}),b.style.height=h.adaptRangeDifferenceToZoomLevel(a.height,c)+"px",b.style.top=h.adaptRangeDifferenceToZoomLevel(a.top-k.top,c)+"px"):(b.style.height="1em",b.style.top="5%")}var b,p,r,d=!0,k=!1,a=!1,e,h=new core.DomUtils;this.handleUpdate=n;this.refreshCursorBlinking=function(){c||g.getSelectedRange().collapsed?(k=!0,m(!0)):(k=!1,b.s [...]
- "0")};this.setFocus=function(){k=!0;p.markAsFocussed(!0);m(!0)};this.removeFocus=function(){k=!1;p.markAsFocussed(!1);b.style.opacity="1"};this.show=function(){d=!0;n();p.markAsFocussed(!0)};this.hide=function(){d=!1;n();p.markAsFocussed(!1)};this.setAvatarImageUrl=function(a){p.setImageUrl(a)};this.setColor=function(a){b.style.borderColor=a;p.setColor(a)};this.getCursor=function(){return g};this.getFocusElement=function(){return b};this.toggleHandleVisibility=function(){p.isVisible()?p [...]
- this.showHandle=function(){p.show()};this.hideHandle=function(){p.hide()};this.ensureVisible=function(){var a,c,d,e,f=g.getOdtDocument().getOdfCanvas().getElement().parentNode,k;d=f.offsetWidth-f.clientWidth+5;e=f.offsetHeight-f.clientHeight+5;k=b.getBoundingClientRect();a=k.left-d;c=k.top-e;d=k.right+d;e=k.bottom+e;k=f.getBoundingClientRect();c<k.top?f.scrollTop-=k.top-c:e>k.bottom&&(f.scrollTop+=e-k.bottom);a<k.left?f.scrollLeft-=k.left-a:d>k.right&&(f.scrollLeft+=d-k.right);n()};this [...]
- a(c):(r.removeChild(b),a())})};(function(){var a=g.getOdtDocument().getDOM();b=a.createElementNS(a.documentElement.namespaceURI,"span");b.style.top="5%";r=g.getNode();r.appendChild(b);p=new gui.Avatar(r,l);n()})()};
- // Input 77
+/*
+
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- gui.PlainTextPasteboard=function(g,l){function c(c,f){c.init(f);return c}this.createPasteOps=function(m){var f=g.getCursorPosition(l),n=f,b=[];m.replace(/\r/g,"").split("\n").forEach(function(f){b.push(c(new ops.OpSplitParagraph,{memberid:l,position:n}));n+=1;b.push(c(new ops.OpInsertText,{memberid:l,position:n,text:f}));n+=f.length});b.push(c(new ops.OpRemoveText,{memberid:l,position:f,length:1}));return b}};
- // Input 78
++ops.OpSetBlob=function(){var g,k,e,n,m;this.init=function(q){g=q.memberid;k=q.timestamp;e=q.filename;n=q.mimetype;m=q.content};this.isEdit=!0;this.execute=function(g){g.getOdfCanvas().odfContainer().setBlob(e,n,m);return!0};this.spec=function(){return{optype:"SetBlob",memberid:g,timestamp:k,filename:e,mimetype:n,content:m}}};
++// Input 77
+/*
+
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("odf.Namespaces");runtime.loadClass("xmldom.LSSerializer");runtime.loadClass("odf.OdfNodeFilter");runtime.loadClass("odf.TextSerializer");
- gui.Clipboard=function(){var g,l,c;this.setDataFromRange=function(c,f){var n=!0,b,p=c.clipboardData;b=runtime.getWindow();var r=f.startContainer.ownerDocument;!p&&b&&(p=b.clipboardData);p?(r=r.createElement("span"),r.appendChild(f.cloneContents()),b=p.setData("text/plain",l.writeToString(r)),n=n&&b,b=p.setData("text/html",g.writeToString(r,odf.Namespaces.namespaceMap)),n=n&&b,c.preventDefault()):n=!1;return n};g=new xmldom.LSSerializer;l=new odf.TextSerializer;c=new odf.OdfNodeFilter;g. [...]
- c};
- // Input 79
++ops.OpSetParagraphStyle=function(){var g,k,e,n;this.init=function(m){g=m.memberid;k=m.timestamp;e=m.position;n=m.styleName};this.isEdit=!0;this.execute=function(m){var q;q=m.getIteratorAtPosition(e);return(q=m.getParagraphElement(q.container()))?(""!==n?q.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0","text:style-name",n):q.removeAttributeNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0","style-name"),m.getOdfCanvas().refreshSize(),m.emit(ops.OdtDocument.signalParagra [...]
++{paragraphElement:q,timeStamp:k,memberId:g}),m.getOdfCanvas().rerenderAnnotations(),!0):!1};this.spec=function(){return{optype:"SetParagraphStyle",memberid:g,timestamp:k,position:e,styleName:n}}};
++// Input 78
+/*
+
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.EventNotifier");runtime.loadClass("core.Utils");runtime.loadClass("ops.OpApplyDirectStyling");runtime.loadClass("gui.StyleHelper");
- gui.DirectTextStyler=function(g,l){function c(a,b){for(var c=0,d=b[c];d&&a;)a=a[d],c+=1,d=b[c];return b.length===c?a:void 0}function m(a,b){var d=c(a[0],b);return a.every(function(a){return d===c(a,b)})?d:void 0}function f(){var a=t.getCursor(l),a=(a=a&&a.getSelectedRange())&&s.getAppliedStyles(a)||[];a[0]&&A&&(a[0]=w.mergeObjects(a[0],A));return a}function n(){function a(b,d,e){b!==d&&(void 0===c&&(c={}),c[e]=d);return d}var b,c;B=f();M=a(M,B?s.isBold(B):!1,"isBold");z=a(z,B?s.isItalic [...]
- K=a(K,B?s.hasUnderline(B):!1,"hasUnderline");F=a(F,B?s.hasStrikeThrough(B):!1,"hasStrikeThrough");b=B&&m(B,["style:text-properties","fo:font-size"]);Q=a(Q,b&&parseFloat(b),"fontSize");$=a($,B&&m(B,["style:text-properties","style:font-name"]),"fontName");c&&D.emit(gui.DirectTextStyler.textStylingChanged,c)}function b(a){a.getMemberId()===l&&n()}function p(a){a===l&&n()}function r(a){a.getMemberId()===l&&n()}function d(){n()}function k(a){var b=t.getCursor(l);b&&t.getParagraphElement(b.ge [...]
- a.paragraphElement&&n()}function a(a,b){var c=t.getCursor(l);if(!c)return!1;c=s.getAppliedStyles(c.getSelectedRange());b(!a(c));return!0}function e(a){var b=t.getCursorSelection(l),c={"style:text-properties":a};0!==b.length?(a=new ops.OpApplyDirectStyling,a.init({memberid:l,position:b.position,length:b.length,setProperties:c}),g.enqueue([a])):(A=w.mergeObjects(A||{},c),n())}function h(a,b){var c={};c[a]=b;e(c)}function q(a){a=a.spec();A&&a.memberid===l&&"SplitParagraph"!==a.optype&&(A=n [...]
- a?"bold":"normal")}function x(a){h("fo:font-style",a?"italic":"normal")}function v(a){h("style:text-underline-style",a?"solid":"none")}function y(a){h("style:text-line-through-style",a?"solid":"none")}var w=new core.Utils,t=g.getOdtDocument(),s=new gui.StyleHelper(t.getFormatting()),D=new core.EventNotifier([gui.DirectTextStyler.textStylingChanged]),A,B=[],M=!1,z=!1,K=!1,F=!1,Q,$;this.formatTextSelection=e;this.createCursorStyleOp=function(a,b){var c=null;A&&(c=new ops.OpApplyDirectStyl [...]
- position:a,length:b,setProperties:A}),A=null,n());return c};this.setBold=u;this.setItalic=x;this.setHasUnderline=v;this.setHasStrikethrough=y;this.setFontSize=function(a){h("fo:font-size",a+"pt")};this.setFontName=function(a){h("style:font-name",a)};this.getAppliedStyles=function(){return B};this.toggleBold=a.bind(this,s.isBold,u);this.toggleItalic=a.bind(this,s.isItalic,x);this.toggleUnderline=a.bind(this,s.hasUnderline,v);this.toggleStrikethrough=a.bind(this,s.hasStrikeThrough,y);this [...]
- this.isItalic=function(){return z};this.hasUnderline=function(){return K};this.hasStrikeThrough=function(){return F};this.fontSize=function(){return Q};this.fontName=function(){return $};this.subscribe=function(a,b){D.subscribe(a,b)};this.unsubscribe=function(a,b){D.unsubscribe(a,b)};this.destroy=function(a){t.unsubscribe(ops.OdtDocument.signalCursorAdded,b);t.unsubscribe(ops.OdtDocument.signalCursorRemoved,p);t.unsubscribe(ops.OdtDocument.signalCursorMoved,r);t.unsubscribe(ops.OdtDocum [...]
- d);t.unsubscribe(ops.OdtDocument.signalParagraphChanged,k);t.unsubscribe(ops.OdtDocument.signalOperationExecuted,q);a()};t.subscribe(ops.OdtDocument.signalCursorAdded,b);t.subscribe(ops.OdtDocument.signalCursorRemoved,p);t.subscribe(ops.OdtDocument.signalCursorMoved,r);t.subscribe(ops.OdtDocument.signalParagraphStyleModified,d);t.subscribe(ops.OdtDocument.signalParagraphChanged,k);t.subscribe(ops.OdtDocument.signalOperationExecuted,q);n()};gui.DirectTextStyler.textStylingChanged="textSt [...]
- (function(){return gui.DirectTextStyler})();
++ops.OpSplitParagraph=function(){var g,k,e,n;this.init=function(m){g=m.memberid;k=m.timestamp;e=m.position;n=new odf.OdfUtils};this.isEdit=!0;this.execute=function(m){var q,b,h,r,d,f,a;m.upgradeWhitespacesAtPosition(e);q=m.getTextNodeAtStep(e,g);if(!q)return!1;b=m.getParagraphElement(q.textNode);if(!b)return!1;h=n.isListItem(b.parentNode)?b.parentNode:b;0===q.offset?(a=q.textNode.previousSibling,f=null):(a=q.textNode,f=q.offset>=q.textNode.length?null:q.textNode.splitText(q.offset));for( [...]
++h;){r=r.parentNode;d=r.cloneNode(!1);f&&d.appendChild(f);if(a)for(;a&&a.nextSibling;)d.appendChild(a.nextSibling);else for(;r.firstChild;)d.appendChild(r.firstChild);r.parentNode.insertBefore(d,r.nextSibling);a=r;f=d}n.isListItem(f)&&(f=f.childNodes[0]);0===q.textNode.length&&q.textNode.parentNode.removeChild(q.textNode);m.emit(ops.OdtDocument.signalStepsInserted,{position:e,length:1});m.fixCursorPositions();m.getOdfCanvas().refreshSize();m.emit(ops.OdtDocument.signalParagraphChanged,{p [...]
++memberId:g,timeStamp:k});m.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:f,memberId:g,timeStamp:k});m.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"SplitParagraph",memberid:g,timestamp:k,position:e}}};
++// Input 79
++/*
++
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ This file is part of WebODF.
++
++ WebODF is free software: you can redistribute it and/or modify it
++ under the terms of the GNU Affero General Public License (GNU AGPL)
++ as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version.
++
++ WebODF is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU Affero General Public License for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
++ @licend
++
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++runtime.loadClass("ops.Member");runtime.loadClass("xmldom.XPath");
++ops.OpUpdateMember=function(){function g(){var b="//dc:creator[@editinfo:memberid='"+k+"']",b=xmldom.XPath.getODFElementsWithXPath(q.getRootNode(),b,function(b){return"editinfo"===b?"urn:webodf:names:editinfo":odf.Namespaces.lookupNamespaceURI(b)}),e;for(e=0;e<b.length;e+=1)b[e].textContent=n.fullName}var k,e,n,m,q;this.init=function(b){k=b.memberid;e=parseInt(b.timestamp,10);n=b.setProperties;m=b.removedProperties};this.isEdit=!1;this.execute=function(b){q=b;var e=b.getMember(k);if(!e) [...]
++e.removeProperties(m);n&&(e.setProperties(n),n.fullName&&g());b.emit(ops.OdtDocument.signalMemberUpdated,e);return!0};this.spec=function(){return{optype:"UpdateMember",memberid:k,timestamp:e,setProperties:n,removedProperties:m}}};
+// Input 80
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
++ This file is part of WebODF.
++
++ WebODF is free software: you can redistribute it and/or modify it
++ under the terms of the GNU Affero General Public License (GNU AGPL)
++ as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version.
++
++ WebODF is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU Affero General Public License for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
++ @licend
++
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++ops.OpUpdateMetadata=function(){var g,k,e,n;this.init=function(m){g=m.memberid;k=parseInt(m.timestamp,10);e=m.setProperties;n=m.removedProperties};this.isEdit=!0;this.execute=function(g){g=g.getOdfCanvas().odfContainer().getMetadataManager();var k=[],b=["dc:date","dc:creator","meta:editing-cycles"];e&&b.forEach(function(b){if(e[b])return!1});n&&(b.forEach(function(b){if(-1!==k.indexOf(b))return!1}),k=n.attributes.split(","));g.setMetadata(e,k);return!0};this.spec=function(){return{optyp [...]
++memberid:g,timestamp:k,setProperties:e,removedProperties:n}}};
++// Input 81
++/*
++
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.EventNotifier");runtime.loadClass("core.Utils");runtime.loadClass("odf.OdfUtils");runtime.loadClass("ops.OpAddStyle");runtime.loadClass("ops.OpSetParagraphStyle");runtime.loadClass("gui.StyleHelper");
- gui.DirectParagraphStyler=function(g,l,c){function m(){function a(b,d,e){b!==d&&(void 0===c&&(c={}),c[e]=d);return d}var b=h.getCursor(l),b=b&&b.getSelectedRange(),c;y=a(y,b?x.isAlignedLeft(b):!1,"isAlignedLeft");w=a(w,b?x.isAlignedCenter(b):!1,"isAlignedCenter");t=a(t,b?x.isAlignedRight(b):!1,"isAlignedRight");s=a(s,b?x.isAlignedJustified(b):!1,"isAlignedJustified");c&&v.emit(gui.DirectParagraphStyler.paragraphStylingChanged,c)}function f(a){a.getMemberId()===l&&m()}function n(a){a===l [...]
- l&&m()}function p(){m()}function r(a){var b=h.getCursor(l);b&&h.getParagraphElement(b.getNode())===a.paragraphElement&&m()}function d(a){var b=h.getCursor(l).getSelectedRange(),d=h.getCursorPosition(l),b=u.getParagraphElements(b),e=h.getFormatting();b.forEach(function(b){var f=d+h.getDistanceFromCursor(l,b,0),k=b.getAttributeNS(odf.Namespaces.textns,"style-name");b=c.generateStyleName();var m,f=f+1;k&&(m=e.createDerivedStyleObject(k,"paragraph",{}));m=a(m||{});k=new ops.OpAddStyle;k.ini [...]
- styleName:b,styleFamily:"paragraph",isAutomaticStyle:!0,setProperties:m});m=new ops.OpSetParagraphStyle;m.init({memberid:l,styleName:b,position:f});g.enqueue([k,m])})}function k(a){d(function(b){return q.mergeObjects(b,a)})}function a(a){k({"style:paragraph-properties":{"fo:text-align":a}})}function e(a,b){var c=h.getFormatting().getDefaultTabStopDistance(),d=b["style:paragraph-properties"],d=(d=d&&d["fo:margin-left"])&&u.parseLength(d);return q.mergeObjects(b,{"style:paragraph-properti [...]
- d.unit===c.unit?d.value+a*c.value+d.unit:a*c.value+c.unit}})}var h=g.getOdtDocument(),q=new core.Utils,u=new odf.OdfUtils,x=new gui.StyleHelper(h.getFormatting()),v=new core.EventNotifier([gui.DirectParagraphStyler.paragraphStylingChanged]),y,w,t,s;this.isAlignedLeft=function(){return y};this.isAlignedCenter=function(){return w};this.isAlignedRight=function(){return t};this.isAlignedJustified=function(){return s};this.alignParagraphLeft=function(){a("left");return!0};this.alignParagraph [...]
- return!0};this.alignParagraphRight=function(){a("right");return!0};this.alignParagraphJustified=function(){a("justify");return!0};this.indent=function(){d(e.bind(null,1));return!0};this.outdent=function(){d(e.bind(null,-1));return!0};this.subscribe=function(a,b){v.subscribe(a,b)};this.unsubscribe=function(a,b){v.unsubscribe(a,b)};this.destroy=function(a){h.unsubscribe(ops.OdtDocument.signalCursorAdded,f);h.unsubscribe(ops.OdtDocument.signalCursorRemoved,n);h.unsubscribe(ops.OdtDocument. [...]
- b);h.unsubscribe(ops.OdtDocument.signalParagraphStyleModified,p);h.unsubscribe(ops.OdtDocument.signalParagraphChanged,r);a()};h.subscribe(ops.OdtDocument.signalCursorAdded,f);h.subscribe(ops.OdtDocument.signalCursorRemoved,n);h.subscribe(ops.OdtDocument.signalCursorMoved,b);h.subscribe(ops.OdtDocument.signalParagraphStyleModified,p);h.subscribe(ops.OdtDocument.signalParagraphChanged,r);m()};gui.DirectParagraphStyler.paragraphStylingChanged="paragraphStyling/changed";(function(){return g [...]
- // Input 81
++runtime.loadClass("odf.Namespaces");
++ops.OpUpdateParagraphStyle=function(){function g(b,e){var d,f,a=e?e.split(","):[];for(d=0;d<a.length;d+=1)f=a[d].split(":"),b.removeAttributeNS(odf.Namespaces.lookupNamespaceURI(f[0]),f[1])}var k,e,n,m,q,b=odf.Namespaces.stylens;this.init=function(b){k=b.memberid;e=b.timestamp;n=b.styleName;m=b.setProperties;q=b.removedProperties};this.isEdit=!0;this.execute=function(e){var k=e.getFormatting(),d,f,a;return(d=""!==n?e.getParagraphStyleElement(n):k.getDefaultStyleElement("paragraph"))?(f= [...]
++"paragraph-properties")[0],a=d.getElementsByTagNameNS(b,"text-properties")[0],m&&k.updateStyle(d,m),q&&(q["style:paragraph-properties"]&&(g(f,q["style:paragraph-properties"].attributes),0===f.attributes.length&&d.removeChild(f)),q["style:text-properties"]&&(g(a,q["style:text-properties"].attributes),0===a.attributes.length&&d.removeChild(a)),g(d,q.attributes)),e.getOdfCanvas().refreshCSS(),e.emit(ops.OdtDocument.signalParagraphStyleModified,n),e.getOdfCanvas().rerenderAnnotations(),!0): [...]
++function(){return{optype:"UpdateParagraphStyle",memberid:k,timestamp:e,styleName:n,setProperties:m,removedProperties:q}}};
++// Input 82
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- gui.KeyboardHandler=function(){function g(c,g){g||(g=l.None);return c+":"+g}var l=gui.KeyboardHandler.Modifier,c=null,m={};this.setDefault=function(f){c=f};this.bind=function(c,l,b){c=g(c,l);runtime.assert(!1===m.hasOwnProperty(c),"tried to overwrite the callback handler of key combo: "+c);m[c]=b};this.unbind=function(c,l){var b=g(c,l);delete m[b]};this.reset=function(){c=null;m={}};this.handleEvent=function(f){var n=f.keyCode,b=l.None;f.metaKey&&(b|=l.Meta);f.ctrlKey&&(b|=l.Ctrl);f.alt [...]
- f.shiftKey&&(b|=l.Shift);n=g(n,b);n=m[n];b=!1;n?b=n():null!==c&&(b=c(f));b&&(f.preventDefault?f.preventDefault():f.returnValue=!1)}};gui.KeyboardHandler.Modifier={None:0,Meta:1,Ctrl:2,Alt:4,CtrlAlt:6,Shift:8,MetaShift:9,CtrlShift:10,AltShift:12};gui.KeyboardHandler.KeyCode={Backspace:8,Tab:9,Clear:12,Enter:13,End:35,Home:36,Left:37,Up:38,Right:39,Down:40,Delete:46,A:65,B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89 [...]
- // Input 82
- runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.ObjectNameGenerator");
- gui.ImageManager=function(g,l,c){var m={"image/gif":".gif","image/jpeg":".jpg","image/png":".png"},f=odf.Namespaces.textns,n=g.getOdtDocument(),b=n.getFormatting(),p={};this.insertImage=function(r,d,k,a){var e;runtime.assert(0<k&&0<a,"Both width and height of the image should be greater than 0px.");e=n.getParagraphElement(n.getCursor(l).getNode()).getAttributeNS(f,"style-name");p.hasOwnProperty(e)||(p[e]=b.getContentSize(e,"paragraph"));e=p[e];k*=0.0264583333333334;a*=0.0264583333333334 [...]
- 1;k>e.width&&(h=e.width/k);a>e.height&&(q=e.height/a);h=Math.min(h,q);e=k*h;k=a*h;q=n.getOdfCanvas().odfContainer().rootElement.styles;a=r.toLowerCase();var h=m.hasOwnProperty(a)?m[a]:null,u;a=[];runtime.assert(null!==h,"Image type is not supported: "+r);h="Pictures/"+c.generateImageName()+h;u=new ops.OpSetBlob;u.init({memberid:l,filename:h,mimetype:r,content:d});a.push(u);b.getStyleElement("Graphics","graphic",[q])||(r=new ops.OpAddStyle,r.init({memberid:l,styleName:"Graphics",styleFam [...]
- isAutomaticStyle:!1,setProperties:{"style:graphic-properties":{"text:anchor-type":"paragraph","svg:x":"0cm","svg:y":"0cm","style:wrap":"dynamic","style:number-wrapped-paragraphs":"no-limit","style:wrap-contour":"false","style:vertical-pos":"top","style:vertical-rel":"paragraph","style:horizontal-pos":"center","style:horizontal-rel":"paragraph"}}}),a.push(r));r=c.generateStyleName();d=new ops.OpAddStyle;d.init({memberid:l,styleName:r,styleFamily:"graphic",isAutomaticStyle:!0,setPropertie [...]
- "style:graphic-properties":{"style:vertical-pos":"top","style:vertical-rel":"baseline","style:horizontal-pos":"center","style:horizontal-rel":"paragraph","fo:background-color":"transparent","style:background-transparency":"100%","style:shadow":"none","style:mirror":"none","fo:clip":"rect(0cm, 0cm, 0cm, 0cm)","draw:luminance":"0%","draw:contrast":"0%","draw:red":"0%","draw:green":"0%","draw:blue":"0%","draw:gamma":"100%","draw:color-inversion":"false","draw:image-opacity":"100%","draw:co [...]
- a.push(d);u=new ops.OpInsertImage;u.init({memberid:l,position:n.getCursorPosition(l),filename:h,frameWidth:e+"cm",frameHeight:k+"cm",frameStyleName:r,frameName:c.generateFrameName()});a.push(u);g.enqueue(a)}};
++runtime.loadClass("ops.OpAddMember");runtime.loadClass("ops.OpUpdateMember");runtime.loadClass("ops.OpRemoveMember");runtime.loadClass("ops.OpAddCursor");runtime.loadClass("ops.OpApplyDirectStyling");runtime.loadClass("ops.OpRemoveCursor");runtime.loadClass("ops.OpMoveCursor");runtime.loadClass("ops.OpSetBlob");runtime.loadClass("ops.OpRemoveBlob");runtime.loadClass("ops.OpInsertImage");runtime.loadClass("ops.OpInsertTable");runtime.loadClass("ops.OpInsertText");runtime.loadClass("ops.O [...]
++runtime.loadClass("ops.OpSplitParagraph");runtime.loadClass("ops.OpSetParagraphStyle");runtime.loadClass("ops.OpUpdateParagraphStyle");runtime.loadClass("ops.OpAddStyle");runtime.loadClass("ops.OpRemoveStyle");runtime.loadClass("ops.OpAddAnnotation");runtime.loadClass("ops.OpRemoveAnnotation");runtime.loadClass("ops.OpUpdateMetadata");
++ops.OperationFactory=function(){function g(e){return function(){return new e}}var k;this.register=function(e,g){k[e]=g};this.create=function(e){var g=null,m=k[e.optype];m&&(g=m(e),g.init(e));return g};k={AddMember:g(ops.OpAddMember),UpdateMember:g(ops.OpUpdateMember),RemoveMember:g(ops.OpRemoveMember),AddCursor:g(ops.OpAddCursor),ApplyDirectStyling:g(ops.OpApplyDirectStyling),SetBlob:g(ops.OpSetBlob),RemoveBlob:g(ops.OpRemoveBlob),InsertImage:g(ops.OpInsertImage),InsertTable:g(ops.OpIns [...]
++InsertText:g(ops.OpInsertText),RemoveText:g(ops.OpRemoveText),SplitParagraph:g(ops.OpSplitParagraph),SetParagraphStyle:g(ops.OpSetParagraphStyle),UpdateParagraphStyle:g(ops.OpUpdateParagraphStyle),AddStyle:g(ops.OpAddStyle),RemoveStyle:g(ops.OpRemoveStyle),MoveCursor:g(ops.OpMoveCursor),RemoveCursor:g(ops.OpRemoveCursor),AddAnnotation:g(ops.OpAddAnnotation),RemoveAnnotation:g(ops.OpRemoveAnnotation),UpdateMetadata:g(ops.OpUpdateMetadata)}};
+// Input 83
- runtime.loadClass("odf.Namespaces");
- gui.ImageSelector=function(g){function l(){var b=g.getSizer(),c,l;c=f.createElement("div");c.id="imageSelector";c.style.borderWidth="1px";b.appendChild(c);m.forEach(function(b){l=f.createElement("div");l.className=b;c.appendChild(l)});return c}var c=odf.Namespaces.svgns,m="topLeft topRight bottomRight bottomLeft topMiddle rightMiddle bottomMiddle leftMiddle".split(" "),f=g.getElement().ownerDocument,n=!1;this.select=function(b){var m,r,d=f.getElementById("imageSelector");d||(d=l());n=!0 [...]
- r=b.getBoundingClientRect();var k=m.getBoundingClientRect(),a=g.getZoomLevel();m=(r.left-k.left)/a-1;r=(r.top-k.top)/a-1;d.style.display="block";d.style.left=m+"px";d.style.top=r+"px";d.style.width=b.getAttributeNS(c,"width");d.style.height=b.getAttributeNS(c,"height")};this.clearSelection=function(){var b;n&&(b=f.getElementById("imageSelector"))&&(b.style.display="none");n=!1};this.isSelectorElement=function(b){var c=f.getElementById("imageSelector");return c?b===c||b.parentNode===c:!1}};
- // Input 84
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.PositionFilter");
- gui.TextManipulator=function(g,l,c){function m(b){var c=new ops.OpRemoveText;c.init({memberid:l,position:b.position,length:b.length});return c}function f(b){0>b.length&&(b.position+=b.length,b.length=-b.length);return b}function n(c,d){var f=new core.PositionFilterChain,a=gui.SelectionMover.createPositionIterator(b.getRootElement(c)),e=d?a.nextPosition:a.previousPosition;f.addFilter("BaseFilter",b.getPositionFilter());f.addFilter("RootFilter",b.createRootFilter(l));for(a.setUnfilteredPo [...]
- p)return!0;return!1}var b=g.getOdtDocument(),p=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.enqueueParagraphSplittingOps=function(){var c=f(b.getCursorSelection(l)),d,k=[];0<c.length&&(d=m(c),k.push(d));d=new ops.OpSplitParagraph;d.init({memberid:l,position:c.position});k.push(d);g.enqueue(k);return!0};this.removeTextByBackspaceKey=function(){var c=b.getCursor(l),d=f(b.getCursorSelection(l)),k=null;0===d.length?n(c.getNode(),!1)&&(k=new ops.OpRemoveText,k.init({memberid:l,positio [...]
- 1,length:1}),g.enqueue([k])):(k=m(d),g.enqueue([k]));return null!==k};this.removeTextByDeleteKey=function(){var c=b.getCursor(l),d=f(b.getCursorSelection(l)),k=null;0===d.length?n(c.getNode(),!0)&&(k=new ops.OpRemoveText,k.init({memberid:l,position:d.position,length:1}),g.enqueue([k])):(k=m(d),g.enqueue([k]));return null!==k};this.removeCurrentSelection=function(){var c=f(b.getCursorSelection(l));0!==c.length&&(c=m(c),g.enqueue([c]));return!0};this.insertText=function(n){var d=f(b.getCu [...]
- k,a=[];0<d.length&&(k=m(d),a.push(k));k=new ops.OpInsertText;k.init({memberid:l,position:d.position,text:n});a.push(k);c&&(n=c(d.position,n.length))&&a.push(n);g.enqueue(a)}};(function(){return gui.TextManipulator})();
++ops.OperationRouter=function(){};ops.OperationRouter.prototype.setOperationFactory=function(g){};ops.OperationRouter.prototype.setPlaybackFunction=function(g){};ops.OperationRouter.prototype.push=function(g){};ops.OperationRouter.prototype.close=function(g){};ops.OperationRouter.prototype.subscribe=function(g,k){};ops.OperationRouter.prototype.unsubscribe=function(g,k){};ops.OperationRouter.prototype.hasLocalUnsyncedOps=function(){};ops.OperationRouter.prototype.hasSessionHostConnection [...]
++// Input 84
++/*
++
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ This file is part of WebODF.
++
++ WebODF is free software: you can redistribute it and/or modify it
++ under the terms of the GNU Affero General Public License (GNU AGPL)
++ as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version.
++
++ WebODF is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU Affero General Public License for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
++ @licend
++
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++ops.OperationTransformMatrix=function(){function g(a){a.position+=a.length;a.length*=-1}function k(a){var c=0>a.length;c&&g(a);return c}function e(a,c){var b=[];a&&["style:parent-style-name","style:next-style-name"].forEach(function(d){a[d]===c&&b.push(d)});return b}function n(a,c){a&&["style:parent-style-name","style:next-style-name"].forEach(function(b){a[b]===c&&delete a[b]})}function m(a){var c={};Object.keys(a).forEach(function(b){c[b]="object"===typeof a[b]?m(a[b]):a[b]});return c [...]
++c,b,d){var f,e,g=!1,h=!1,k,m,n=d&&d.attributes?d.attributes.split(","):[];a&&(b||0<n.length)&&Object.keys(a).forEach(function(c){f=a[c];"object"!==typeof f&&(k=b&&b[c],void 0!==k?(delete a[c],h=!0,k===f&&(delete b[c],g=!0)):n&&-1!==n.indexOf(c)&&(delete a[c],h=!0))});if(c&&c.attributes&&(b||0<n.length)){m=c.attributes.split(",");for(d=0;d<m.length;d+=1)if(e=m[d],b&&void 0!==b[e]||n&&-1!==n.indexOf(e))m.splice(d,1),d-=1,h=!0;0<m.length?c.attributes=m.join(","):delete c.attributes}return{ [...]
++minorChanged:h}}function b(a){for(var c in a)if(a.hasOwnProperty(c))return!0;return!1}function h(a){for(var c in a)if(a.hasOwnProperty(c)&&("attributes"!==c||0<a.attributes.length))return!0;return!1}function r(a,c,d){var f=a.setProperties?a.setProperties[d]:null,e=a.removedProperties?a.removedProperties[d]:null,g=c.setProperties?c.setProperties[d]:null,k=c.removedProperties?c.removedProperties[d]:null,m;m=q(f,e,g,k);f&&!b(f)&&delete a.setProperties[d];e&&!h(e)&&delete a.removedPropertie [...]
++delete c.setProperties[d];k&&!h(k)&&delete c.removedProperties[d];return m}function d(a,c){return{opSpecsA:[a],opSpecsB:[c]}}var f={AddCursor:{AddCursor:d,AddMember:d,AddStyle:d,ApplyDirectStyling:d,InsertText:d,MoveCursor:d,RemoveCursor:d,RemoveMember:d,RemoveStyle:d,RemoveText:d,SetParagraphStyle:d,SplitParagraph:d,UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:d},AddMember:{AddStyle:d,InsertText:d,MoveCursor:d,RemoveCursor:d,RemoveStyle:d,RemoveText:d,SetParagraphStyle:d,SplitP [...]
++UpdateMetadata:d,UpdateParagraphStyle:d},AddStyle:{AddStyle:d,ApplyDirectStyling:d,InsertText:d,MoveCursor:d,RemoveCursor:d,RemoveMember:d,RemoveStyle:function(a,c){var b,d=[a],f=[c];a.styleFamily===c.styleFamily&&(b=e(a.setProperties,c.styleName),0<b.length&&(b={optype:"UpdateParagraphStyle",memberid:c.memberid,timestamp:c.timestamp,styleName:a.styleName,removedProperties:{attributes:b.join(",")}},f.unshift(b)),n(a.setProperties,c.styleName));return{opSpecsA:d,opSpecsB:f}},RemoveText:d [...]
++SplitParagraph:d,UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:d},ApplyDirectStyling:{ApplyDirectStyling:function(a,c,d){var f,e,g,h,k,n,q,s;h=[a];g=[c];if(!(a.position+a.length<=c.position||a.position>=c.position+c.length)){f=d?a:c;e=d?c:a;if(a.position!==c.position||a.length!==c.length)n=m(f),q=m(e);c=r(e,f,"style:text-properties");if(c.majorChanged||c.minorChanged)g=[],a=[],h=f.position+f.length,k=e.position+e.length,e.position<f.position?c.minorChanged&&(s=m(q),s.length=f.pos [...]
++a.push(s),e.position=f.position,e.length=k-e.position):f.position<e.position&&c.majorChanged&&(s=m(n),s.length=e.position-f.position,g.push(s),f.position=e.position,f.length=h-f.position),k>h?c.minorChanged&&(n=q,n.position=h,n.length=k-h,a.push(n),e.length=h-e.position):h>k&&c.majorChanged&&(n.position=k,n.length=h-k,g.push(n),f.length=k-f.position),f.setProperties&&b(f.setProperties)&&g.push(f),e.setProperties&&b(e.setProperties)&&a.push(e),d?(h=g,g=a):h=a}return{opSpecsA:h,opSpecsB:g [...]
++c){c.position<=a.position?a.position+=c.text.length:c.position<=a.position+a.length&&(a.length+=c.text.length);return{opSpecsA:[a],opSpecsB:[c]}},MoveCursor:d,RemoveCursor:d,RemoveStyle:d,RemoveText:function(a,c){var b=a.position+a.length,d=c.position+c.length,f=[a],e=[c];d<=a.position?a.position-=c.length:c.position<b&&(a.position<c.position?a.length=d<b?a.length-c.length:c.position-a.position:(a.position=c.position,d<b?a.length=b-d:f=[]));return{opSpecsA:f,opSpecsB:e}},SetParagraphSty [...]
++c){c.position<a.position?a.position+=1:c.position<a.position+a.length&&(a.length+=1);return{opSpecsA:[a],opSpecsB:[c]}},UpdateMetadata:d,UpdateParagraphStyle:d},InsertText:{InsertText:function(a,c,b){if(a.position<c.position)c.position+=a.text.length;else if(a.position>c.position)a.position+=c.text.length;else return b?c.position+=a.text.length:a.position+=c.text.length,null;return{opSpecsA:[a],opSpecsB:[c]}},MoveCursor:function(a,c){var b=k(c);a.position<c.position?c.position+=a.text.l [...]
++c.position+c.length&&(c.length+=a.text.length);b&&g(c);return{opSpecsA:[a],opSpecsB:[c]}},RemoveCursor:d,RemoveMember:d,RemoveStyle:d,RemoveText:function(a,c){var b;b=c.position+c.length;var d=[a],f=[c];b<=a.position?a.position-=c.length:a.position<=c.position?c.position+=a.text.length:(c.length=a.position-c.position,b={optype:"RemoveText",memberid:c.memberid,timestamp:c.timestamp,position:a.position+a.text.length,length:b-a.position},f.unshift(b),a.position=c.position);return{opSpecsA: [...]
++SplitParagraph:function(a,c,b){if(a.position<c.position)c.position+=a.text.length;else if(a.position>c.position)a.position+=1;else return b?c.position+=a.text.length:a.position+=1,null;return{opSpecsA:[a],opSpecsB:[c]}},UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:d},MoveCursor:{MoveCursor:d,RemoveCursor:function(a,c){return{opSpecsA:a.memberid===c.memberid?[]:[a],opSpecsB:[c]}},RemoveMember:d,RemoveStyle:d,RemoveText:function(a,c){var b=k(a),d=a.position+a.length,f=c.position+c [...]
++a.position?a.position-=c.length:c.position<d&&(a.position<c.position?a.length=f<d?a.length-c.length:c.position-a.position:(a.position=c.position,a.length=f<d?d-f:0));b&&g(a);return{opSpecsA:[a],opSpecsB:[c]}},SetParagraphStyle:d,SplitParagraph:function(a,b){var d=k(a);b.position<a.position?a.position+=1:b.position<a.position+a.length&&(a.length+=1);d&&g(a);return{opSpecsA:[a],opSpecsB:[b]}},UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:d},RemoveCursor:{RemoveCursor:function(a,b){ [...]
++b.memberid;return{opSpecsA:d?[]:[a],opSpecsB:d?[]:[b]}},RemoveMember:d,RemoveStyle:d,RemoveText:d,SetParagraphStyle:d,SplitParagraph:d,UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:d},RemoveMember:{RemoveStyle:d,RemoveText:d,SetParagraphStyle:d,SplitParagraph:d,UpdateMetadata:d,UpdateParagraphStyle:d},RemoveStyle:{RemoveStyle:function(a,b){var d=a.styleName===b.styleName&&a.styleFamily===b.styleFamily;return{opSpecsA:d?[]:[a],opSpecsB:d?[]:[b]}},RemoveText:d,SetParagraphStyle:fun [...]
++f=[a],e=[b];"paragraph"===a.styleFamily&&a.styleName===b.styleName&&(d={optype:"SetParagraphStyle",memberid:a.memberid,timestamp:a.timestamp,position:b.position,styleName:""},f.unshift(d),b.styleName="");return{opSpecsA:f,opSpecsB:e}},SplitParagraph:d,UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:function(a,b){var d,f=[a],g=[b];"paragraph"===a.styleFamily&&(d=e(b.setProperties,a.styleName),0<d.length&&(d={optype:"UpdateParagraphStyle",memberid:a.memberid,timestamp:a.timestamp,sty [...]
++removedProperties:{attributes:d.join(",")}},f.unshift(d)),a.styleName===b.styleName?g=[]:n(b.setProperties,a.styleName));return{opSpecsA:f,opSpecsB:g}}},RemoveText:{RemoveText:function(a,b){var d=a.position+a.length,f=b.position+b.length,e=[a],g=[b];f<=a.position?a.position-=b.length:d<=b.position?b.position-=a.length:b.position<d&&(a.position<b.position?(a.length=f<d?a.length-b.length:b.position-a.position,d<f?(b.position=a.position,b.length=f-d):g=[]):(d<f?b.length-=a.length:b.positio [...]
++b.length=a.position-b.position:g=[],f<d?(a.position=b.position,a.length=d-f):e=[]));return{opSpecsA:e,opSpecsB:g}},SplitParagraph:function(a,b){var d=a.position+a.length,f=[a],e=[b];b.position<=a.position?a.position+=1:b.position<d&&(a.length=b.position-a.position,d={optype:"RemoveText",memberid:a.memberid,timestamp:a.timestamp,position:b.position+1,length:d-b.position},f.unshift(d));a.position+a.length<=b.position?b.position-=a.length:a.position<b.position&&(b.position=a.position);retu [...]
++opSpecsB:e}},UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:d},SetParagraphStyle:{UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:d},SplitParagraph:{SplitParagraph:function(a,b,d){if(a.position<b.position)b.position+=1;else if(a.position>b.position)a.position+=1;else if(a.position===b.position)return d?b.position+=1:a.position+=1,null;return{opSpecsA:[a],opSpecsB:[b]}},UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:d},UpdateMember:{UpdateMetadata:d,UpdateParagraphStyle: [...]
++c,d){var f,e=[a],g=[c];f=d?a:c;a=d?c:a;q(a.setProperties||null,a.removedProperties||null,f.setProperties||null,f.removedProperties||null);f.setProperties&&b(f.setProperties)||f.removedProperties&&h(f.removedProperties)||(d?e=[]:g=[]);a.setProperties&&b(a.setProperties)||a.removedProperties&&h(a.removedProperties)||(d?g=[]:e=[]);return{opSpecsA:e,opSpecsB:g}},UpdateParagraphStyle:d},UpdateParagraphStyle:{UpdateParagraphStyle:function(a,c,d){var f,e=[a],g=[c];a.styleName===c.styleName&&(f [...]
++c:a,r(a,f,"style:paragraph-properties"),r(a,f,"style:text-properties"),q(a.setProperties||null,a.removedProperties||null,f.setProperties||null,f.removedProperties||null),f.setProperties&&b(f.setProperties)||f.removedProperties&&h(f.removedProperties)||(d?e=[]:g=[]),a.setProperties&&b(a.setProperties)||a.removedProperties&&h(a.removedProperties)||(d?g=[]:e=[]));return{opSpecsA:e,opSpecsB:g}}}};this.passUnchanged=d;this.extendTransformations=function(a){Object.keys(a).forEach(function(b){ [...]
++e,g=f.hasOwnProperty(b);runtime.log((g?"Extending":"Adding")+" map for optypeA: "+b);g||(f[b]={});e=f[b];Object.keys(d).forEach(function(a){var f=e.hasOwnProperty(a);runtime.assert(b<=a,"Wrong order:"+b+", "+a);runtime.log(" "+(f?"Overwriting":"Adding")+" entry for optypeB: "+a);e[a]=d[a]})})};this.transformOpspecVsOpspec=function(a,b){var d=a.optype<=b.optype,e;runtime.log("Crosstransforming:");runtime.log(runtime.toJson(a));runtime.log(runtime.toJson(b));d||(e=a,a=b,b=e);(e=(e=f[a.op [...]
++(e=e(a,b,!d),d||null===e||(e={opSpecsA:e.opSpecsB,opSpecsB:e.opSpecsA})):e=null;runtime.log("result:");e?(runtime.log(runtime.toJson(e.opSpecsA)),runtime.log(runtime.toJson(e.opSpecsB))):runtime.log("null");return e}};
+// Input 85
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ This file is part of WebODF.
+
+ WebODF is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License (GNU AGPL)
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ WebODF is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ @licend
+
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.EventNotifier");runtime.loadClass("core.PositionFilter");runtime.loadClass("ops.OpAddAnnotation");runtime.loadClass("ops.OpRemoveAnnotation");runtime.loadClass("gui.SelectionMover");
- gui.AnnotationController=function(g,l){function c(){var c=b.getCursor(l),c=c&&c.getNode(),a;if(a=c){a:{for(a=b.getRootNode();c&&c!==a;){if(c.namespaceURI===d&&"annotation"===c.localName){c=!0;break a}c=c.parentNode}c=!1}a=!c}c=a;c!==p&&(p=c,r.emit(gui.AnnotationController.annotatableChanged,p))}function m(b){b.getMemberId()===l&&c()}function f(b){b===l&&c()}function n(b){b.getMemberId()===l&&c()}var b=g.getOdtDocument(),p=!1,r=new core.EventNotifier([gui.AnnotationController.annotatable [...]
- d=odf.Namespaces.officens;this.isAnnotatable=function(){return p};this.addAnnotation=function(){var c=new ops.OpAddAnnotation,a=b.getCursorSelection(l),d=a.length,a=a.position;p&&(a=0<=d?a:a+d,d=Math.abs(d),c.init({memberid:l,position:a,length:d,name:l+Date.now()}),g.enqueue([c]))};this.removeAnnotation=function(c){var a,d;a=b.convertDomPointToCursorStep(c,0)+1;d=b.convertDomPointToCursorStep(c,c.childNodes.length);c=new ops.OpRemoveAnnotation;c.init({memberid:l,position:a,length:d-a}); [...]
- d.init({memberid:l,position:0<a?a-1:a,length:0});g.enqueue([c,d])};this.subscribe=function(b,a){r.subscribe(b,a)};this.unsubscribe=function(b,a){r.unsubscribe(b,a)};this.destroy=function(c){b.unsubscribe(ops.OdtDocument.signalCursorAdded,m);b.unsubscribe(ops.OdtDocument.signalCursorRemoved,f);b.unsubscribe(ops.OdtDocument.signalCursorMoved,n);c()};b.subscribe(ops.OdtDocument.signalCursorAdded,m);b.subscribe(ops.OdtDocument.signalCursorRemoved,f);b.subscribe(ops.OdtDocument.signalCursorM [...]
- gui.AnnotationController.annotatableChanged="annotatable/changed";(function(){return gui.AnnotationController})();
++runtime.loadClass("ops.OperationFactory");runtime.loadClass("ops.OperationTransformMatrix");
++ops.OperationTransformer=function(){function g(g){var k=[];g.forEach(function(b){k.push(e.create(b))});return k}function k(e,g){for(var b,h,r=[],d=[];0<e.length&&g;){b=e.shift();b=n.transformOpspecVsOpspec(b,g);if(!b)return null;r=r.concat(b.opSpecsA);if(0===b.opSpecsB.length){r=r.concat(e);g=null;break}for(;1<b.opSpecsB.length;){h=k(e,b.opSpecsB.shift());if(!h)return null;d=d.concat(h.opSpecsB);e=h.opSpecsA}g=b.opSpecsB.pop()}g&&d.push(g);return{opSpecsA:r,opSpecsB:d}}var e,n=new ops.O [...]
++this.setOperationFactory=function(g){e=g};this.getOperationTransformMatrix=function(){return n};this.transform=function(e,n){for(var b,h=[];0<n.length;){b=k(e,n.shift());if(!b)return null;e=b.opSpecsA;h=h.concat(b.opSpecsB)}return{opsA:g(e),opsB:g(h)}}};
+// Input 86
- gui.EventManager=function(g){function l(){var b=this,a=[];this.handlers=[];this.isSubscribed=!1;this.handleEvent=function(c){-1===a.indexOf(c)&&(a.push(c),b.handlers.forEach(function(a){a(c)}),runtime.setTimeout(function(){a.splice(a.indexOf(c),1)},0))}}function c(b){var a=b.scrollX,c=b.scrollY;this.restore=function(){b.scrollX===a&&b.scrollY===c||b.scrollTo(a,c)}}function m(b){var a=b.scrollTop,c=b.scrollLeft;this.restore=function(){if(b.scrollTop!==a||b.scrollLeft!==c)b.scrollTop=a,b. [...]
- c}}function f(b,a,c){var d="on"+a,f=!1;b.attachEvent&&(f=b.attachEvent(d,c));!f&&b.addEventListener&&(b.addEventListener(a,c,!1),f=!0);f&&!r[a]||!b.hasOwnProperty(d)||(b[d]=c)}function n(){return g.getDOM().activeElement===b}var b=g.getOdfCanvas().getElement(),p=runtime.getWindow(),r={beforecut:!0,beforepaste:!0},d;this.subscribe=function(c,a){var e=p&&d[c];e?(e.handlers.push(a),e.isSubscribed||(e.isSubscribed=!0,f(p,c,e.handleEvent),f(b,c,e.handleEvent))):f(b,c,a)};this.unsubscribe=fun [...]
- p&&d[c],f=e&&e.handlers.indexOf(a);e?-1!==f&&e.handlers.splice(f,1):(e=b,f="on"+c,e.detachEvent&&e.detachEvent(f,a),e.removeEventListener&&e.removeEventListener(c,a,!1),e[f]===a&&(e[f]=null))};this.hasFocus=n;this.focus=function(){var d;if(!n()){for(d=b;d&&!d.scrollTop&&!d.scrollLeft;)d=d.parentNode;d=d?new m(d):p?new c(p):null;b.focus();d&&d.restore()}};d={mousedown:new l,mouseup:new l}};
- // Input 87
- runtime.loadClass("core.DomUtils");runtime.loadClass("core.Async");runtime.loadClass("core.ScheduledTask");runtime.loadClass("odf.OdfUtils");runtime.loadClass("odf.ObjectNameGenerator");runtime.loadClass("ops.OdtCursor");runtime.loadClass("ops.OpAddCursor");runtime.loadClass("ops.OpRemoveCursor");runtime.loadClass("gui.Clipboard");runtime.loadClass("gui.DirectTextStyler");runtime.loadClass("gui.DirectParagraphStyler");runtime.loadClass("gui.KeyboardHandler");runtime.loadClass("gui.Image [...]
- runtime.loadClass("gui.ImageSelector");runtime.loadClass("gui.TextManipulator");runtime.loadClass("gui.AnnotationController");runtime.loadClass("gui.EventManager");runtime.loadClass("gui.PlainTextPasteboard");
- gui.SessionController=function(){var g=core.PositionFilter.FilterResult.FILTER_ACCEPT;gui.SessionController=function(l,c,m,f){function n(a){a.preventDefault?a.preventDefault():a.returnValue=!1}function b(a,b,d){var e=new ops.OpMoveCursor;e.init({memberid:c,position:a,length:b||0,selectionType:d});return e}function p(a){a=H.getDistanceFromCursor(c,a,0);var d=null!==a?a+1:null,e;if(d||a)e=H.getCursorPosition(c),a=b(e+a,d-a,ops.OdtCursor.RegionSelection),l.enqueue([a]);X.focus()}function r [...]
- f,g,h;f=H.getOdfCanvas().getElement();e=d.detail;if(a){if(!a.anchorNode&&!a.focusNode){g=d.clientX;h=d.clientY;var k=H.getDOM();k.caretRangeFromPoint?(g=k.caretRangeFromPoint(g,h),g={container:g.startContainer,offset:g.startOffset}):k.caretPositionFromPoint?(g=k.caretPositionFromPoint(g,h),g={container:g.offsetNode,offset:g.offset}):g=null;if(!g)return;a.anchorNode=g.container;a.anchorOffset=g.offset;a.focusNode=a.anchorNode;a.focusOffset=a.anchorOffset}runtime.assert(null!==a.anchorNod [...]
- a.focusNode,"anchorNode or focusNode is null");g=fa.containsNode(f,a.anchorNode);f=fa.containsNode(f,a.focusNode);if(g||f){if(g&&f)if(2===e){var k=/[A-Za-z0-9]/,m=gui.SelectionMover.createPositionIterator(H.getRootNode()),n=0<fa.comparePoints(a.anchorNode,a.anchorOffset,a.focusNode,a.focusOffset),p;n?(g=a.anchorNode,h=a.anchorOffset,e=a.focusNode,f=a.focusOffset):(g=a.focusNode,h=a.focusOffset,e=a.anchorNode,f=a.anchorOffset);for(m.setUnfilteredPosition(g,h);m.previousPosition();){p=m.g [...]
- if(p.nodeType===Node.TEXT_NODE){if(p=p.data[m.unfilteredDomOffset()],!k.test(p))break}else if(!W.isTextSpan(p))break;g=m.container();h=m.unfilteredDomOffset()}m.setUnfilteredPosition(e,f);do if(p=m.getCurrentNode(),p.nodeType===Node.TEXT_NODE){if(p=p.data[m.unfilteredDomOffset()],!k.test(p))break}else if(!W.isTextSpan(p))break;while(m.nextPosition());e=m.container();f=m.unfilteredDomOffset();n?(a.anchorNode=g,a.anchorOffset=h,a.focusNode=e,a.focusOffset=f):(a.focusNode=g,a.focusOffset=h [...]
- e,a.anchorOffset=f)}else 3<=e&&(e=H.getParagraphElement(a.anchorNode),f=H.getParagraphElement(a.focusNode),e&&(a.anchorNode=e,a.anchorOffset=0),f&&(a.focusNode=f,a.focusOffset=f.childNodes.length));f=H.convertDomToCursorRange(a.anchorNode,a.anchorOffset,a.focusNode,a.focusOffset);e=H.getCursorSelection(c);if(f.position!==e.position||f.length!==e.length)e=b(f.position,f.length,ops.OdtCursor.RangeSelection),l.enqueue([e]);X.focus()}}}function d(a){var d=H.getCursorSelection(c),e=H.getCurs [...]
- 0!==a&&(a=0<a?e.convertForwardStepsBetweenFilters(a,na,ta):-e.convertBackwardStepsBetweenFilters(-a,na,ta),a=d.length+a,l.enqueue([b(d.position,a)]))}function k(a){var d=H.getCursorPosition(c),e=H.getCursor(c).getStepCounter();0!==a&&(a=0<a?e.convertForwardStepsBetweenFilters(a,na,ta):-e.convertBackwardStepsBetweenFilters(-a,na,ta),l.enqueue([b(d+a,0)]))}function a(){k(-1);return!0}function e(){k(1);return!0}function h(){d(-1);return!0}function q(){d(1);return!0}function u(a,b){var e=H. [...]
- runtime.assert(Boolean(e),"SessionController: Cursor outside paragraph");e=H.getCursor(c).getStepCounter().countLinesSteps(a,na);b?d(e):k(e)}function x(){u(-1,!1);return!0}function v(){u(1,!1);return!0}function y(){u(-1,!0);return!0}function w(){u(1,!0);return!0}function t(a,b){var e=H.getCursor(c).getStepCounter().countStepsToLineBoundary(a,na);b?d(e):k(e)}function s(){t(-1,!1);return!0}function D(){t(1,!1);return!0}function A(){t(-1,!0);return!0}function B(){t(1,!0);return!0}function [...]
- H.getParagraphElement(H.getCursor(c).getNode()),b,e;runtime.assert(Boolean(a),"SessionController: Cursor outside paragraph");e=H.getDistanceFromCursor(c,a,0);b=gui.SelectionMover.createPositionIterator(H.getRootNode());for(b.setUnfilteredPosition(a,0);0===e&&b.previousPosition();)a=b.getCurrentNode(),W.isParagraph(a)&&(e=H.getDistanceFromCursor(c,a,0));d(e);return!0}function z(){var a=H.getParagraphElement(H.getCursor(c).getNode()),b,e;runtime.assert(Boolean(a),"SessionController: Curso [...]
- b=gui.SelectionMover.createPositionIterator(H.getRootNode());b.moveToEndOfNode(a);for(e=H.getDistanceFromCursor(c,b.container(),b.unfilteredDomOffset());0===e&&b.nextPosition();)a=b.getCurrentNode(),W.isParagraph(a)&&(b.moveToEndOfNode(a),e=H.getDistanceFromCursor(c,b.container(),b.unfilteredDomOffset()));d(e);return!0}function K(a,b){var e=gui.SelectionMover.createPositionIterator(H.getRootNode());0<a&&e.moveToEnd();e=H.getDistanceFromCursor(c,e.container(),e.unfilteredDomOffset());b?d [...]
- !1);return!0}function Q(){K(1,!1);return!0}function $(){K(-1,!0);return!0}function ia(){K(1,!0);return!0}function R(){var a=H.getRootNode(),a=H.convertDomPointToCursorStep(a,a.childNodes.length);l.enqueue([b(0,a)]);return!0}function ma(){var a=H.getCursor(c),b=U.getSelection(),d;a?(ua.clearSelection(),a.getSelectionType()===ops.OdtCursor.RegionSelection&&(d=W.getImageElements(a.getSelectedRange())[0])&&ua.select(d.parentNode),X.hasFocus()&&(d=a.getSelectedRange(),b.extend?a.hasForwardSe [...]
- (b.collapse(d.startContainer,d.startOffset),b.extend(d.endContainer,d.endOffset)):(b.collapse(d.endContainer,d.endOffset),b.extend(d.startContainer,d.startOffset)):(xa=!0,b.removeAllRanges(),b.addRange(d.cloneRange()),H.getOdfCanvas().getElement().setActive(),runtime.setTimeout(function(){xa=!1},0)))):ua.clearSelection()}function ba(){!1===xa&&runtime.setTimeout(ma,0)}function ga(a){var b=H.getCursor(c);b.getSelectedRange().collapsed||(ja.setDataFromRange(a,b.getSelectedRange())?pa.remo [...]
- runtime.log("Cut operation failed"))}function S(){return!1!==H.getCursor(c).getSelectedRange().collapsed}function Y(a){var b=H.getCursor(c);b.getSelectedRange().collapsed||ja.setDataFromRange(a,b.getSelectedRange())||runtime.log("Cut operation failed")}function V(a){var b;U.clipboardData&&U.clipboardData.getData?b=U.clipboardData.getData("Text"):a.clipboardData&&a.clipboardData.getData&&(b=a.clipboardData.getData("text/plain"));b&&(pa.removeCurrentSelection(),l.enqueue(Ba.createPasteOps [...]
- a.preventDefault():a.returnValue=!1)}function G(){return!1}function I(a){if(da)da.onOperationExecuted(a)}function ha(a){H.emit(ops.OdtDocument.signalUndoStackChanged,a)}function N(){return da?(da.moveBackward(1),ma(),!0):!1}function O(){return da?(da.moveForward(1),ma(),!0):!1}function Z(a){if(oa=(a=a.target||a.srcElement)&&fa.containsNode(H.getOdfCanvas().getElement(),a))va=!1,wa=H.createRootFilter(a)}function ka(a){var b=a.getSelectedRange();return a.hasForwardSelection()?{anchorNode: [...]
- anchorOffset:b.startOffset,focusNode:b.endContainer,focusOffset:b.endOffset}:{anchorNode:b.endContainer,anchorOffset:b.endOffset,focusNode:b.startContainer,focusOffset:b.startOffset}}function ca(a){var b=a.target||a.srcElement,c={detail:a.detail,clientX:a.clientX,clientY:a.clientY,target:b};ra.processRequests();W.isImage(b)&&W.isCharacterFrame(b.parentNode)?p(b.parentNode):oa&&!ua.isSelectorElement(b)&&(va?r(ka(m),a):runtime.setTimeout(function(){var a;a=(a=U.getSelection())?{anchorNode [...]
- anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}:null;r(a,c)},0));va=oa=!1}function T(a){ca(a)}function P(a){var b=a.target||a.srcElement,c=null;"annotationRemoveButton"===b.className?(c=fa.getElementsByTagNameNS(b.parentNode,odf.Namespaces.officens,"annotation")[0],qa.removeAnnotation(c)):ca(a)}function L(){var a=U.getSelection(),b;oa&&0<a.rangeCount&&(va=!0,ua.clearSelection(),ya.setUnfilteredPosition(a.focusNode,a.focusOffset),wa.acceptPosition(ya)===g&&(b [...]
- a=a.anchorNode===b.startContainer&&a.anchorOffset===b.startOffset,m.setSelectedRange(b,a),H.emit(ops.OdtDocument.signalCursorMoved,m)))}function ea(a){return function(){a();return!0}}function E(a){return function(b){return H.getCursor(c).getSelectionType()===ops.OdtCursor.RangeSelection?a(b):!0}}var U=runtime.getWindow(),H=l.getOdtDocument(),la=new core.Async,fa=new core.DomUtils,W=new odf.OdfUtils,ja=new gui.Clipboard,C=new gui.KeyboardHandler,sa=new gui.KeyboardHandler,na=new core.Pos [...]
- ta=H.getPositionFilter(),oa=!1,za=new odf.ObjectNameGenerator(H.getOdfCanvas().odfContainer(),c),va=!1,wa=null,da=null,X=new gui.EventManager(H),qa=new gui.AnnotationController(l,c),aa=new gui.DirectTextStyler(l,c),J=f&&f.directParagraphStylingEnabled?new gui.DirectParagraphStyler(l,c,za):null,pa=new gui.TextManipulator(l,c,aa.createCursorStyleOp),Aa=new gui.ImageManager(l,c,za),ua=new gui.ImageSelector(H.getOdfCanvas()),ya=gui.SelectionMover.createPositionIterator(H.getRootNode()),ra,x [...]
- c);runtime.assert(null!==U,"Expected to be run in an environment which has a global window, like a browser.");na.addFilter("BaseFilter",ta);na.addFilter("RootFilter",H.createRootFilter(c));this.selectRange=r;this.moveCursorToLeft=a;this.moveCursorToDocumentBoundary=K;this.extendSelectionToEntireDocument=R;this.startEditing=function(){var a;H.getOdfCanvas().getElement().classList.add("virtualSelections");X.subscribe("keydown",C.handleEvent);X.subscribe("keypress",sa.handleEvent);X.subscr [...]
- n);X.subscribe("beforecut",S);X.subscribe("cut",ga);X.subscribe("copy",Y);X.subscribe("beforepaste",G);X.subscribe("paste",V);X.subscribe("mousedown",Z);X.subscribe("mousemove",ra.trigger);X.subscribe("mouseup",P);X.subscribe("contextmenu",T);X.subscribe("focus",ba);H.subscribe(ops.OdtDocument.signalOperationExecuted,ma);H.subscribe(ops.OdtDocument.signalOperationExecuted,I);a=new ops.OpAddCursor;a.init({memberid:c});l.enqueue([a]);da&&da.saveInitialState()};this.endEditing=function(){v [...]
- a.init({memberid:c});l.enqueue([a]);da&&da.resetInitialState();H.unsubscribe(ops.OdtDocument.signalOperationExecuted,I);H.unsubscribe(ops.OdtDocument.signalOperationExecuted,ma);X.unsubscribe("keydown",C.handleEvent);X.unsubscribe("keypress",sa.handleEvent);X.unsubscribe("keyup",n);X.unsubscribe("cut",ga);X.unsubscribe("beforecut",S);X.unsubscribe("copy",Y);X.unsubscribe("paste",V);X.unsubscribe("beforepaste",G);X.unsubscribe("mousemove",ra.trigger);X.unsubscribe("mousedown",Z);X.unsubs [...]
- P);X.unsubscribe("contextmenu",T);X.unsubscribe("focus",ba);H.getOdfCanvas().getElement().classList.remove("virtualSelections")};this.getInputMemberId=function(){return c};this.getSession=function(){return l};this.setUndoManager=function(a){da&&da.unsubscribe(gui.UndoManager.signalUndoStackChanged,ha);if(da=a)da.setOdtDocument(H),da.setPlaybackFunction(function(a){a.execute(H)}),da.subscribe(gui.UndoManager.signalUndoStackChanged,ha)};this.getUndoManager=function(){return da};this.getAn [...]
- function(){return qa};this.getDirectTextStyler=function(){return aa};this.getDirectParagraphStyler=function(){return J};this.getImageManager=function(){return Aa};this.getTextManipulator=function(){return pa};this.getEventManager=function(){return X};this.getKeyboardHandlers=function(){return{keydown:C,keypress:sa}};this.destroy=function(a){var b=[ra.destroy,aa.destroy];J&&b.push(J.destroy);la.destroyAll(b,a)};(function(){var b=-1!==U.navigator.appVersion.toLowerCase().indexOf("mac"),c= [...]
- d=gui.KeyboardHandler.KeyCode;ra=new core.ScheduledTask(L,0);C.bind(d.Tab,c.None,E(function(){pa.insertText("\t");return!0}));C.bind(d.Left,c.None,E(a));C.bind(d.Right,c.None,E(e));C.bind(d.Up,c.None,E(x));C.bind(d.Down,c.None,E(v));C.bind(d.Backspace,c.None,ea(pa.removeTextByBackspaceKey));C.bind(d.Delete,c.None,pa.removeTextByDeleteKey);C.bind(d.Left,c.Shift,E(h));C.bind(d.Right,c.Shift,E(q));C.bind(d.Up,c.Shift,E(y));C.bind(d.Down,c.Shift,E(w));C.bind(d.Home,c.None,E(s));C.bind(d.End [...]
- C.bind(d.Home,c.Ctrl,E(F));C.bind(d.End,c.Ctrl,E(Q));C.bind(d.Home,c.Shift,E(A));C.bind(d.End,c.Shift,E(B));C.bind(d.Up,c.CtrlShift,E(M));C.bind(d.Down,c.CtrlShift,E(z));C.bind(d.Home,c.CtrlShift,E($));C.bind(d.End,c.CtrlShift,E(ia));b?(C.bind(d.Clear,c.None,pa.removeCurrentSelection),C.bind(d.Left,c.Meta,E(s)),C.bind(d.Right,c.Meta,E(D)),C.bind(d.Home,c.Meta,E(F)),C.bind(d.End,c.Meta,E(Q)),C.bind(d.Left,c.MetaShift,E(A)),C.bind(d.Right,c.MetaShift,E(B)),C.bind(d.Up,c.AltShift,E(M)),C.b [...]
- c.AltShift,E(z)),C.bind(d.Up,c.MetaShift,E($)),C.bind(d.Down,c.MetaShift,E(ia)),C.bind(d.A,c.Meta,E(R)),C.bind(d.B,c.Meta,E(aa.toggleBold)),C.bind(d.I,c.Meta,E(aa.toggleItalic)),C.bind(d.U,c.Meta,E(aa.toggleUnderline)),J&&(C.bind(d.L,c.MetaShift,E(J.alignParagraphLeft)),C.bind(d.E,c.MetaShift,E(J.alignParagraphCenter)),C.bind(d.R,c.MetaShift,E(J.alignParagraphRight)),C.bind(d.J,c.MetaShift,E(J.alignParagraphJustified))),qa&&C.bind(d.C,c.MetaShift,qa.addAnnotation),C.bind(d.Z,c.Meta,N),C [...]
- c.MetaShift,O)):(C.bind(d.A,c.Ctrl,E(R)),C.bind(d.B,c.Ctrl,E(aa.toggleBold)),C.bind(d.I,c.Ctrl,E(aa.toggleItalic)),C.bind(d.U,c.Ctrl,E(aa.toggleUnderline)),J&&(C.bind(d.L,c.CtrlShift,E(J.alignParagraphLeft)),C.bind(d.E,c.CtrlShift,E(J.alignParagraphCenter)),C.bind(d.R,c.CtrlShift,E(J.alignParagraphRight)),C.bind(d.J,c.CtrlShift,E(J.alignParagraphJustified))),qa&&C.bind(d.C,c.CtrlAlt,qa.addAnnotation),C.bind(d.Z,c.Ctrl,N),C.bind(d.Z,c.CtrlShift,O));sa.setDefault(E(function(a){var b;b=nul [...]
- void 0===a.which?String.fromCharCode(a.keyCode):0!==a.which&&0!==a.charCode?String.fromCharCode(a.which):null;return!b||a.altKey||a.ctrlKey||a.metaKey?!1:(pa.insertText(b),!0)}));sa.bind(d.Enter,c.None,E(pa.enqueueParagraphSplittingOps))})()};return gui.SessionController}();
- // Input 88
+/*
+
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2012 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.OperationRouter=function(){};ops.OperationRouter.prototype.setOperationFactory=function(g){};ops.OperationRouter.prototype.setPlaybackFunction=function(g){};ops.OperationRouter.prototype.push=function(g){};ops.OperationRouter.prototype.close=function(g){};
- // Input 89
++ops.TrivialOperationRouter=function(){var g,k;this.setOperationFactory=function(e){g=e};this.setPlaybackFunction=function(e){k=e};this.push=function(e){e.forEach(function(e){e=e.spec();e.timestamp=(new Date).getTime();e=g.create(e);k(e)})};this.close=function(e){e()};this.subscribe=function(e,g){};this.unsubscribe=function(e,g){};this.hasLocalUnsyncedOps=function(){return!1};this.hasSessionHostConnection=function(){return!0}};
++// Input 87
+/*
+
- Copyright (C) 2012 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- ops.TrivialOperationRouter=function(){var g,l;this.setOperationFactory=function(c){g=c};this.setPlaybackFunction=function(c){l=c};this.push=function(c){c.forEach(function(c){c=c.spec();c.timestamp=(new Date).getTime();c=g.create(c);l(c)})};this.close=function(c){c()}};
- // Input 90
- gui.EditInfoHandle=function(g){var l=[],c,m=g.ownerDocument,f=m.documentElement.namespaceURI;this.setEdits=function(g){l=g;var b,p,r,d;c.innerHTML="";for(g=0;g<l.length;g+=1)b=m.createElementNS(f,"div"),b.className="editInfo",p=m.createElementNS(f,"span"),p.className="editInfoColor",p.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",l[g].memberid),r=m.createElementNS(f,"span"),r.className="editInfoAuthor",r.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",l[g [...]
- d=m.createElementNS(f,"span"),d.className="editInfoTime",d.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",l[g].memberid),d.innerHTML=l[g].time,b.appendChild(p),b.appendChild(r),b.appendChild(d),c.appendChild(b)};this.show=function(){c.style.display="block"};this.hide=function(){c.style.display="none"};this.destroy=function(f){g.removeChild(c);f()};c=m.createElementNS(f,"div");c.setAttribute("class","editInfoHandle");c.style.display="none";g.appendChild(c)};
- // Input 91
++runtime.loadClass("ops.EditInfo");runtime.loadClass("gui.EditInfoHandle");
++gui.EditInfoMarker=function(g,k){function e(d,f){return runtime.setTimeout(function(){b.style.opacity=d},f)}var n=this,m,q,b,h,r;this.addEdit=function(d,f){var a=Date.now()-f;g.addEdit(d,f);q.setEdits(g.getSortedEdits());b.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",d);h&&runtime.clearTimeout(h);r&&runtime.clearTimeout(r);1E4>a?(e(1,0),h=e(0.5,1E4-a),r=e(0.2,2E4-a)):1E4<=a&&2E4>a?(e(0.5,0),r=e(0.2,2E4-a)):e(0.2,0)};this.getEdits=function(){return g.getEdits()};this.cl [...]
++q.setEdits([]);b.hasAttributeNS("urn:webodf:names:editinfo","editinfo:memberid")&&b.removeAttributeNS("urn:webodf:names:editinfo","editinfo:memberid")};this.getEditInfo=function(){return g};this.show=function(){b.style.display="block"};this.hide=function(){n.hideHandle();b.style.display="none"};this.showHandle=function(){q.show()};this.hideHandle=function(){q.hide()};this.destroy=function(d){m.removeChild(b);q.destroy(function(b){b?d(b):g.destroy(d)})};(function(){var d=g.getOdtDocument [...]
++b=d.createElementNS(d.documentElement.namespaceURI,"div");b.setAttribute("class","editInfoMarker");b.onmouseover=function(){n.showHandle()};b.onmouseout=function(){n.hideHandle()};m=g.getNode();m.appendChild(b);q=new gui.EditInfoHandle(m);k||n.hide()})()};
++// Input 88
+/*
+
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("ops.EditInfo");runtime.loadClass("gui.EditInfoHandle");
- gui.EditInfoMarker=function(g,l){function c(c,f){return runtime.setTimeout(function(){b.style.opacity=c},f)}var m=this,f,n,b,p,r;this.addEdit=function(d,f){var a=Date.now()-f;g.addEdit(d,f);n.setEdits(g.getSortedEdits());b.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",d);p&&runtime.clearTimeout(p);r&&runtime.clearTimeout(r);1E4>a?(c(1,0),p=c(0.5,1E4-a),r=c(0.2,2E4-a)):1E4<=a&&2E4>a?(c(0.5,0),r=c(0.2,2E4-a)):c(0.2,0)};this.getEdits=function(){return g.getEdits()};this.cl [...]
- n.setEdits([]);b.hasAttributeNS("urn:webodf:names:editinfo","editinfo:memberid")&&b.removeAttributeNS("urn:webodf:names:editinfo","editinfo:memberid")};this.getEditInfo=function(){return g};this.show=function(){b.style.display="block"};this.hide=function(){m.hideHandle();b.style.display="none"};this.showHandle=function(){n.show()};this.hideHandle=function(){n.hide()};this.destroy=function(c){f.removeChild(b);n.destroy(function(b){b?c(b):g.destroy(c)})};(function(){var c=g.getOdtDocument [...]
- b=c.createElementNS(c.documentElement.namespaceURI,"div");b.setAttribute("class","editInfoMarker");b.onmouseover=function(){m.showHandle()};b.onmouseout=function(){m.hideHandle()};f=g.getNode();f.appendChild(b);n=new gui.EditInfoHandle(f);l||m.hide()})()};
- // Input 92
++gui.PlainTextPasteboard=function(g,k){function e(e,g){e.init(g);return e}this.createPasteOps=function(n){var m=g.getCursorPosition(k),q=m,b=[];n.replace(/\r/g,"").split("\n").forEach(function(g){b.push(e(new ops.OpSplitParagraph,{memberid:k,position:q}));q+=1;b.push(e(new ops.OpInsertText,{memberid:k,position:q,text:g}));q+=g.length});b.push(e(new ops.OpRemoveText,{memberid:k,position:m,length:1}));return b}};
++// Input 89
++runtime.loadClass("core.DomUtils");runtime.loadClass("odf.OdfUtils");runtime.loadClass("odf.OdfNodeFilter");runtime.loadClass("gui.SelectionMover");
++gui.SelectionView=function(g){function k(){var a=p.getRootNode();l!==a&&(l=a,u=l.parentNode.parentNode.parentNode,u.appendChild(w),u.appendChild(y),u.appendChild(v))}function e(a,b){a.style.left=b.left+"px";a.style.top=b.top+"px";a.style.width=b.width+"px";a.style.height=b.height+"px"}function n(a){N=a;w.style.display=y.style.display=v.style.display=!0===a?"block":"none"}function m(a){var b=s.getBoundingClientRect(u),c=p.getOdfCanvas().getZoomLevel(),d={};d.top=s.adaptRangeDifferenceToZ [...]
++b.top,c);d.left=s.adaptRangeDifferenceToZoomLevel(a.left-b.left,c);d.bottom=s.adaptRangeDifferenceToZoomLevel(a.bottom-b.top,c);d.right=s.adaptRangeDifferenceToZoomLevel(a.right-b.left,c);d.width=s.adaptRangeDifferenceToZoomLevel(a.width,c);d.height=s.adaptRangeDifferenceToZoomLevel(a.height,c);return d}function q(a){a=a.getBoundingClientRect();return Boolean(a&&0!==a.height)}function b(a){var b=t.getTextElements(a,!0,!1),c=a.cloneRange(),d=a.cloneRange();a=a.cloneRange();if(!b.length)r [...]
++var f;a:{f=0;var e=b[f],g=c.startContainer===e?c.startOffset:0,h=g;c.setStart(e,g);for(c.setEnd(e,h);!q(c);){if(e.nodeType===Node.ELEMENT_NODE&&h<e.childNodes.length)h=e.childNodes.length;else if(e.nodeType===Node.TEXT_NODE&&h<e.length)h+=1;else if(b[f])e=b[f],f+=1,g=h=0;else{f=!1;break a}c.setStart(e,g);c.setEnd(e,h)}f=!0}if(!f)return null;a:{f=b.length-1;e=b[f];h=g=d.endContainer===e?d.endOffset:e.length||e.childNodes.length;d.setStart(e,g);for(d.setEnd(e,h);!q(d);){if(e.nodeType===No [...]
++0<g)g=0;else if(e.nodeType===Node.TEXT_NODE&&0<g)g-=1;else if(b[f])e=b[f],f-=1,g=h=e.length||e.childNodes.length;else{b=!1;break a}d.setStart(e,g);d.setEnd(e,h)}b=!0}if(!b)return null;a.setStart(c.startContainer,c.startOffset);a.setEnd(d.endContainer,d.endOffset);return{firstRange:c,lastRange:d,fillerRange:a}}function h(a,b){var c={};c.top=Math.min(a.top,b.top);c.left=Math.min(a.left,b.left);c.right=Math.max(a.right,b.right);c.bottom=Math.max(a.bottom,b.bottom);c.width=c.right-c.left;c. [...]
++c.top;return c}function r(a,b){b&&0<b.width&&0<b.height&&(a=a?h(a,b):b);return a}function d(a){function b(a){z.setUnfilteredPosition(a,0);return w.acceptNode(a)===x&&u.acceptPosition(z)===x?x:R}function c(a){var d=null;b(a)===x&&(d=s.getBoundingClientRect(a));return d}var d=a.commonAncestorContainer,f=a.startContainer,e=a.endContainer,g=a.startOffset,h=a.endOffset,k,l,m=null,n,q=B.createRange(),u,w=new odf.OdfNodeFilter,v;if(f===d||e===d)return q=a.cloneRange(),m=q.getBoundingClientRect [...]
++m;for(a=f;a.parentNode!==d;)a=a.parentNode;for(l=e;l.parentNode!==d;)l=l.parentNode;u=p.createRootFilter(f);for(d=a.nextSibling;d&&d!==l;)n=c(d),m=r(m,n),d=d.nextSibling;if(t.isParagraph(a))m=r(m,s.getBoundingClientRect(a));else if(a.nodeType===Node.TEXT_NODE)d=a,q.setStart(d,g),q.setEnd(d,d===l?h:d.length),n=q.getBoundingClientRect(),m=r(m,n);else for(v=B.createTreeWalker(a,NodeFilter.SHOW_TEXT,b,!1),d=v.currentNode=f;d&&d!==e;)q.setStart(d,g),q.setEnd(d,d.length),n=q.getBoundingClient [...]
++n),k=d,g=0,d=v.nextNode();k||(k=f);if(t.isParagraph(l))m=r(m,s.getBoundingClientRect(l));else if(l.nodeType===Node.TEXT_NODE)d=l,q.setStart(d,d===a?g:0),q.setEnd(d,h),n=q.getBoundingClientRect(),m=r(m,n);else for(v=B.createTreeWalker(l,NodeFilter.SHOW_TEXT,b,!1),d=v.currentNode=e;d&&d!==k;)if(q.setStart(d,0),q.setEnd(d,h),n=q.getBoundingClientRect(),m=r(m,n),d=v.previousNode())h=d.length;return m}function f(a,b){var c=a.getBoundingClientRect(),d={width:0};d.top=c.top;d.bottom=c.bottom;d [...]
++d.left=d.right=b?c.right:c.left;return d}function a(){k();if(g.getSelectionType()===ops.OdtCursor.RangeSelection){n(!0);var a=g.getSelectedRange(),c=b(a),l,p,q,r;a.collapsed||!c?n(!1):(n(!0),a=c.firstRange,l=c.lastRange,c=c.fillerRange,p=m(f(a,!1)),r=m(f(l,!0)),q=(q=d(c))?m(q):h(p,r),e(w,{left:p.left,top:p.top,width:Math.max(0,q.width-(p.left-q.left)),height:p.height}),r.top===p.top||r.bottom===p.bottom?y.style.display=v.style.display="none":(e(v,{left:q.left,top:r.top,width:Math.max(0, [...]
++height:r.height}),e(y,{left:q.left,top:p.top+p.height,width:Math.max(0,parseFloat(w.style.left)+parseFloat(w.style.width)-parseFloat(v.style.left)),height:Math.max(0,r.top-p.bottom)})),a.detach(),l.detach(),c.detach())}else n(!1)}function c(b){b===g&&a()}var p=g.getOdtDocument(),l,u,B=p.getDOM(),w=B.createElement("div"),y=B.createElement("div"),v=B.createElement("div"),t=new odf.OdfUtils,s=new core.DomUtils,N=!0,z=gui.SelectionMover.createPositionIterator(p.getRootNode()),x=NodeFilter.F [...]
++R=NodeFilter.FILTER_REJECT;this.show=this.rerender=a;this.hide=function(){n(!1)};this.visible=function(){return N};this.destroy=function(a){u.removeChild(w);u.removeChild(y);u.removeChild(v);g.getOdtDocument().unsubscribe(ops.OdtDocument.signalCursorMoved,c);a()};(function(){var a=g.getMemberId();k();w.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",a);y.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",a);v.setAttributeNS("urn:webodf:names:editinfo","editinf [...]
++a);w.className=y.className=v.className="selectionOverlay";g.getOdtDocument().subscribe(ops.OdtDocument.signalCursorMoved,c)})()};
++// Input 90
+/*
+
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("gui.Caret");runtime.loadClass("ops.EditInfo");runtime.loadClass("gui.EditInfoMarker");gui.SessionViewOptions=function(){this.caretBlinksOnRangeSelect=this.caretAvatarsInitiallyVisible=this.editInfoMarkersInitiallyVisible=!0};
- gui.SessionView=function(){return function(g,l,c,m,f){function n(a,b,c){function d(b,c,e){c=b+'[editinfo|memberid="'+a+'"]'+e+c;a:{var f=u.firstChild;for(b=b+'[editinfo|memberid="'+a+'"]'+e+"{";f;){if(f.nodeType===Node.TEXT_NODE&&0===f.data.indexOf(b)){b=f;break a}f=f.nextSibling}b=null}b?b.data=c:u.appendChild(document.createTextNode(c))}d("div.editInfoMarker","{ background-color: "+c+"; }","");d("span.editInfoColor","{ background-color: "+c+"; }","");d("span.editInfoAuthor",'{ content [...]
- ":before");d("dc|creator","{ background-color: "+c+"; }","");d("div.selectionOverlay","{ background-color: "+c+";}","")}function b(a){var b,c;for(c in v)v.hasOwnProperty(c)&&(b=v[c],a?b.show():b.hide())}function p(a){m.getCarets().forEach(function(b){a?b.showHandle():b.hideHandle()})}function r(a){var b=a.getMemberId();a=a.getProperties();n(b,a.fullName,a.color);l===b&&n("","",a.color)}function d(a){var b=a.getMemberId(),d=c.getOdtDocument().getMember(b).getProperties();m.registerCursor [...]
- !0);if(a=m.getCaret(b))a.setAvatarImageUrl(d.imageUrl),a.setColor(d.color);runtime.log("+++ View here +++ eagerly created an Caret for '"+b+"'! +++")}function k(a){a=a.getMemberId();var b=f.getSelectionView(l),c=f.getSelectionView(gui.ShadowCursor.ShadowCursorMemberId),d=m.getCaret(l);a===l?(c.hide(),b.show(),d&&d.show()):a===gui.ShadowCursor.ShadowCursorMemberId&&(c.show(),b.hide(),d&&d.hide())}function a(a){f.removeSelectionView(a)}function e(a){var b=a.paragraphElement,d=a.memberId;a [...]
- var e,f="",g=b.getElementsByTagNameNS(x,"editinfo")[0];g?(f=g.getAttributeNS(x,"id"),e=v[f]):(f=Math.random().toString(),e=new ops.EditInfo(b,c.getOdtDocument()),e=new gui.EditInfoMarker(e,y),g=b.getElementsByTagNameNS(x,"editinfo")[0],g.setAttributeNS(x,"id",f),v[f]=e);e.addEdit(d,new Date(a))}function h(){D=!0}function q(){s=runtime.getWindow().setInterval(function(){D&&(f.rerenderSelectionViews(),D=!1)},200)}var u,x="urn:webodf:names:editinfo",v={},y=void 0!==g.editInfoMarkersInitial [...]
- Boolean(g.editInfoMarkersInitiallyVisible):!0,w=void 0!==g.caretAvatarsInitiallyVisible?Boolean(g.caretAvatarsInitiallyVisible):!0,t=void 0!==g.caretBlinksOnRangeSelect?Boolean(g.caretBlinksOnRangeSelect):!0,s,D=!1;this.showEditInfoMarkers=function(){y||(y=!0,b(y))};this.hideEditInfoMarkers=function(){y&&(y=!1,b(y))};this.showCaretAvatars=function(){w||(w=!0,p(w))};this.hideCaretAvatars=function(){w&&(w=!1,p(w))};this.getSession=function(){return c};this.getCaret=function(a){return m.ge [...]
- this.destroy=function(b){var f=c.getOdtDocument(),g=Object.keys(v).map(function(a){return v[a]});f.unsubscribe(ops.OdtDocument.signalMemberAdded,r);f.unsubscribe(ops.OdtDocument.signalMemberUpdated,r);f.unsubscribe(ops.OdtDocument.signalCursorAdded,d);f.unsubscribe(ops.OdtDocument.signalCursorRemoved,a);f.unsubscribe(ops.OdtDocument.signalParagraphChanged,e);f.unsubscribe(ops.OdtDocument.signalCursorMoved,k);f.unsubscribe(ops.OdtDocument.signalParagraphChanged,h);f.unsubscribe(ops.OdtDo [...]
- h);f.unsubscribe(ops.OdtDocument.signalParagraphStyleModified,h);runtime.getWindow().clearInterval(s);u.parentNode.removeChild(u);(function K(a,c){c?b(c):a<g.length?g[a].destroy(function(b){K(a+1,b)}):b()})(0,void 0)};(function(){var b=c.getOdtDocument(),f=document.getElementsByTagName("head")[0];b.subscribe(ops.OdtDocument.signalMemberAdded,r);b.subscribe(ops.OdtDocument.signalMemberUpdated,r);b.subscribe(ops.OdtDocument.signalCursorAdded,d);b.subscribe(ops.OdtDocument.signalCursorRemo [...]
- e);b.subscribe(ops.OdtDocument.signalCursorMoved,k);q();b.subscribe(ops.OdtDocument.signalParagraphChanged,h);b.subscribe(ops.OdtDocument.signalTableAdded,h);b.subscribe(ops.OdtDocument.signalParagraphStyleModified,h);u=document.createElementNS(f.namespaceURI,"style");u.type="text/css";u.media="screen, print, handheld, projection";u.appendChild(document.createTextNode("@namespace editinfo url(urn:webodf:names:editinfo);"));u.appendChild(document.createTextNode("@namespace dc url(http:// [...]
- f.appendChild(u)})()}}();
- // Input 93
++runtime.loadClass("gui.SelectionView");
++gui.SelectionViewManager=function(){function g(){return Object.keys(k).map(function(e){return k[e]})}var k={};this.getSelectionView=function(e){return k.hasOwnProperty(e)?k[e]:null};this.getSelectionViews=g;this.removeSelectionView=function(e){k.hasOwnProperty(e)&&(k[e].destroy(function(){}),delete k[e])};this.hideSelectionView=function(e){k.hasOwnProperty(e)&&k[e].hide()};this.showSelectionView=function(e){k.hasOwnProperty(e)&&k[e].show()};this.rerenderSelectionViews=function(){Object. [...]
++k[e].rerender()})};this.registerCursor=function(e,g){var m=e.getMemberId(),q=new gui.SelectionView(e);g?q.show():q.hide();return k[m]=q};this.destroy=function(e){var k=g();(function q(b,g){g?e(g):b<k.length?k[b].destroy(function(e){q(b+1,e)}):e()})(0,void 0)}};
++// Input 91
+/*
+
- Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("gui.Caret");
- gui.CaretManager=function(g){function l(a){return e.hasOwnProperty(a)?e[a]:null}function c(){return Object.keys(e).map(function(a){return e[a]})}function m(a){a===g.getInputMemberId()&&g.getSession().getOdtDocument().getOdfCanvas().getElement().removeAttribute("tabindex");delete e[a]}function f(a){a=a.getMemberId();a===g.getInputMemberId()&&(a=l(a))&&a.refreshCursorBlinking()}function n(){var a=l(g.getInputMemberId());q=!1;a&&a.ensureVisible()}function b(){var a=l(g.getInputMemberId()); [...]
- q||(q=!0,runtime.setTimeout(n,50)))}function p(a){a.memberId===g.getInputMemberId()&&b()}function r(){var a=l(g.getInputMemberId());a&&a.setFocus()}function d(){var a=l(g.getInputMemberId());a&&a.removeFocus()}function k(){var a=l(g.getInputMemberId());a&&a.show()}function a(){var a=l(g.getInputMemberId());a&&a.hide()}var e={},h=runtime.getWindow(),q=!1;this.registerCursor=function(a,c,d){var f=a.getMemberId();c=new gui.Caret(a,c,d);e[f]=c;f===g.getInputMemberId()?(runtime.log("Starting [...]
- f),a.handleUpdate=b,g.getSession().getOdtDocument().getOdfCanvas().getElement().setAttribute("tabindex",-1),g.getEventManager().focus()):a.handleUpdate=c.handleUpdate;return c};this.getCaret=l;this.getCarets=c;this.destroy=function(b){var l=g.getSession().getOdtDocument(),n=g.getEventManager(),q=c();l.unsubscribe(ops.OdtDocument.signalParagraphChanged,p);l.unsubscribe(ops.OdtDocument.signalCursorMoved,f);l.unsubscribe(ops.OdtDocument.signalCursorRemoved,m);n.unsubscribe("focus",r);n.uns [...]
- d);h.removeEventListener("focus",k,!1);h.removeEventListener("blur",a,!1);(function t(a,c){c?b(c):a<q.length?q[a].destroy(function(b){t(a+1,b)}):b()})(0,void 0);e={}};(function(){var b=g.getSession().getOdtDocument(),c=g.getEventManager();b.subscribe(ops.OdtDocument.signalParagraphChanged,p);b.subscribe(ops.OdtDocument.signalCursorMoved,f);b.subscribe(ops.OdtDocument.signalCursorRemoved,m);c.subscribe("focus",r);c.subscribe("blur",d);h.addEventListener("focus",k,!1);h.addEventListener(" [...]
- // Input 94
++runtime.loadClass("core.DomUtils");runtime.loadClass("gui.UndoManager");runtime.loadClass("gui.UndoStateRules");
++gui.TrivialUndoManager=function(g){function k(){u.emit(gui.UndoManager.signalUndoStackChanged,{undoAvailable:b.hasUndoStates(),redoAvailable:b.hasRedoStates()})}function e(){c!==d&&c!==p[p.length-1]&&p.push(c)}function n(a){var b=a.previousSibling||a.nextSibling;a.parentNode.removeChild(a);h.normalizeTextNodes(b)}function m(a){return Object.keys(a).map(function(b){return a[b]})}function q(b){function c(a){var b=a.spec();if(e[b.memberid])switch(b.optype){case "AddCursor":d[b.memberid]||( [...]
++a,delete e[b.memberid],g-=1);break;case "MoveCursor":f[b.memberid]||(f[b.memberid]=a)}}var d={},f={},e={},g,h=b.pop();a.getCursors().forEach(function(a){e[a.getMemberId()]=!0});for(g=Object.keys(e).length;h&&0<g;)h.reverse(),h.forEach(c),h=b.pop();return m(d).concat(m(f))}var b=this,h=new core.DomUtils,r,d=[],f,a,c=[],p=[],l=[],u=new core.EventNotifier([gui.UndoManager.signalUndoStackChanged,gui.UndoManager.signalUndoStateCreated,gui.UndoManager.signalUndoStateModified,gui.TrivialUndoMa [...]
++B=g||new gui.UndoStateRules;this.subscribe=function(a,b){u.subscribe(a,b)};this.unsubscribe=function(a,b){u.unsubscribe(a,b)};this.hasUndoStates=function(){return 0<p.length};this.hasRedoStates=function(){return 0<l.length};this.setOdtDocument=function(b){a=b};this.resetInitialState=function(){p.length=0;l.length=0;d.length=0;c.length=0;r=null;k()};this.saveInitialState=function(){var b=a.getOdfCanvas().odfContainer(),f=a.getOdfCanvas().getAnnotationViewManager();f&&f.forgetAnnotations( [...]
++a.getOdfCanvas().refreshAnnotations();b=r;h.getElementsByTagNameNS(b,"urn:webodf:names:cursor","cursor").forEach(n);h.getElementsByTagNameNS(b,"urn:webodf:names:cursor","anchor").forEach(n);e();p.unshift(d);c=d=q(p);p.length=0;l.length=0;k()};this.setPlaybackFunction=function(a){f=a};this.onOperationExecuted=function(a){l.length=0;B.isEditOperation(a)&&c===d||!B.isPartOfOperationSet(a,c)?(e(),c=[a],p.push(c),u.emit(gui.UndoManager.signalUndoStateCreated,{operations:c}),k()):(c.push(a),u [...]
++{operations:c}))};this.moveForward=function(a){for(var b=0,d;a&&l.length;)d=l.pop(),p.push(d),d.forEach(f),a-=1,b+=1;b&&(c=p[p.length-1],k());return b};this.moveBackward=function(b){for(var e=a.getOdfCanvas(),g=e.odfContainer(),h=0;b&&p.length;)l.push(p.pop()),b-=1,h+=1;h&&(g.setRootElement(r.cloneNode(!0)),e.setOdfContainer(g,!0),u.emit(gui.TrivialUndoManager.signalDocumentRootReplaced,{}),a.getCursors().forEach(function(b){a.removeCursor(b.getMemberId())}),d.forEach(f),p.forEach(funct [...]
++e.refreshCSS(),c=p[p.length-1]||d,k());return h}};gui.TrivialUndoManager.signalDocumentRootReplaced="documentRootReplaced";(function(){return gui.TrivialUndoManager})();
++// Input 92
+/*
+
- Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- gui.UndoManager=function(){};gui.UndoManager.prototype.subscribe=function(g,l){};gui.UndoManager.prototype.unsubscribe=function(g,l){};gui.UndoManager.prototype.setOdtDocument=function(g){};gui.UndoManager.prototype.saveInitialState=function(){};gui.UndoManager.prototype.resetInitialState=function(){};gui.UndoManager.prototype.setPlaybackFunction=function(g){};gui.UndoManager.prototype.hasUndoStates=function(){};gui.UndoManager.prototype.hasRedoStates=function(){};
- gui.UndoManager.prototype.moveForward=function(g){};gui.UndoManager.prototype.moveBackward=function(g){};gui.UndoManager.prototype.onOperationExecuted=function(g){};gui.UndoManager.signalUndoStackChanged="undoStackChanged";gui.UndoManager.signalUndoStateCreated="undoStateCreated";gui.UndoManager.signalUndoStateModified="undoStateModified";(function(){return gui.UndoManager})();
- // Input 95
++runtime.loadClass("ops.TrivialOperationRouter");runtime.loadClass("ops.OperationFactory");runtime.loadClass("ops.OdtDocument");
++ops.Session=function(g){var k=new ops.OperationFactory,e=new ops.OdtDocument(g),n=null;this.setOperationFactory=function(e){k=e;n&&n.setOperationFactory(k)};this.setOperationRouter=function(g){n=g;g.setPlaybackFunction(function(g){return g.execute(e)?(e.emit(ops.OdtDocument.signalOperationExecuted,g),!0):!1});g.setOperationFactory(k)};this.getOperationFactory=function(){return k};this.getOdtDocument=function(){return e};this.enqueue=function(e){n.push(e)};this.close=function(g){n.close( [...]
++g(k):e.close(g)})};this.destroy=function(g){e.destroy(g)};this.setOperationRouter(new ops.TrivialOperationRouter)};
++// Input 93
++/*
++
++ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
++
++ @licstart
++ This file is part of WebODF.
++
++ WebODF is free software: you can redistribute it and/or modify it
++ under the terms of the GNU Affero General Public License (GNU AGPL)
++ as published by the Free Software Foundation, either version 3 of
++ the License, or (at your option) any later version.
++
++ WebODF is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU Affero General Public License for more details.
++
++ You should have received a copy of the GNU Affero General Public License
++ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
++ @licend
++
++ @source: http://www.webodf.org/
++ @source: https://github.com/kogmbh/WebODF/
++*/
++runtime.loadClass("core.EventNotifier");runtime.loadClass("core.PositionFilter");runtime.loadClass("ops.Session");runtime.loadClass("ops.OpAddAnnotation");runtime.loadClass("ops.OpRemoveAnnotation");runtime.loadClass("gui.SelectionMover");
++gui.AnnotationController=function(g,k){function e(){var f=b.getCursor(k),f=f&&f.getNode(),a=!1;if(f){a:{for(a=b.getRootNode();f&&f!==a;){if(f.namespaceURI===d&&"annotation"===f.localName){f=!0;break a}f=f.parentNode}f=!1}a=!f}a!==h&&(h=a,r.emit(gui.AnnotationController.annotatableChanged,h))}function n(b){b.getMemberId()===k&&e()}function m(b){b===k&&e()}function q(b){b.getMemberId()===k&&e()}var b=g.getOdtDocument(),h=!1,r=new core.EventNotifier([gui.AnnotationController.annotatableCha [...]
++this.isAnnotatable=function(){return h};this.addAnnotation=function(){var d=new ops.OpAddAnnotation,a=b.getCursorSelection(k),c=a.length,a=a.position;h&&(a=0<=c?a:a+c,c=Math.abs(c),d.init({memberid:k,position:a,length:c,name:k+Date.now()}),g.enqueue([d]))};this.removeAnnotation=function(d){var a,c;a=b.convertDomPointToCursorStep(d,0)+1;c=b.convertDomPointToCursorStep(d,d.childNodes.length);d=new ops.OpRemoveAnnotation;d.init({memberid:k,position:a,length:c-a});c=new ops.OpMoveCursor;c.i [...]
++position:0<a?a-1:a,length:0});g.enqueue([d,c])};this.subscribe=function(b,a){r.subscribe(b,a)};this.unsubscribe=function(b,a){r.unsubscribe(b,a)};this.destroy=function(d){b.unsubscribe(ops.OdtDocument.signalCursorAdded,n);b.unsubscribe(ops.OdtDocument.signalCursorRemoved,m);b.unsubscribe(ops.OdtDocument.signalCursorMoved,q);d()};b.subscribe(ops.OdtDocument.signalCursorAdded,n);b.subscribe(ops.OdtDocument.signalCursorRemoved,m);b.subscribe(ops.OdtDocument.signalCursorMoved,q);e()};
++gui.AnnotationController.annotatableChanged="annotatable/changed";(function(){return gui.AnnotationController})();
++// Input 94
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- gui.UndoStateRules=function(){function g(c){return c.spec().optype}function l(c){return c.isEdit}this.getOpType=g;this.isEditOperation=l;this.isPartOfOperationSet=function(c,m){if(c.isEdit){if(0===m.length)return!0;var f;if(f=m[m.length-1].isEdit)a:{f=m.filter(l);var n=g(c),b;b:switch(n){case "RemoveText":case "InsertText":b=!0;break b;default:b=!1}if(b&&n===g(f[0])){if(1===f.length){f=!0;break a}n=f[f.length-2].spec().position;f=f[f.length-1].spec().position;b=c.spec().position;if(f=== [...]
- !0;break a}}f=!1}return f}return!0}};
- // Input 96
++runtime.loadClass("core.EventNotifier");runtime.loadClass("core.Utils");runtime.loadClass("odf.OdfUtils");runtime.loadClass("ops.OpAddStyle");runtime.loadClass("ops.OpSetParagraphStyle");runtime.loadClass("gui.StyleHelper");
++gui.DirectParagraphStyler=function(g,k,e){function n(){function a(b,d,e){b!==d&&(void 0===c&&(c={}),c[e]=d);return d}var b=l.getCursor(k),b=b&&b.getSelectedRange(),c;v=a(v,b?w.isAlignedLeft(b):!1,"isAlignedLeft");t=a(t,b?w.isAlignedCenter(b):!1,"isAlignedCenter");s=a(s,b?w.isAlignedRight(b):!1,"isAlignedRight");N=a(N,b?w.isAlignedJustified(b):!1,"isAlignedJustified");c&&y.emit(gui.DirectParagraphStyler.paragraphStylingChanged,c)}function m(a){a.getMemberId()===k&&n()}function q(a){a===k [...]
++k&&n()}function h(){n()}function r(a){var b=l.getCursor(k);b&&l.getParagraphElement(b.getNode())===a.paragraphElement&&n()}function d(a){return a===ops.StepsTranslator.NEXT_STEP}function f(a){var b=l.getCursor(k).getSelectedRange(),b=B.getParagraphElements(b),c=l.getFormatting();b.forEach(function(b){var f=l.convertDomPointToCursorStep(b,0,d),h=b.getAttributeNS(odf.Namespaces.textns,"style-name");b=e.generateStyleName();var m;h&&(m=c.createDerivedStyleObject(h,"paragraph",{}));m=a(m||{} [...]
++h.init({memberid:k,styleName:b,styleFamily:"paragraph",isAutomaticStyle:!0,setProperties:m});m=new ops.OpSetParagraphStyle;m.init({memberid:k,styleName:b,position:f});g.enqueue([h,m])})}function a(a){f(function(b){return u.mergeObjects(b,a)})}function c(b){a({"style:paragraph-properties":{"fo:text-align":b}})}function p(a,b){var c=l.getFormatting().getDefaultTabStopDistance(),d=b["style:paragraph-properties"],d=(d=d&&d["fo:margin-left"])&&B.parseLength(d);return u.mergeObjects(b,{"style [...]
++d.unit===c.unit?d.value+a*c.value+d.unit:a*c.value+c.unit}})}var l=g.getOdtDocument(),u=new core.Utils,B=new odf.OdfUtils,w=new gui.StyleHelper(l.getFormatting()),y=new core.EventNotifier([gui.DirectParagraphStyler.paragraphStylingChanged]),v,t,s,N;this.isAlignedLeft=function(){return v};this.isAlignedCenter=function(){return t};this.isAlignedRight=function(){return s};this.isAlignedJustified=function(){return N};this.alignParagraphLeft=function(){c("left");return!0};this.alignParagraph [...]
++return!0};this.alignParagraphRight=function(){c("right");return!0};this.alignParagraphJustified=function(){c("justify");return!0};this.indent=function(){f(p.bind(null,1));return!0};this.outdent=function(){f(p.bind(null,-1));return!0};this.subscribe=function(a,b){y.subscribe(a,b)};this.unsubscribe=function(a,b){y.unsubscribe(a,b)};this.destroy=function(a){l.unsubscribe(ops.OdtDocument.signalCursorAdded,m);l.unsubscribe(ops.OdtDocument.signalCursorRemoved,q);l.unsubscribe(ops.OdtDocument. [...]
++b);l.unsubscribe(ops.OdtDocument.signalParagraphStyleModified,h);l.unsubscribe(ops.OdtDocument.signalParagraphChanged,r);a()};l.subscribe(ops.OdtDocument.signalCursorAdded,m);l.subscribe(ops.OdtDocument.signalCursorRemoved,q);l.subscribe(ops.OdtDocument.signalCursorMoved,b);l.subscribe(ops.OdtDocument.signalParagraphStyleModified,h);l.subscribe(ops.OdtDocument.signalParagraphChanged,r);n()};gui.DirectParagraphStyler.paragraphStylingChanged="paragraphStyling/changed";(function(){return g [...]
++// Input 95
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.DomUtils");runtime.loadClass("gui.UndoManager");runtime.loadClass("gui.UndoStateRules");
- gui.TrivialUndoManager=function(g){function l(){u.emit(gui.UndoManager.signalUndoStackChanged,{undoAvailable:b.hasUndoStates(),redoAvailable:b.hasRedoStates()})}function c(){e!==d&&e!==h[h.length-1]&&h.push(e)}function m(a){var b=a.previousSibling||a.nextSibling;a.parentNode.removeChild(a);p.normalizeTextNodes(b)}function f(a){return Object.keys(a).map(function(b){return a[b]})}function n(b){function c(a){var b=a.spec();if(g[b.memberid])switch(b.optype){case "AddCursor":d[b.memberid]||( [...]
- a,delete g[b.memberid],h-=1);break;case "MoveCursor":e[b.memberid]||(e[b.memberid]=a)}}var d={},e={},g={},h,k=b.pop();a.getCursors().forEach(function(a){g[a.getMemberId()]=!0});for(h=Object.keys(g).length;k&&0<h;)k.reverse(),k.forEach(c),k=b.pop();return f(d).concat(f(e))}var b=this,p=new core.DomUtils,r,d=[],k,a,e=[],h=[],q=[],u=new core.EventNotifier([gui.UndoManager.signalUndoStackChanged,gui.UndoManager.signalUndoStateCreated,gui.UndoManager.signalUndoStateModified,gui.TrivialUndoMa [...]
- x=g||new gui.UndoStateRules;this.subscribe=function(a,b){u.subscribe(a,b)};this.unsubscribe=function(a,b){u.unsubscribe(a,b)};this.hasUndoStates=function(){return 0<h.length};this.hasRedoStates=function(){return 0<q.length};this.setOdtDocument=function(b){a=b};this.resetInitialState=function(){h.length=0;q.length=0;d.length=0;e.length=0;r=null;l()};this.saveInitialState=function(){var b=a.getOdfCanvas().odfContainer(),f=a.getOdfCanvas().getAnnotationViewManager();f&&f.forgetAnnotations( [...]
- a.getOdfCanvas().refreshAnnotations();b=r;p.getElementsByTagNameNS(b,"urn:webodf:names:cursor","cursor").forEach(m);p.getElementsByTagNameNS(b,"urn:webodf:names:cursor","anchor").forEach(m);c();h.unshift(d);e=d=n(h);h.length=0;q.length=0;l()};this.setPlaybackFunction=function(a){k=a};this.onOperationExecuted=function(a){q.length=0;x.isEditOperation(a)&&e===d||!x.isPartOfOperationSet(a,e)?(c(),e=[a],h.push(e),u.emit(gui.UndoManager.signalUndoStateCreated,{operations:e}),l()):(e.push(a),u [...]
- {operations:e}))};this.moveForward=function(a){for(var b=0,c;a&&q.length;)c=q.pop(),h.push(c),c.forEach(k),a-=1,b+=1;b&&(e=h[h.length-1],l());return b};this.moveBackward=function(b){for(var c=a.getOdfCanvas(),f=c.odfContainer(),g=0;b&&h.length;)q.push(h.pop()),b-=1,g+=1;g&&(f.setRootElement(r.cloneNode(!0)),c.setOdfContainer(f,!0),u.emit(gui.TrivialUndoManager.signalDocumentRootReplaced,{}),a.getCursors().forEach(function(b){a.removeCursor(b.getMemberId())}),d.forEach(k),h.forEach(funct [...]
- c.refreshCSS(),e=h[h.length-1]||d,l());return g}};gui.TrivialUndoManager.signalDocumentRootReplaced="documentRootReplaced";(function(){return gui.TrivialUndoManager})();
++runtime.loadClass("core.EventNotifier");runtime.loadClass("core.Utils");runtime.loadClass("ops.OpApplyDirectStyling");runtime.loadClass("gui.StyleHelper");
++gui.DirectTextStyler=function(g,k){function e(a,b){for(var c=0,d=b[c];d&&a;)a=a[d],c+=1,d=b[c];return b.length===c?a:void 0}function n(a,b){var c=e(a[0],b);return a.every(function(a){return c===e(a,b)})?c:void 0}function m(){var a=t.getCursor(k),a=(a=a&&a.getSelectedRange())&&s.getAppliedStyles(a)||[];a[0]&&z&&(a[0]=v.mergeObjects(a[0],z));return a}function q(){function a(b,d,e){b!==d&&(void 0===c&&(c={}),c[e]=d);return d}var b,c;x=m();R=a(R,x?s.isBold(x):!1,"isBold");F=a(F,x?s.isItalic [...]
++U=a(U,x?s.hasUnderline(x):!1,"hasUnderline");P=a(P,x?s.hasStrikeThrough(x):!1,"hasStrikeThrough");b=x&&n(x,["style:text-properties","fo:font-size"]);A=a(A,b&&parseFloat(b),"fontSize");ja=a(ja,x&&n(x,["style:text-properties","style:font-name"]),"fontName");c&&N.emit(gui.DirectTextStyler.textStylingChanged,c)}function b(a){a.getMemberId()===k&&q()}function h(a){a===k&&q()}function r(a){a.getMemberId()===k&&q()}function d(){q()}function f(a){var b=t.getCursor(k);b&&t.getParagraphElement(b. [...]
++a.paragraphElement&&q()}function a(a,b){var c=t.getCursor(k);if(!c)return!1;c=s.getAppliedStyles(c.getSelectedRange());b(!a(c));return!0}function c(a){var b=t.getCursorSelection(k),c={"style:text-properties":a};0!==b.length?(a=new ops.OpApplyDirectStyling,a.init({memberid:k,position:b.position,length:b.length,setProperties:c}),g.enqueue([a])):(z=v.mergeObjects(z||{},c),q())}function p(a,b){var d={};d[a]=b;c(d)}function l(a){a=a.spec();z&&a.memberid===k&&"SplitParagraph"!==a.optype&&(z=n [...]
++a?"bold":"normal")}function B(a){p("fo:font-style",a?"italic":"normal")}function w(a){p("style:text-underline-style",a?"solid":"none")}function y(a){p("style:text-line-through-style",a?"solid":"none")}var v=new core.Utils,t=g.getOdtDocument(),s=new gui.StyleHelper(t.getFormatting()),N=new core.EventNotifier([gui.DirectTextStyler.textStylingChanged]),z,x=[],R=!1,F=!1,U=!1,P=!1,A,ja;this.formatTextSelection=c;this.createCursorStyleOp=function(a,b){var c=null;z&&(c=new ops.OpApplyDirectSty [...]
++position:a,length:b,setProperties:z}),z=null,q());return c};this.setBold=u;this.setItalic=B;this.setHasUnderline=w;this.setHasStrikethrough=y;this.setFontSize=function(a){p("fo:font-size",a+"pt")};this.setFontName=function(a){p("style:font-name",a)};this.getAppliedStyles=function(){return x};this.toggleBold=a.bind(this,s.isBold,u);this.toggleItalic=a.bind(this,s.isItalic,B);this.toggleUnderline=a.bind(this,s.hasUnderline,w);this.toggleStrikethrough=a.bind(this,s.hasStrikeThrough,y);this [...]
++this.isItalic=function(){return F};this.hasUnderline=function(){return U};this.hasStrikeThrough=function(){return P};this.fontSize=function(){return A};this.fontName=function(){return ja};this.subscribe=function(a,b){N.subscribe(a,b)};this.unsubscribe=function(a,b){N.unsubscribe(a,b)};this.destroy=function(a){t.unsubscribe(ops.OdtDocument.signalCursorAdded,b);t.unsubscribe(ops.OdtDocument.signalCursorRemoved,h);t.unsubscribe(ops.OdtDocument.signalCursorMoved,r);t.unsubscribe(ops.OdtDocu [...]
++d);t.unsubscribe(ops.OdtDocument.signalParagraphChanged,f);t.unsubscribe(ops.OdtDocument.signalOperationExecuted,l);a()};t.subscribe(ops.OdtDocument.signalCursorAdded,b);t.subscribe(ops.OdtDocument.signalCursorRemoved,h);t.subscribe(ops.OdtDocument.signalCursorMoved,r);t.subscribe(ops.OdtDocument.signalParagraphStyleModified,d);t.subscribe(ops.OdtDocument.signalParagraphChanged,f);t.subscribe(ops.OdtDocument.signalOperationExecuted,l);q()};gui.DirectTextStyler.textStylingChanged="textSt [...]
++(function(){return gui.DirectTextStyler})();
++// Input 96
++runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.ObjectNameGenerator");
++gui.ImageManager=function(g,k,e){var n={"image/gif":".gif","image/jpeg":".jpg","image/png":".png"},m=odf.Namespaces.textns,q=g.getOdtDocument(),b=q.getFormatting(),h={};this.insertImage=function(r,d,f,a){var c;runtime.assert(0<f&&0<a,"Both width and height of the image should be greater than 0px.");c=q.getParagraphElement(q.getCursor(k).getNode()).getAttributeNS(m,"style-name");h.hasOwnProperty(c)||(h[c]=b.getContentSize(c,"paragraph"));c=h[c];f*=0.0264583333333334;a*=0.0264583333333334 [...]
++1;f>c.width&&(p=c.width/f);a>c.height&&(l=c.height/a);p=Math.min(p,l);c=f*p;f=a*p;l=q.getOdfCanvas().odfContainer().rootElement.styles;a=r.toLowerCase();var p=n.hasOwnProperty(a)?n[a]:null,u;a=[];runtime.assert(null!==p,"Image type is not supported: "+r);p="Pictures/"+e.generateImageName()+p;u=new ops.OpSetBlob;u.init({memberid:k,filename:p,mimetype:r,content:d});a.push(u);b.getStyleElement("Graphics","graphic",[l])||(r=new ops.OpAddStyle,r.init({memberid:k,styleName:"Graphics",styleFam [...]
++isAutomaticStyle:!1,setProperties:{"style:graphic-properties":{"text:anchor-type":"paragraph","svg:x":"0cm","svg:y":"0cm","style:wrap":"dynamic","style:number-wrapped-paragraphs":"no-limit","style:wrap-contour":"false","style:vertical-pos":"top","style:vertical-rel":"paragraph","style:horizontal-pos":"center","style:horizontal-rel":"paragraph"}}}),a.push(r));r=e.generateStyleName();d=new ops.OpAddStyle;d.init({memberid:k,styleName:r,styleFamily:"graphic",isAutomaticStyle:!0,setPropertie [...]
++"style:graphic-properties":{"style:vertical-pos":"top","style:vertical-rel":"baseline","style:horizontal-pos":"center","style:horizontal-rel":"paragraph","fo:background-color":"transparent","style:background-transparency":"100%","style:shadow":"none","style:mirror":"none","fo:clip":"rect(0cm, 0cm, 0cm, 0cm)","draw:luminance":"0%","draw:contrast":"0%","draw:red":"0%","draw:green":"0%","draw:blue":"0%","draw:gamma":"100%","draw:color-inversion":"false","draw:image-opacity":"100%","draw:co [...]
++a.push(d);u=new ops.OpInsertImage;u.init({memberid:k,position:q.getCursorPosition(k),filename:p,frameWidth:c+"cm",frameHeight:f+"cm",frameStyleName:r,frameName:e.generateFrameName()});a.push(u);g.enqueue(a)}};
+// Input 97
- runtime.loadClass("core.DomUtils");runtime.loadClass("odf.OdfUtils");runtime.loadClass("odf.OdfNodeFilter");runtime.loadClass("gui.SelectionMover");
- gui.SelectionView=function(g){function l(){var a=h.getRootNode();q!==a&&(q=a,u=q.parentNode.parentNode.parentNode,u.appendChild(v),u.appendChild(y),u.appendChild(w))}function c(a,b){a.style.left=b.left+"px";a.style.top=b.top+"px";a.style.width=b.width+"px";a.style.height=b.height+"px"}function m(a){D=a;v.style.display=y.style.display=w.style.display=!0===a?"block":"none"}function f(a){var b=s.getBoundingClientRect(u),c=h.getOdfCanvas().getZoomLevel(),d={};d.top=s.adaptRangeDifferenceToZ [...]
- b.top,c);d.left=s.adaptRangeDifferenceToZoomLevel(a.left-b.left,c);d.bottom=s.adaptRangeDifferenceToZoomLevel(a.bottom-b.top,c);d.right=s.adaptRangeDifferenceToZoomLevel(a.right-b.left,c);d.width=s.adaptRangeDifferenceToZoomLevel(a.width,c);d.height=s.adaptRangeDifferenceToZoomLevel(a.height,c);return d}function n(a){a=a.getBoundingClientRect();return Boolean(a&&0!==a.height)}function b(a){var b=t.getTextElements(a,!0,!1),c=a.cloneRange(),d=a.cloneRange();a=a.cloneRange();if(!b.length)r [...]
- var e;a:{e=0;var f=b[e],g=c.startContainer===f?c.startOffset:0,h=g;c.setStart(f,g);for(c.setEnd(f,h);!n(c);){if(f.nodeType===Node.ELEMENT_NODE&&h<f.childNodes.length)h=f.childNodes.length;else if(f.nodeType===Node.TEXT_NODE&&h<f.length)h+=1;else if(b[e])f=b[e],e+=1,g=h=0;else{e=!1;break a}c.setStart(f,g);c.setEnd(f,h)}e=!0}if(!e)return null;a:{e=b.length-1;f=b[e];h=g=d.endContainer===f?d.endOffset:f.length||f.childNodes.length;d.setStart(f,g);for(d.setEnd(f,h);!n(d);){if(f.nodeType===No [...]
- 0<g)g=0;else if(f.nodeType===Node.TEXT_NODE&&0<g)g-=1;else if(b[e])f=b[e],e-=1,g=h=f.length||f.childNodes.length;else{b=!1;break a}d.setStart(f,g);d.setEnd(f,h)}b=!0}if(!b)return null;a.setStart(c.startContainer,c.startOffset);a.setEnd(d.endContainer,d.endOffset);return{firstRange:c,lastRange:d,fillerRange:a}}function p(a,b){var c={};c.top=Math.min(a.top,b.top);c.left=Math.min(a.left,b.left);c.right=Math.max(a.right,b.right);c.bottom=Math.max(a.bottom,b.bottom);c.width=c.right-c.left;c. [...]
- c.top;return c}function r(a,b){b&&0<b.width&&0<b.height&&(a=a?p(a,b):b);return a}function d(a){function b(a){A.setUnfilteredPosition(a,0);return v.acceptNode(a)===B&&w.acceptPosition(A)===B?B:M}function c(a){var d=null;b(a)===B&&(d=s.getBoundingClientRect(a));return d}var d=a.commonAncestorContainer,e=a.startContainer,f=a.endContainer,g=a.startOffset,k=a.endOffset,l,m,n=null,p,q=x.createRange(),w,v=new odf.OdfNodeFilter,u;if(e===d||f===d)return q=a.cloneRange(),n=q.getBoundingClientRect [...]
- n;for(a=e;a.parentNode!==d;)a=a.parentNode;for(m=f;m.parentNode!==d;)m=m.parentNode;w=h.createRootFilter(e);for(d=a.nextSibling;d&&d!==m;)p=c(d),n=r(n,p),d=d.nextSibling;if(t.isParagraph(a))n=r(n,s.getBoundingClientRect(a));else if(a.nodeType===Node.TEXT_NODE)d=a,q.setStart(d,g),q.setEnd(d,d===m?k:d.length),p=q.getBoundingClientRect(),n=r(n,p);else for(u=x.createTreeWalker(a,NodeFilter.SHOW_TEXT,b,!1),d=u.currentNode=e;d&&d!==f;)q.setStart(d,g),q.setEnd(d,d.length),p=q.getBoundingClient [...]
- p),l=d,g=0,d=u.nextNode();l||(l=e);if(t.isParagraph(m))n=r(n,s.getBoundingClientRect(m));else if(m.nodeType===Node.TEXT_NODE)d=m,q.setStart(d,d===a?g:0),q.setEnd(d,k),p=q.getBoundingClientRect(),n=r(n,p);else for(u=x.createTreeWalker(m,NodeFilter.SHOW_TEXT,b,!1),d=u.currentNode=f;d&&d!==l;)if(q.setStart(d,0),q.setEnd(d,k),p=q.getBoundingClientRect(),n=r(n,p),d=u.previousNode())k=d.length;return n}function k(a,b){var c=a.getBoundingClientRect(),d={width:0};d.top=c.top;d.bottom=c.bottom;d [...]
- d.left=d.right=b?c.right:c.left;return d}function a(){l();if(g.getSelectionType()===ops.OdtCursor.RangeSelection){m(!0);var a=g.getSelectedRange(),e=b(a),h,n,s,t;a.collapsed||!e?m(!1):(m(!0),a=e.firstRange,h=e.lastRange,e=e.fillerRange,n=f(k(a,!1)),t=f(k(h,!0)),s=(s=d(e))?f(s):p(n,t),c(v,{left:n.left,top:n.top,width:Math.max(0,s.width-(n.left-s.left)),height:n.height}),t.top===n.top||t.bottom===n.bottom?y.style.display=w.style.display="none":(c(w,{left:s.left,top:t.top,width:Math.max(0, [...]
- height:t.height}),c(y,{left:s.left,top:n.top+n.height,width:Math.max(0,parseFloat(v.style.left)+parseFloat(v.style.width)-parseFloat(w.style.left)),height:Math.max(0,t.top-n.bottom)})),a.detach(),h.detach(),e.detach())}else m(!1)}function e(b){b===g&&a()}var h=g.getOdtDocument(),q,u,x=h.getDOM(),v=x.createElement("div"),y=x.createElement("div"),w=x.createElement("div"),t=new odf.OdfUtils,s=new core.DomUtils,D=!0,A=gui.SelectionMover.createPositionIterator(h.getRootNode()),B=NodeFilter.F [...]
- M=NodeFilter.FILTER_REJECT;this.show=this.rerender=a;this.hide=function(){m(!1)};this.visible=function(){return D};this.destroy=function(a){u.removeChild(v);u.removeChild(y);u.removeChild(w);g.getOdtDocument().unsubscribe(ops.OdtDocument.signalCursorMoved,e);a()};(function(){var a=g.getMemberId();l();v.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",a);y.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",a);w.setAttributeNS("urn:webodf:names:editinfo","editinf [...]
- a);v.className=y.className=w.className="selectionOverlay";g.getOdtDocument().subscribe(ops.OdtDocument.signalCursorMoved,e)})()};
- // Input 98
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("gui.SelectionView");
- gui.SelectionViewManager=function(){function g(){return Object.keys(l).map(function(c){return l[c]})}var l={};this.getSelectionView=function(c){return l.hasOwnProperty(c)?l[c]:null};this.getSelectionViews=g;this.removeSelectionView=function(c){l.hasOwnProperty(c)&&(l[c].destroy(function(){}),delete l[c])};this.hideSelectionView=function(c){l.hasOwnProperty(c)&&l[c].hide()};this.showSelectionView=function(c){l.hasOwnProperty(c)&&l[c].show()};this.rerenderSelectionViews=function(){Object. [...]
- l[c].rerender()})};this.registerCursor=function(c,g){var f=c.getMemberId(),n=new gui.SelectionView(c);g?n.show():n.hide();return l[f]=n};this.destroy=function(c){var l=g();(function n(b,g){g?c(g):b<l.length?l[b].destroy(function(c){n(b+1,c)}):c()})(0,void 0)}};
++runtime.loadClass("core.PositionFilter");
++gui.TextManipulator=function(g,k,e){function n(b){var d=new ops.OpRemoveText;d.init({memberid:k,position:b.position,length:b.length});return d}function m(b){0>b.length&&(b.position+=b.length,b.length=-b.length);return b}function q(e,d){var f=new core.PositionFilterChain,a=gui.SelectionMover.createPositionIterator(b.getRootElement(e)),c=d?a.nextPosition:a.previousPosition;f.addFilter("BaseFilter",b.getPositionFilter());f.addFilter("RootFilter",b.createRootFilter(k));for(a.setUnfilteredPo [...]
++h)return!0;return!1}var b=g.getOdtDocument(),h=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.enqueueParagraphSplittingOps=function(){var e=m(b.getCursorSelection(k)),d,f=[];0<e.length&&(d=n(e),f.push(d));d=new ops.OpSplitParagraph;d.init({memberid:k,position:e.position});f.push(d);g.enqueue(f);return!0};this.removeTextByBackspaceKey=function(){var e=b.getCursor(k),d=m(b.getCursorSelection(k)),f=null;0===d.length?q(e.getNode(),!1)&&(f=new ops.OpRemoveText,f.init({memberid:k,positio [...]
++1,length:1}),g.enqueue([f])):(f=n(d),g.enqueue([f]));return null!==f};this.removeTextByDeleteKey=function(){var e=b.getCursor(k),d=m(b.getCursorSelection(k)),f=null;0===d.length?q(e.getNode(),!0)&&(f=new ops.OpRemoveText,f.init({memberid:k,position:d.position,length:1}),g.enqueue([f])):(f=n(d),g.enqueue([f]));return null!==f};this.removeCurrentSelection=function(){var e=m(b.getCursorSelection(k));0!==e.length&&(e=n(e),g.enqueue([e]));return!0};this.insertText=function(h){var d=m(b.getCu [...]
++f,a=[];0<d.length&&(f=n(d),a.push(f));f=new ops.OpInsertText;f.init({memberid:k,position:d.position,text:h});a.push(f);e&&(h=e(d.position,h.length))&&a.push(h);g.enqueue(a)}};(function(){return gui.TextManipulator})();
++// Input 98
++runtime.loadClass("core.DomUtils");runtime.loadClass("core.Async");runtime.loadClass("core.ScheduledTask");runtime.loadClass("odf.OdfUtils");runtime.loadClass("odf.ObjectNameGenerator");runtime.loadClass("ops.OdtCursor");runtime.loadClass("ops.OpAddCursor");runtime.loadClass("ops.OpRemoveCursor");runtime.loadClass("gui.Clipboard");runtime.loadClass("gui.DirectTextStyler");runtime.loadClass("gui.DirectParagraphStyler");runtime.loadClass("gui.KeyboardHandler");runtime.loadClass("gui.Image [...]
++runtime.loadClass("gui.ImageSelector");runtime.loadClass("gui.TextManipulator");runtime.loadClass("gui.AnnotationController");runtime.loadClass("gui.EventManager");runtime.loadClass("gui.PlainTextPasteboard");
++gui.SessionController=function(){var g=core.PositionFilter.FilterResult.FILTER_ACCEPT;gui.SessionController=function(k,e,n,m){function q(a){a.preventDefault?a.preventDefault():a.returnValue=!1}function b(a,b,c){var d=new ops.OpMoveCursor;d.init({memberid:e,position:a,length:b||0,selectionType:c});return d}function h(a){var b=/[A-Za-z0-9]/,c=gui.SelectionMover.createPositionIterator(E.getRootNode()),d;for(c.setUnfilteredPosition(a.startContainer,a.startOffset);c.previousPosition();){d=c. [...]
++if(d.nodeType===Node.TEXT_NODE){if(d=d.data[c.unfilteredDomOffset()],!b.test(d))break}else if(!ia.isTextSpan(d))break;a.setStart(c.container(),c.unfilteredDomOffset())}c.setUnfilteredPosition(a.endContainer,a.endOffset);do if(d=c.getCurrentNode(),d.nodeType===Node.TEXT_NODE){if(d=d.data[c.unfilteredDomOffset()],!b.test(d))break}else if(!ia.isTextSpan(d))break;while(c.nextPosition());a.setEnd(c.container(),c.unfilteredDomOffset())}function r(a){var b=E.getParagraphElement(a.startContaine [...]
++b&&a.setStart(b,0);c&&(ia.isParagraph(a.endContainer)&&0===a.endOffset?a.setEndBefore(c):a.setEnd(c,c.childNodes.length))}function d(a){a=E.getDistanceFromCursor(e,a,0);var c=null!==a?a+1:null,d;if(c||a)d=E.getCursorPosition(e),a=b(d+a,c-a,ops.OdtCursor.RegionSelection),k.enqueue([a]);J.focus()}function f(a){var b=0<=ha.comparePoints(a.anchorNode,a.anchorOffset,a.focusNode,a.focusOffset),c=a.focusNode.ownerDocument.createRange();b?(c.setStart(a.anchorNode,a.anchorOffset),c.setEnd(a.focu [...]
++(c.setStart(a.focusNode,a.focusOffset),c.setEnd(a.anchorNode,a.anchorOffset));return{range:c,hasForwardSelection:b}}function a(a){return function(b){var c=a(b);return function(b,d){return a(d)===c}}}function c(c,d,f){var g=E.getOdfCanvas().getElement(),l;l=ha.containsNode(g,c.startContainer);g=ha.containsNode(g,c.endContainer);if(l||g){l&&g&&(2===f?h(c):3<=f&&r(c));c=d?{anchorNode:c.startContainer,anchorOffset:c.startOffset,focusNode:c.endContainer,focusOffset:c.endOffset}:{anchorNode:c [...]
++anchorOffset:c.endOffset,focusNode:c.startContainer,focusOffset:c.startOffset};d=E.convertDomToCursorRange(c,a(ia.getParagraphElement));c=E.getCursorSelection(e);if(d.position!==c.position||d.length!==c.length)c=b(d.position,d.length,ops.OdtCursor.RangeSelection),k.enqueue([c]);J.focus()}}function p(a){var c=E.getCursorSelection(e),d=E.getCursor(e).getStepCounter();0!==a&&(a=0<a?d.convertForwardStepsBetweenFilters(a,ra,wa):-d.convertBackwardStepsBetweenFilters(-a,ra,wa),a=c.length+a,k.e [...]
++a)]))}function l(a){var c=E.getCursorPosition(e),d=E.getCursor(e).getStepCounter();0!==a&&(a=0<a?d.convertForwardStepsBetweenFilters(a,ra,wa):-d.convertBackwardStepsBetweenFilters(-a,ra,wa),k.enqueue([b(c+a,0)]))}function u(){l(-1);return!0}function B(){l(1);return!0}function w(){p(-1);return!0}function y(){p(1);return!0}function v(a,b){var c=E.getParagraphElement(E.getCursor(e).getNode());runtime.assert(Boolean(c),"SessionController: Cursor outside paragraph");c=E.getCursor(e).getStepC [...]
++ra);b?p(c):l(c)}function t(){v(-1,!1);return!0}function s(){v(1,!1);return!0}function N(){v(-1,!0);return!0}function z(){v(1,!0);return!0}function x(a,b){var c=E.getCursor(e).getStepCounter().countStepsToLineBoundary(a,ra);b?p(c):l(c)}function R(){x(-1,!1);return!0}function F(){x(1,!1);return!0}function U(){x(-1,!0);return!0}function P(){x(1,!0);return!0}function A(){var a=E.getParagraphElement(E.getCursor(e).getNode()),b,c;runtime.assert(Boolean(a),"SessionController: Cursor outside pa [...]
++c=E.getDistanceFromCursor(e,a,0);b=gui.SelectionMover.createPositionIterator(E.getRootNode());for(b.setUnfilteredPosition(a,0);0===c&&b.previousPosition();)a=b.getCurrentNode(),ia.isParagraph(a)&&(c=E.getDistanceFromCursor(e,a,0));p(c);return!0}function ja(){var a=E.getParagraphElement(E.getCursor(e).getNode()),b,c;runtime.assert(Boolean(a),"SessionController: Cursor outside paragraph");b=gui.SelectionMover.createPositionIterator(E.getRootNode());b.moveToEndOfNode(a);for(c=E.getDistance [...]
++b.container(),b.unfilteredDomOffset());0===c&&b.nextPosition();)a=b.getCurrentNode(),ia.isParagraph(a)&&(b.moveToEndOfNode(a),c=E.getDistanceFromCursor(e,b.container(),b.unfilteredDomOffset()));p(c);return!0}function ka(a,b){var c=gui.SelectionMover.createPositionIterator(E.getRootNode());0<a&&c.moveToEnd();c=E.getDistanceFromCursor(e,c.container(),c.unfilteredDomOffset());b?p(c):l(c)}function G(){ka(-1,!1);return!0}function Z(){ka(1,!1);return!0}function O(){ka(-1,!0);return!0}function [...]
++!0);return!0}function K(){var a=E.getRootNode(),a=E.convertDomPointToCursorStep(a,a.childNodes.length);k.enqueue([b(0,a)]);return!0}function I(){var a=E.getCursor(e),b=fa.getSelection(),c;a?(va.clearSelection(),a.getSelectionType()===ops.OdtCursor.RegionSelection&&(c=a.getSelectedRange(),(c=ia.getImageElements(c)[0])&&va.select(c.parentNode)),J.hasFocus()&&(c=a.getSelectedRange(),b.extend?a.hasForwardSelection()?(b.collapse(c.startContainer,c.startOffset),b.extend(c.endContainer,c.endOf [...]
++c.endOffset),b.extend(c.startContainer,c.startOffset)):(Da=!0,b.removeAllRanges(),b.addRange(c.cloneRange()),E.getOdfCanvas().getElement().setActive(),runtime.setTimeout(function(){Da=!1},0)))):va.clearSelection()}function C(){!1===Da&&runtime.setTimeout(I,0)}function Y(a){var b=E.getCursor(e).getSelectedRange();b.collapsed||(Ea.setDataFromRange(a,b)?oa.removeCurrentSelection():runtime.log("Cut operation failed"))}function H(){return!1!==E.getCursor(e).getSelectedRange().collapsed}funct [...]
++E.getCursor(e).getSelectedRange();b.collapsed||Ea.setDataFromRange(a,b)||runtime.log("Cut operation failed")}function Q(a){var b;fa.clipboardData&&fa.clipboardData.getData?b=fa.clipboardData.getData("Text"):a.clipboardData&&a.clipboardData.getData&&(b=a.clipboardData.getData("text/plain"));b&&(oa.removeCurrentSelection(),k.enqueue(Ga.createPasteOps(b)),a.preventDefault?a.preventDefault():a.returnValue=!1)}function L(){return!1}function ca(a){if(V)V.onOperationExecuted(a)}function la(a){ [...]
++a)}function aa(){return V?(V.moveBackward(1),ya.trigger(),!0):!1}function ma(){return V?(V.moveForward(1),ya.trigger(),!0):!1}function T(){var a=fa.getSelection(),b=0<a.rangeCount&&f(a);sa&&b&&(ta=!0,va.clearSelection(),Fa.setUnfilteredPosition(a.focusNode,a.focusOffset),Ba.acceptPosition(Fa)===g&&(2===za?h(b.range):3<=za&&r(b.range),n.setSelectedRange(b.range,b.hasForwardSelection),E.emit(ops.OdtDocument.signalCursorMoved,n)))}function $(a){var b=a.target||a.srcElement,c=E.getCursor(e) [...]
++ha.containsNode(E.getOdfCanvas().getElement(),b))ta=!1,Ba=E.createRootFilter(b),za=a.detail,c&&a.shiftKey&&fa.getSelection().collapse(c.getAnchorNode(),0),1<za&&T()}function W(a){var b=a.target||a.srcElement,e=a.detail,g=a.clientX,h=a.clientY;xa.processRequests();ia.isImage(b)&&ia.isCharacterFrame(b.parentNode)?d(b.parentNode):sa&&!va.isSelectorElement(b)&&(ta?c(n.getSelectedRange(),n.hasForwardSelection(),a.detail):runtime.setTimeout(function(){var a;a=(a=fa.getSelection())?{anchorNode [...]
++anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}:null;var b;if(!a.anchorNode&&!a.focusNode){var d=E.getDOM();b=null;d.caretRangeFromPoint?(d=d.caretRangeFromPoint(g,h),b={container:d.startContainer,offset:d.startOffset}):d.caretPositionFromPoint&&(d=d.caretPositionFromPoint(g,h))&&d.offsetNode&&(b={container:d.offsetNode,offset:d.offset});if(!b)return;a.anchorNode=b.container;a.anchorOffset=b.offset;a.focusNode=a.anchorNode;a.focusOffset=a.anchorOffset}a=f(a) [...]
++a.hasForwardSelection,e)},0));za=0;ta=sa=!1}function da(a){W(a)}function S(a){var b=a.target||a.srcElement,c=null;"annotationRemoveButton"===b.className?(c=ha.getElementsByTagNameNS(b.parentNode,odf.Namespaces.officens,"annotation")[0],ua.removeAnnotation(c)):W(a)}function ga(a){return function(){a();return!0}}function D(a){return function(b){return E.getCursor(e).getSelectionType()===ops.OdtCursor.RangeSelection?a(b):!0}}var fa=runtime.getWindow(),E=k.getOdtDocument(),pa=new core.Async [...]
++ia=new odf.OdfUtils,Ea=new gui.Clipboard,M=new gui.KeyboardHandler,qa=new gui.KeyboardHandler,ra=new core.PositionFilterChain,wa=E.getPositionFilter(),sa=!1,Aa=new odf.ObjectNameGenerator(E.getOdfCanvas().odfContainer(),e),ta=!1,Ba=null,V=null,J=new gui.EventManager(E),ua=new gui.AnnotationController(k,e),na=new gui.DirectTextStyler(k,e),ea=m&&m.directParagraphStylingEnabled?new gui.DirectParagraphStyler(k,e,Aa):null,oa=new gui.TextManipulator(k,e,na.createCursorStyleOp),Ca=new gui.Imag [...]
++e,Aa),va=new gui.ImageSelector(E.getOdfCanvas()),Fa=gui.SelectionMover.createPositionIterator(E.getRootNode()),xa,Da=!1,ya,Ga=new gui.PlainTextPasteboard(E,e),za=0;runtime.assert(null!==fa,"Expected to be run in an environment which has a global window, like a browser.");ra.addFilter("BaseFilter",wa);ra.addFilter("RootFilter",E.createRootFilter(e));this.selectRange=c;this.moveCursorToLeft=u;this.moveCursorToDocumentBoundary=ka;this.extendSelectionToEntireDocument=K;this.startEditing=fun [...]
++E.getOdfCanvas().getElement().classList.add("virtualSelections");J.subscribe("keydown",M.handleEvent);J.subscribe("keypress",qa.handleEvent);J.subscribe("keyup",q);J.subscribe("beforecut",H);J.subscribe("cut",Y);J.subscribe("copy",X);J.subscribe("beforepaste",L);J.subscribe("paste",Q);J.subscribe("mousedown",$);J.subscribe("mousemove",xa.trigger);J.subscribe("mouseup",S);J.subscribe("contextmenu",da);J.subscribe("focus",C);E.subscribe(ops.OdtDocument.signalOperationExecuted,ya.trigger); [...]
++ca);a=new ops.OpAddCursor;a.init({memberid:e});k.enqueue([a]);V&&V.saveInitialState()};this.endEditing=function(){var a;a=new ops.OpRemoveCursor;a.init({memberid:e});k.enqueue([a]);V&&V.resetInitialState();E.unsubscribe(ops.OdtDocument.signalOperationExecuted,ca);E.unsubscribe(ops.OdtDocument.signalOperationExecuted,ya.trigger);J.unsubscribe("keydown",M.handleEvent);J.unsubscribe("keypress",qa.handleEvent);J.unsubscribe("keyup",q);J.unsubscribe("cut",Y);J.unsubscribe("beforecut",H);J.un [...]
++X);J.unsubscribe("paste",Q);J.unsubscribe("beforepaste",L);J.unsubscribe("mousemove",xa.trigger);J.unsubscribe("mousedown",$);J.unsubscribe("mouseup",S);J.unsubscribe("contextmenu",da);J.unsubscribe("focus",C);E.getOdfCanvas().getElement().classList.remove("virtualSelections")};this.getInputMemberId=function(){return e};this.getSession=function(){return k};this.setUndoManager=function(a){V&&V.unsubscribe(gui.UndoManager.signalUndoStackChanged,la);if(V=a)V.setOdtDocument(E),V.setPlayback [...]
++V.subscribe(gui.UndoManager.signalUndoStackChanged,la)};this.getUndoManager=function(){return V};this.getAnnotationController=function(){return ua};this.getDirectTextStyler=function(){return na};this.getDirectParagraphStyler=function(){return ea};this.getImageManager=function(){return Ca};this.getTextManipulator=function(){return oa};this.getEventManager=function(){return J};this.getKeyboardHandlers=function(){return{keydown:M,keypress:qa}};this.destroy=function(a){var b=[xa.destroy,na. [...]
++b.push(ea.destroy);pa.destroyAll(b,a)};(function(){var a=-1!==fa.navigator.appVersion.toLowerCase().indexOf("mac"),b=gui.KeyboardHandler.Modifier,c=gui.KeyboardHandler.KeyCode;xa=new core.ScheduledTask(T,0);ya=new core.ScheduledTask(I,0);M.bind(c.Tab,b.None,D(function(){oa.insertText("\t");return!0}));M.bind(c.Left,b.None,D(u));M.bind(c.Right,b.None,D(B));M.bind(c.Up,b.None,D(t));M.bind(c.Down,b.None,D(s));M.bind(c.Backspace,b.None,ga(oa.removeTextByBackspaceKey));M.bind(c.Delete,b.None [...]
++M.bind(c.Left,b.Shift,D(w));M.bind(c.Right,b.Shift,D(y));M.bind(c.Up,b.Shift,D(N));M.bind(c.Down,b.Shift,D(z));M.bind(c.Home,b.None,D(R));M.bind(c.End,b.None,D(F));M.bind(c.Home,b.Ctrl,D(G));M.bind(c.End,b.Ctrl,D(Z));M.bind(c.Home,b.Shift,D(U));M.bind(c.End,b.Shift,D(P));M.bind(c.Up,b.CtrlShift,D(A));M.bind(c.Down,b.CtrlShift,D(ja));M.bind(c.Home,b.CtrlShift,D(O));M.bind(c.End,b.CtrlShift,D(ba));a?(M.bind(c.Clear,b.None,oa.removeCurrentSelection),M.bind(c.Left,b.Meta,D(R)),M.bind(c.Righ [...]
++M.bind(c.Home,b.Meta,D(G)),M.bind(c.End,b.Meta,D(Z)),M.bind(c.Left,b.MetaShift,D(U)),M.bind(c.Right,b.MetaShift,D(P)),M.bind(c.Up,b.AltShift,D(A)),M.bind(c.Down,b.AltShift,D(ja)),M.bind(c.Up,b.MetaShift,D(O)),M.bind(c.Down,b.MetaShift,D(ba)),M.bind(c.A,b.Meta,D(K)),M.bind(c.B,b.Meta,D(na.toggleBold)),M.bind(c.I,b.Meta,D(na.toggleItalic)),M.bind(c.U,b.Meta,D(na.toggleUnderline)),ea&&(M.bind(c.L,b.MetaShift,D(ea.alignParagraphLeft)),M.bind(c.E,b.MetaShift,D(ea.alignParagraphCenter)),M.bin [...]
++D(ea.alignParagraphRight)),M.bind(c.J,b.MetaShift,D(ea.alignParagraphJustified))),ua&&M.bind(c.C,b.MetaShift,ua.addAnnotation),M.bind(c.Z,b.Meta,aa),M.bind(c.Z,b.MetaShift,ma)):(M.bind(c.A,b.Ctrl,D(K)),M.bind(c.B,b.Ctrl,D(na.toggleBold)),M.bind(c.I,b.Ctrl,D(na.toggleItalic)),M.bind(c.U,b.Ctrl,D(na.toggleUnderline)),ea&&(M.bind(c.L,b.CtrlShift,D(ea.alignParagraphLeft)),M.bind(c.E,b.CtrlShift,D(ea.alignParagraphCenter)),M.bind(c.R,b.CtrlShift,D(ea.alignParagraphRight)),M.bind(c.J,b.CtrlSh [...]
++ua&&M.bind(c.C,b.CtrlAlt,ua.addAnnotation),M.bind(c.Z,b.Ctrl,aa),M.bind(c.Z,b.CtrlShift,ma));qa.setDefault(D(function(a){var b;b=null===a.which||void 0===a.which?String.fromCharCode(a.keyCode):0!==a.which&&0!==a.charCode?String.fromCharCode(a.which):null;return!b||a.altKey||a.ctrlKey||a.metaKey?!1:(oa.insertText(b),!0)}));qa.bind(c.Enter,b.None,D(oa.enqueueParagraphSplittingOps))})()};return gui.SessionController}();
+// Input 99
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("core.EventNotifier");runtime.loadClass("core.DomUtils");runtime.loadClass("odf.OdfUtils");runtime.loadClass("odf.Namespaces");runtime.loadClass("gui.SelectionMover");runtime.loadClass("core.PositionFilterChain");runtime.loadClass("ops.StepsTranslator");runtime.loadClass("ops.TextPositionFilter");runtime.loadClass("ops.Member");
- ops.OdtDocument=function(g){function l(){var a=g.odfContainer().getContentElement(),b=a&&a.localName;runtime.assert("text"===b,"Unsupported content element type '"+b+"' for OdtDocument");return a}function c(){return l().ownerDocument}function m(a){for(;a&&!(a.namespaceURI===odf.Namespaces.officens&&"text"===a.localName||a.namespaceURI===odf.Namespaces.officens&&"annotation"===a.localName);)a=a.parentNode;return a}function f(b){this.acceptPosition=function(c){c=c.container();var d;d="str [...]
- a[b].getNode():b;return m(c)===m(d)?q:u}}function n(a){var b=gui.SelectionMover.createPositionIterator(l());a=v.convertStepsToDomPoint(a);b.setUnfilteredPosition(a.node,a.offset);return b}function b(a,b){return g.getFormatting().getStyleElement(a,b)}function p(a){return b(a,"paragraph")}var r=this,d,k,a={},e={},h=new core.EventNotifier([ops.OdtDocument.signalMemberAdded,ops.OdtDocument.signalMemberUpdated,ops.OdtDocument.signalMemberRemoved,ops.OdtDocument.signalCursorAdded,ops.OdtDocum [...]
- ops.OdtDocument.signalCursorMoved,ops.OdtDocument.signalParagraphChanged,ops.OdtDocument.signalParagraphStyleModified,ops.OdtDocument.signalCommonStyleCreated,ops.OdtDocument.signalCommonStyleDeleted,ops.OdtDocument.signalTableAdded,ops.OdtDocument.signalOperationExecuted,ops.OdtDocument.signalUndoStackChanged,ops.OdtDocument.signalStepsInserted,ops.OdtDocument.signalStepsRemoved]),q=core.PositionFilter.FilterResult.FILTER_ACCEPT,u=core.PositionFilter.FilterResult.FILTER_REJECT,x,v,y;th [...]
- c;this.getRootElement=m;this.getIteratorAtPosition=n;this.convertDomPointToCursorStep=function(a,b){return v.convertDomPointToSteps(a,b)};this.convertDomToCursorRange=function(a,b,c,d){var e;e=v.convertDomPointToSteps(a,b);a=a===c&&b===d?e:v.convertDomPointToSteps(c,d);return{position:e,length:a-e}};this.convertCursorToDomRange=function(a,b){var d=c().createRange(),e,f;e=v.convertStepsToDomPoint(a);b?(f=v.convertStepsToDomPoint(a+b),0<b?(d.setStart(e.node,e.offset),d.setEnd(f.node,f.off [...]
- f.offset),d.setEnd(e.node,e.offset))):d.setStart(e.node,e.offset);return d};this.getStyleElement=b;this.upgradeWhitespacesAtPosition=function(a){a=n(a);var b,c,e;a.previousPosition();a.previousPosition();for(e=-1;1>=e;e+=1){b=a.container();c=a.unfilteredDomOffset();if(b.nodeType===Node.TEXT_NODE&&" "===b.data[c]&&d.isSignificantWhitespace(b,c)){runtime.assert(" "===b.data[c],"upgradeWhitespaceToElement: textNode.data[offset] should be a literal space");var f=b.ownerDocument.createElemen [...]
- "text:s");f.appendChild(b.ownerDocument.createTextNode(" "));b.deleteData(c,1);0<c&&(b=b.splitText(c));b.parentNode.insertBefore(f,b);b=f;a.moveToEndOfNode(b)}a.nextPosition()}};this.downgradeWhitespacesAtPosition=function(a){var b=n(a),c;a=b.container();for(b=b.unfilteredDomOffset();!d.isCharacterElement(a)&&a.childNodes[b];)a=a.childNodes[b],b=0;a.nodeType===Node.TEXT_NODE&&(a=a.parentNode);d.isDowngradableSpaceElement(a)&&(b=a.firstChild,c=a.lastChild,k.mergeIntoParent(a),c!==b&&k.no [...]
- k.normalizeTextNodes(b))};this.getParagraphStyleElement=p;this.getParagraphElement=function(a){return d.getParagraphElement(a)};this.getParagraphStyleAttributes=function(a){return(a=p(a))?g.getFormatting().getInheritedStyleAttributes(a):null};this.getTextNodeAtStep=function(b,d){var e=n(b),f=e.container(),g,h=0,k=null;f.nodeType===Node.TEXT_NODE?(g=f,h=e.unfilteredDomOffset()):(g=c().createTextNode(""),h=0,f.insertBefore(g,e.rightNode()));if(d&&a[d]&&r.getCursorPosition(d)===b){for(k=a[ [...]
- "cursor"===k.nextSibling.localName;)k.parentNode.insertBefore(k.nextSibling,k);0<g.length&&g.nextSibling!==k&&(g=c().createTextNode(""),h=0);k.parentNode.insertBefore(g,k)}for(;g.previousSibling&&g.previousSibling.nodeType===Node.TEXT_NODE;)g.previousSibling.appendData(g.data),h=g.previousSibling.length,g=g.previousSibling,g.parentNode.removeChild(g.nextSibling);return{textNode:g,offset:h}};this.fixCursorPositions=function(){var b=new core.PositionFilterChain;b.addFilter("BaseFilter",x) [...]
- a[c],e=d.getStepCounter(),f,g,h=!1;b.addFilter("RootFilter",r.createRootFilter(c));c=e.countStepsToPosition(d.getAnchorNode(),0,b);e.isPositionWalkable(b)?0===c&&(h=!0,d.move(0)):(h=!0,f=e.countPositionsToNearestStep(d.getNode(),0,b),g=e.countPositionsToNearestStep(d.getAnchorNode(),0,b),d.move(f),0!==c&&(0<g&&(c+=1),0<f&&(c-=1),e=e.countSteps(c,b),d.move(e),d.move(-e,!0)));h&&r.emit(ops.OdtDocument.signalCursorMoved,d);b.removeFilter("RootFilter")})};this.getDistanceFromCursor=function [...]
- a[b];var e,f;runtime.assert(null!==c&&void 0!==c,"OdtDocument.getDistanceFromCursor called without node");b&&(e=v.convertDomPointToSteps(b.getNode(),0),f=v.convertDomPointToSteps(c,d));return f-e};this.getCursorPosition=function(b){return(b=a[b])?v.convertDomPointToSteps(b.getNode(),0):0};this.getCursorSelection=function(b){b=a[b];var c=0,d=0;b&&(c=v.convertDomPointToSteps(b.getNode(),0),d=v.convertDomPointToSteps(b.getAnchorNode(),0));return{position:d,length:c-d}};this.getPositionFilt [...]
- this.getOdfCanvas=function(){return g};this.getRootNode=l;this.addMember=function(a){runtime.assert(void 0===e[a.getMemberId()],"This member already exists");e[a.getMemberId()]=a};this.getMember=function(a){return e.hasOwnProperty(a)?e[a]:null};this.removeMember=function(a){delete e[a]};this.getCursor=function(b){return a[b]};this.getCursors=function(){var b=[],c;for(c in a)a.hasOwnProperty(c)&&b.push(a[c]);return b};this.addCursor=function(b){runtime.assert(Boolean(b),"OdtDocument::add [...]
- var c=b.getStepCounter().countSteps(1,x),d=b.getMemberId();runtime.assert("string"===typeof d,"OdtDocument::addCursor has cursor without memberid");runtime.assert(!a[d],"OdtDocument::addCursor is adding a duplicate cursor with memberid "+d);b.move(c);a[d]=b};this.removeCursor=function(b){var c=a[b];return c?(c.removeFromOdtDocument(),delete a[b],r.emit(ops.OdtDocument.signalCursorRemoved,b),!0):!1};this.getFormatting=function(){return g.getFormatting()};this.emit=function(a,b){h.emit(a, [...]
- function(a,b){h.subscribe(a,b)};this.unsubscribe=function(a,b){h.unsubscribe(a,b)};this.createRootFilter=function(a){return new f(a)};this.close=function(a){a()};this.destroy=function(a){a()};x=new ops.TextPositionFilter(l);d=new odf.OdfUtils;k=new core.DomUtils;v=new ops.StepsTranslator(l,gui.SelectionMover.createPositionIterator,x,500);h.subscribe(ops.OdtDocument.signalStepsInserted,v.handleStepsInserted);h.subscribe(ops.OdtDocument.signalStepsRemoved,v.handleStepsRemoved);h.subscribe [...]
- function(a){var b=a.spec(),c=b.memberid,b=(new Date(b.timestamp)).toISOString(),d=g.odfContainer().getMetadataManager();a.isEdit&&(c=r.getMember(c).getProperties().fullName,d.setMetadata({"dc:creator":c,"dc:date":b},null),y||(d.incrementEditingCycles(),d.setMetadata(null,["meta:editing-duration","meta:document-statistic"])),y=a)})};ops.OdtDocument.signalMemberAdded="member/added";ops.OdtDocument.signalMemberUpdated="member/updated";ops.OdtDocument.signalMemberRemoved="member/removed";
- ops.OdtDocument.signalCursorAdded="cursor/added";ops.OdtDocument.signalCursorRemoved="cursor/removed";ops.OdtDocument.signalCursorMoved="cursor/moved";ops.OdtDocument.signalParagraphChanged="paragraph/changed";ops.OdtDocument.signalTableAdded="table/added";ops.OdtDocument.signalCommonStyleCreated="style/created";ops.OdtDocument.signalCommonStyleDeleted="style/deleted";ops.OdtDocument.signalParagraphStyleModified="paragraphstyle/modified";ops.OdtDocument.signalOperationExecuted="operatio [...]
- ops.OdtDocument.signalUndoStackChanged="undo/changed";ops.OdtDocument.signalStepsInserted="steps/inserted";ops.OdtDocument.signalStepsRemoved="steps/removed";(function(){return ops.OdtDocument})();
++runtime.loadClass("gui.Caret");
++gui.CaretManager=function(g){function k(a){return c.hasOwnProperty(a)?c[a]:null}function e(){return Object.keys(c).map(function(a){return c[a]})}function n(a){a===g.getInputMemberId()&&g.getSession().getOdtDocument().getOdfCanvas().getElement().removeAttribute("tabindex");delete c[a]}function m(a){a=a.getMemberId();a===g.getInputMemberId()&&(a=k(a))&&a.refreshCursorBlinking()}function q(){var a=k(g.getInputMemberId());l=!1;a&&a.ensureVisible()}function b(){var a=k(g.getInputMemberId()); [...]
++l||(l=!0,runtime.setTimeout(q,50)))}function h(a){a.memberId===g.getInputMemberId()&&b()}function r(){var a=k(g.getInputMemberId());a&&a.setFocus()}function d(){var a=k(g.getInputMemberId());a&&a.removeFocus()}function f(){var a=k(g.getInputMemberId());a&&a.show()}function a(){var a=k(g.getInputMemberId());a&&a.hide()}var c={},p=runtime.getWindow(),l=!1;this.registerCursor=function(a,d,e){var f=a.getMemberId();d=new gui.Caret(a,d,e);c[f]=d;f===g.getInputMemberId()?(runtime.log("Starting [...]
++f),a.handleUpdate=b,g.getSession().getOdtDocument().getOdfCanvas().getElement().setAttribute("tabindex",-1),g.getEventManager().focus()):a.handleUpdate=d.handleUpdate;return d};this.getCaret=k;this.getCarets=e;this.destroy=function(b){var k=g.getSession().getOdtDocument(),l=g.getEventManager(),q=e();k.unsubscribe(ops.OdtDocument.signalParagraphChanged,h);k.unsubscribe(ops.OdtDocument.signalCursorMoved,m);k.unsubscribe(ops.OdtDocument.signalCursorRemoved,n);l.unsubscribe("focus",r);l.uns [...]
++d);p.removeEventListener("focus",f,!1);p.removeEventListener("blur",a,!1);(function t(a,c){c?b(c):a<q.length?q[a].destroy(function(b){t(a+1,b)}):b()})(0,void 0);c={}};(function(){var b=g.getSession().getOdtDocument(),c=g.getEventManager();b.subscribe(ops.OdtDocument.signalParagraphChanged,h);b.subscribe(ops.OdtDocument.signalCursorMoved,m);b.subscribe(ops.OdtDocument.signalCursorRemoved,n);c.subscribe("focus",r);c.subscribe("blur",d);p.addEventListener("focus",f,!1);p.addEventListener(" [...]
+// Input 100
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright at kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
- runtime.loadClass("ops.TrivialOperationRouter");runtime.loadClass("ops.OperationFactory");runtime.loadClass("ops.OdtDocument");
- ops.Session=function(g){var l=new ops.OperationFactory,c=new ops.OdtDocument(g),m=null;this.setOperationFactory=function(c){l=c;m&&m.setOperationFactory(l)};this.setOperationRouter=function(f){m=f;f.setPlaybackFunction(function(f){f.execute(c);c.emit(ops.OdtDocument.signalOperationExecuted,f)});f.setOperationFactory(l)};this.getOperationFactory=function(){return l};this.getOdtDocument=function(){return c};this.enqueue=function(c){m.push(c)};this.close=function(f){m.close(function(g){g?f [...]
- this.destroy=function(f){c.destroy(f)};this.setOperationRouter(new ops.TrivialOperationRouter)};
++runtime.loadClass("gui.Caret");runtime.loadClass("ops.EditInfo");runtime.loadClass("gui.EditInfoMarker");gui.SessionViewOptions=function(){this.caretBlinksOnRangeSelect=this.caretAvatarsInitiallyVisible=this.editInfoMarkersInitiallyVisible=!0};
++gui.SessionView=function(){return function(g,k,e,n,m){function q(a,b,c){function d(b,c,e){c=b+'[editinfo|memberid="'+a+'"]'+e+c;a:{var f=u.firstChild;for(b=b+'[editinfo|memberid="'+a+'"]'+e+"{";f;){if(f.nodeType===Node.TEXT_NODE&&0===f.data.indexOf(b)){b=f;break a}f=f.nextSibling}b=null}b?b.data=c:u.appendChild(document.createTextNode(c))}d("div.editInfoMarker","{ background-color: "+c+"; }","");d("span.editInfoColor","{ background-color: "+c+"; }","");d("span.editInfoAuthor",'{ content [...]
++":before");d("dc|creator","{ background-color: "+c+"; }","");d("div.selectionOverlay","{ background-color: "+c+";}","")}function b(a){var b,c;for(c in w)w.hasOwnProperty(c)&&(b=w[c],a?b.show():b.hide())}function h(a){n.getCarets().forEach(function(b){a?b.showHandle():b.hideHandle()})}function r(a){var b=a.getMemberId();a=a.getProperties();q(b,a.fullName,a.color);k===b&&q("","",a.color)}function d(a){var b=a.getMemberId(),c=e.getOdtDocument().getMember(b).getProperties();n.registerCursor [...]
++!0);if(a=n.getCaret(b))a.setAvatarImageUrl(c.imageUrl),a.setColor(c.color);runtime.log("+++ View here +++ eagerly created an Caret for '"+b+"'! +++")}function f(a){a=a.getMemberId();var b=m.getSelectionView(k),c=m.getSelectionView(gui.ShadowCursor.ShadowCursorMemberId),d=n.getCaret(k);a===k?(c.hide(),b&&b.show(),d&&d.show()):a===gui.ShadowCursor.ShadowCursorMemberId&&(c.show(),b&&b.hide(),d&&d.hide())}function a(a){m.removeSelectionView(a)}function c(a){var b=a.paragraphElement,c=a.memb [...]
++var d,f="",g=b.getElementsByTagNameNS(B,"editinfo")[0];g?(f=g.getAttributeNS(B,"id"),d=w[f]):(f=Math.random().toString(),d=new ops.EditInfo(b,e.getOdtDocument()),d=new gui.EditInfoMarker(d,y),g=b.getElementsByTagNameNS(B,"editinfo")[0],g.setAttributeNS(B,"id",f),w[f]=d);d.addEdit(c,new Date(a))}function p(){N=!0}function l(){s=runtime.getWindow().setInterval(function(){N&&(m.rerenderSelectionViews(),N=!1)},200)}var u,B="urn:webodf:names:editinfo",w={},y=void 0!==g.editInfoMarkersInitial [...]
++Boolean(g.editInfoMarkersInitiallyVisible):!0,v=void 0!==g.caretAvatarsInitiallyVisible?Boolean(g.caretAvatarsInitiallyVisible):!0,t=void 0!==g.caretBlinksOnRangeSelect?Boolean(g.caretBlinksOnRangeSelect):!0,s,N=!1;this.showEditInfoMarkers=function(){y||(y=!0,b(y))};this.hideEditInfoMarkers=function(){y&&(y=!1,b(y))};this.showCaretAvatars=function(){v||(v=!0,h(v))};this.hideCaretAvatars=function(){v&&(v=!1,h(v))};this.getSession=function(){return e};this.getCaret=function(a){return n.ge [...]
++this.destroy=function(b){var g=e.getOdtDocument(),h=Object.keys(w).map(function(a){return w[a]});g.unsubscribe(ops.OdtDocument.signalMemberAdded,r);g.unsubscribe(ops.OdtDocument.signalMemberUpdated,r);g.unsubscribe(ops.OdtDocument.signalCursorAdded,d);g.unsubscribe(ops.OdtDocument.signalCursorRemoved,a);g.unsubscribe(ops.OdtDocument.signalParagraphChanged,c);g.unsubscribe(ops.OdtDocument.signalCursorMoved,f);g.unsubscribe(ops.OdtDocument.signalParagraphChanged,p);g.unsubscribe(ops.OdtDo [...]
++p);g.unsubscribe(ops.OdtDocument.signalParagraphStyleModified,p);runtime.getWindow().clearInterval(s);u.parentNode.removeChild(u);(function U(a,c){c?b(c):a<h.length?h[a].destroy(function(b){U(a+1,b)}):b()})(0,void 0)};(function(){var b=e.getOdtDocument(),g=document.getElementsByTagName("head")[0];b.subscribe(ops.OdtDocument.signalMemberAdded,r);b.subscribe(ops.OdtDocument.signalMemberUpdated,r);b.subscribe(ops.OdtDocument.signalCursorAdded,d);b.subscribe(ops.OdtDocument.signalCursorRemo [...]
++c);b.subscribe(ops.OdtDocument.signalCursorMoved,f);l();b.subscribe(ops.OdtDocument.signalParagraphChanged,p);b.subscribe(ops.OdtDocument.signalTableAdded,p);b.subscribe(ops.OdtDocument.signalParagraphStyleModified,p);u=document.createElementNS(g.namespaceURI,"style");u.type="text/css";u.media="screen, print, handheld, projection";u.appendChild(document.createTextNode("@namespace editinfo url(urn:webodf:names:editinfo);"));u.appendChild(document.createTextNode("@namespace dc url(http:// [...]
++g.appendChild(u)})()}}();
+// Input 101
+var webodf_css="@namespace draw url(urn:oasis:names:tc:opendocument:xmlns:drawing:1.0);\n at namespace fo url(urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0);\n at namespace office url(urn:oasis:names:tc:opendocument:xmlns:office:1.0);\n at namespace presentation url(urn:oasis:names:tc:opendocument:xmlns:presentation:1.0);\n at namespace style url(urn:oasis:names:tc:opendocument:xmlns:style:1.0);\n at namespace svg url(urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0);\n at namespace [...]
- // Input 102
- var webodf_version="0.4.2-1451-gc9cf878";
diff --cc apps/documents/js/documents.js
index ff7d400,0000000..decb3ff
mode 100644,000000..100644
--- a/apps/documents/js/documents.js
+++ b/apps/documents/js/documents.js
@@@ -1,441 -1,0 +1,456 @@@
+/*globals $,OC,fileDownloadPath,t,document,odf,webodfEditor,alert,require,dojo,runtime */
+var documentsMain = {
+ _documents: [],
+ _sessions: [],
+ _members: [],
+ isEditormode : false,
+ useUnstable : false,
+ isGuest : false,
+ memberId : false,
+ esId : false,
+ ready :false,
+
+ UI : {
+ /* Overlay HTML */
+ overlay : '<div id="documents-overlay"></div> <div id="documents-overlay-below"></div>',
+
+ /* Toolbar HTML */
+ toolbar : '<div id="odf-toolbar" class="dijitToolbar">' +
+ ' <div id="document-title"><div>' +
+ '%title%' +
+ ' </div></div>' +
+ ' <button id="odf-close">' +
+ t('documents', 'Close') +
+ ' </button>' +
+ ' <button id="odf-invite" class="drop">' +
+ t('documents', 'Share') +
+ ' </button>' +
+ ' <span id="toolbar" class="claro"></span>' +
+ '</div>',
+
+ /* Editor wrapper HTML */
+ container : '<div id = "mainContainer" class="claro" style="">' +
+ ' <div id = "editor">' +
+ ' <div id = "container">' +
+ ' <div id="canvas"></div>' +
+ ' </div>' +
+ ' </div>' +
+ ' <div id = "collaboration">' +
+ ' <div id = "collabContainer">' +
+ ' <div id = "members">' +
+ ' <div id = "inviteButton"></div>' +
+ ' <div id = "memberList"></div>' +
+ ' </div>' +
+ ' </div>' +
+ ' </div>' +
+ '</div>',
+
+ /* Previous window title */
+ mainTitle : '',
+
+ init : function(){
+ $(documentsMain.UI.overlay).hide().appendTo(document.body);
+ documentsMain.UI.mainTitle = $('title').text();
+ },
+
+ showOverlay : function(){
+ $('#documents-overlay,#documents-overlay-below').fadeIn('fast');
+ },
+
+ hideOverlay : function(){
+ $('#documents-overlay,#documents-overlay-below').fadeOut('fast');
+ },
+
+ showEditor : function(title, canShare){
+ $(document.body).prepend(documentsMain.UI.toolbar.replace(/%title%/g, title));
+ if (!canShare){
+ $('#odf-invite').remove();
+ } else {
+ //TODO: fill in with users
+ }
+ $(document.body).addClass("claro");
+ $(document.body).prepend(documentsMain.UI.container);
+ // in case we are on the public sharing page we shall display the odf into the preview tag
+ $('#preview').html(container);
+ $('title').text(documentsMain.UI.mainTitle + '| ' + title);
+ },
+
+ hideEditor : function(){
+ // Fade out toolbar
+ $('#odf-toolbar').fadeOut('fast');
+ // Fade out editor
+ $('#mainContainer').fadeOut('fast', function() {
+ $('#mainContainer').remove();
+ $('#odf-toolbar').remove();
+ $('#content').fadeIn('fast');
+ $(document.body).removeClass('claro');
+ $('title').text(documentsMain.UI.mainTitle);
+ });
+ },
+ showProgress : function(){
+ $('.documentslist .progress').show();
+ },
+
+ hideProgress : function(){
+ $('.documentslist .progress').hide();
+ },
+
+ showLostConnection : function(){
+ $('#memberList .memberListButton').css({opacity : 0.3});
+ $('#odf-toolbar').children(':not(#document-title)').hide();
+ $('<div id="connection-lost"></div>').prependTo('#memberList');
+ $('<div id="warning-connection-lost">' + t('documents', 'No connection to server. Trying to reconnect.') +'<img src="'+ OC.imagePath('core', 'loading-dark.gif') +'" alt="" /></div>').appendTo('#odf-toolbar');
+ },
+
+ hideLostConnection : function() {
+ $('#connection-lost,#warning-connection-lost').remove();
+ $('#odf-toolbar').children(':not(#document-title)').show();
+ $('#memberList .memberListButton').css({opacity : 1});
+ }
+ },
+
+ onStartup: function() {
+ var fileId;
+ "use strict";
+ documentsMain.useUnstable = $('#webodf-unstable').val()==='true';
+ documentsMain.UI.init();
+
+ if (!OC.currentUser){
+ documentsMain.isGuest = true;
+
+ } else {
+ // Does anything indicate that we need to autostart a session?
+ fileId = parent.location.hash.replace(/\W*/g, '');
+ }
+
+ documentsMain.show();
+ if (fileId){
+ documentsMain.UI.showOverlay();
+ }
+
+ var webodfSource = (oc_debug === true) ? 'webodf-debug' : 'webodf';
+ OC.addScript('documents', '3rdparty/webodf/' + webodfSource).done(function() {
+ // preload stuff in the background
+ require({}, ["dojo/ready"], function(ready) {
+ ready(function() {
+ require({}, ["webodf/editor/Editor"], function(Editor) {
+ runtime.setTranslator(function(s){return t('documents', s);});
+ documentsMain.ready = true;
+ if (fileId){
+ documentsMain.prepareSession();
+ documentsMain.joinSession(fileId);
+ }
+ });
+ });
+ });
+ });
+ },
+
+ prepareSession : function(){
+ documentsMain.isEditorMode = true;
+ documentsMain.UI.showOverlay();
+ $(window).on('beforeunload', function(){
+ return t('documents', "Leaving this page in Editor mode might cause unsaved data. It is recommended to use 'Close' button instead.");
+ });
+ },
+
+ prepareGrid : function(){
+ documentsMain.isEditorMode = false;
+ documentsMain.UI.hideOverlay();
+ },
+
+ initSession: function(response) {
+ "use strict";
+
- if (!response || !response.es_id || !response.status || response.status==='error'){
++ if(response && (response.id && !response.es_id)){
++ return documentsMain.view(response.id);
++ }
++
++ if (!response || !response.status || response.status==='error'){
+ OC.Notification.show(t('documents', 'Failed to load this document. Please check if it can be opened with an external odt editor. This might also mean it has been unshared or deleted recently.'));
+ documentsMain.prepareGrid();
+ documentsMain.show();
++ $(window).off('beforeunload');
+ setTimeout(OC.Notification.hide, 7000);
+ return;
+ }
+
+ //Wait for 3 sec if editor is still loading
+ if (!documentsMain.ready){
+ setTimeout(function(){ documentsMain.initSession(response); }, 3000);
+ console.log('Waiting for the editor to start...');
+ return;
+ }
+
+ require({ }, ["webodf/editor/server/owncloud/ServerFactory", "webodf/editor/Editor"], function (ServerFactory, Editor) {
+ // fade out file list and show WebODF canvas
+ $('#content').fadeOut('fast').promise().done(function() {
+
+ documentsMain.UI.showEditor(
+ documentsMain.getNameByFileid(response.file_id),
+ response.permissions & OC.PERMISSION_SHARE && !documentsMain.isGuest
+ );
+ var serverFactory = new ServerFactory();
+ documentsMain.esId = response.es_id;
+ documentsMain.memberId = response.member_id;
+
+ // TODO: set webodf translation system, by passing a proper function translate(!string):!string in "runtime.setTranslator(translate);"
+
+ documentsMain.webodfServerInstance = serverFactory.createServer();
+ documentsMain.webodfServerInstance.setToken(oc_requesttoken);
+ documentsMain.webodfEditorInstance = new Editor({unstableFeaturesEnabled: documentsMain.useUnstable}, documentsMain.webodfServerInstance, serverFactory);
+
+ // load the document and get called back when it's live
+ documentsMain.webodfEditorInstance.openSession(documentsMain.esId, documentsMain.memberId, function() {
+ documentsMain.webodfEditorInstance.startEditing();
+ documentsMain.UI.hideOverlay();
+ parent.location.hash = response.file_id;
+ });
+ });
+ });
+ },
+
+
+ joinSession: function(fileId) {
+ console.log('joining session '+fileId);
+ var url;
+ if (documentsMain.isGuest){
+ url = OC.Router.generate('documents_session_joinasguest') + '/' + fileId;
+ } else {
+ url = OC.Router.generate('documents_session_joinasuser') + '/' + fileId;
+ }
+ $.post(
+ url,
+ { name : $("[name='memberName']").val() },
+ documentsMain.initSession
+ );
+ },
++
++ view : function(id){
++ OC.addScript('documents', 'viewer/viewer', function() {
++ documentsMain.prepareGrid();
++ $(window).off('beforeunload');
++ var path = $('li[data-id='+ id +']>a').attr('href');
++ odfViewer.isDocuments = true;
++ odfViewer.onView(path);
++ });
++ },
+
+ onCreate: function(event){
+ event.preventDefault();
+ var docElem = $('.documentslist .template').clone();
+ docElem.removeClass('template');
+ docElem.addClass('document');
+ docElem.insertAfter('.documentslist .template');
+ docElem.show();
+ $.post(
+ OC.Router.generate('documents_documents_create'),
+ {},
+ documentsMain.show
+ );
+ },
+
+ onInvite: function(event) {
+ event.preventDefault();
+ if (OC.Share.droppedDown) {
+ OC.Share.hideDropDown();
+ } else {
+ (function() {
+ var target = OC.Share.showLink;
+ OC.Share.showLink = function() {
+ var r = target.apply( this, arguments );
+ $('#linkText').val( $('#linkText').val().replace('service=files', 'service=documents') );
+ return r;
+ };
+ })();
+
+ OC.Share.showDropDown(
+ 'file',
+ parent.location.hash.replace(/\W*/g, ''),
+ $("#odf-toolbar"),
+ true,
+ OC.PERMISSION_READ | OC.PERMISSION_SHARE | OC.PERMISSION_UPDATE
+ );
+ }
+ },
+
+ sendInvite: function() {
+ var users = [];
+ $('input[name=invitee\\[\\]]').each(function(i, e) {
+ users.push($(e).val());
+ });
+ $.post(OC.Router.generate('documents_user_invite'), {users: users});
+ },
+
+ onClose: function() {
+ "use strict";
+
+ if (!documentsMain.isEditorMode){
+ return;
+ }
+ documentsMain.isEditorMode = false;
+ $(window).off('beforeunload');
+ parent.location.hash = "";
+
+ documentsMain.webodfEditorInstance.endEditing();
+ documentsMain.webodfEditorInstance.closeSession(function() {
+ // successfull shutdown - all is good.
+ // TODO: proper session leaving call to server, either by webodfServerInstance or custom
+// documentsMain.webodfServerInstance.leaveSession(sessionId, memberId, function() {
+ if (documentsMain.isGuest){
+ $(document.body).attr('id', 'body-login');
+ $('header,footer').show();
+ }
+ documentsMain.webodfEditorInstance.destroy(documentsMain.UI.hideEditor);
+
+ if (documentsMain.isGuest){
+ var url = OC.Router.generate('documents_user_disconnectGuest');
+ } else {
+ var url = OC.Router.generate('documents_user_disconnect');
+ }
+
+ $.post(url + '/' + documentsMain.memberId, {esId: documentsMain.esId});
+
+ documentsMain.show();
+// });
+ });
+ },
+
+ getNameByFileid : function(fileid){
+ return $('.documentslist li[data-id='+ fileid + ']').find('label').text();
+ },
+
+ show: function(){
+ if (documentsMain.isGuest){
+ return;
+ }
+ documentsMain.UI.showProgress();
+ jQuery.when(documentsMain.loadDocuments())
+ .then(function(){
+ documentsMain.renderDocuments();
+ documentsMain.UI.hideProgress();
+ });
+ },
+
+ loadDocuments: function () {
+ var self = this;
+ var def = new $.Deferred();
+ OC.Router.registerLoadedCallback(function () {
+ jQuery.getJSON(OC.Router.generate('documents_documents_list'))
+ .done(function (data) {
+ self._documents = data.documents;
+ self._sessions = data.sessions;
+ self._members = data.members;
+ def.resolve();
+ })
+ .fail(function(data){
+ console.log(t('documents','Failed to load documents.'));
+ });
+ });
+ return def;
+ },
+
+ renderDocuments: function () {
+ var self = this,
+ hasDocuments = false;
+
+ //remove all but template
+ $('.documentslist .document:not(.template,.progress)').remove();
+
+ jQuery.each(this._documents, function(i,document){
+ var docElem = $('.documentslist .template').clone();
+ docElem.removeClass('template');
+ docElem.addClass('document');
+ docElem.attr('data-id', document.fileid);
+
+ var a = docElem.find('a');
+ a.attr('href', OC.Router.generate('download',{file:document.path}));
+ a.find('label').text(document.name);
+ a.css('background-image', 'url("'+document.icon+'")');
+
+ $('.documentslist').append(docElem);
+ docElem.show();
+ hasDocuments = true;
+ });
+ jQuery.each(this._sessions, function(i,session){
+ if (self._members[session.es_id].length > 0) {
+ var docElem = $('.documentslist .document[data-id="'+session.file_id+'"]');
+ if (docElem.length > 0) {
+ docElem.attr('data-esid', session.es_id);
+ docElem.find('label').after('<img class="svg session-active" src="'+OC.imagePath('core','places/contacts-dark')+'">');
+ docElem.addClass('session');
+ } else {
+ console.log('Could not find file '+session.file_id+' for session '+session.es_id);
+ }
+ }
+ });
+
+ if (!hasDocuments){
- $('#documents-content').append('<div id="emptyfolder">'
++ $('#documents-content').append('<div id="emptycontent">'
+ + t('documents', 'No documents are found. Please upload or create a document!')
+ + '</div>'
+ );
+ } else {
- $('#emptyfolder').remove();
++ $('#emptycontent').remove();
+ }
+ }
+};
+
+
+//web odf bootstrap code. Added here to reduce number of requests
+/*globals navigator,dojoConfig */
+var usedLocale = "C";
+
+if (navigator && navigator.language.match(/^(de)/)) {
+ usedLocale = navigator.language.substr(0,2);
+}
+
+dojoConfig = {
+ locale: usedLocale,
+ paths: {
+ "webodf/editor": OC.appswebroots.documents + "/js/3rdparty/webodf/editor",
+ "dijit": OC.appswebroots.documents + "/js/3rdparty/resources/dijit",
+ "dojox": OC.appswebroots.documents + "/js/3rdparty/resources/dojox",
+ "dojo": OC.appswebroots.documents + "/js/3rdparty/resources/dojo",
+ "resources": OC.appswebroots.documents + "/js/3rdparty/resources"
+ }
+};
+
+//init
+$(document).ready(function() {
+ "use strict";
+
+ $('.documentslist').on('click', 'li:not(.add-document)', function(event) {
+ event.preventDefault();
+
+ if (documentsMain.isEditorMode){
+ return;
+ }
+
+ documentsMain.prepareSession();
+ if ($(this).attr('data-id')){
+ documentsMain.joinSession($(this).attr('data-id'));
+ }
+ });
+
+ $(document.body).on('click', '#odf-close', documentsMain.onClose);
+ $(document.body).on('click', '#odf-invite', documentsMain.onInvite);
+ $(document.body).on('click', '#odf-join', function(event){
+ event.preventDefault();
+
+ // !Login page mess wih WebODF toolbars
+ $(document.body).attr('id', 'body-user');
+ $('header,footer').hide();
+ documentsMain.prepareSession();
+ documentsMain.joinSession(
+ $("[name='document']").val()
+ );
+ });
+ $('.add-document').on('click', '.add', documentsMain.onCreate);
+
+ var file_upload_start = $('#file_upload_start');
+ file_upload_start.on('fileuploaddone', documentsMain.show);
+ //TODO when ending a session as the last user close session?
+
+ OC.addScript('documents', '3rdparty/webodf/dojo-amalgamation', documentsMain.onStartup);
+});
diff --cc apps/documents/js/viewer/viewer.js
index 4d4534e,0000000..088bafa
mode 100644,000000..100644
--- a/apps/documents/js/viewer/viewer.js
+++ b/apps/documents/js/viewer/viewer.js
@@@ -1,89 -1,0 +1,112 @@@
+var odfViewer = {
++ isDocuments : false,
+ supportedMimesRead: [
+ 'application/vnd.oasis.opendocument.text',
+ 'application/vnd.oasis.opendocument.spreadsheet',
+ 'application/vnd.oasis.opendocument.graphics',
+ 'application/vnd.oasis.opendocument.presentation'
+ ],
+
+ supportedMimesUpdate: [
- //none. see https://github.com/owncloud/documents/issues/108
++ 'application/vnd.oasis.opendocument.text'
+ ],
+
+ register : function(){
+ for (var i = 0; i < odfViewer.supportedMimesRead.length; ++i) {
+ var mime = odfViewer.supportedMimesRead[i];
- FileActions.register(mime, 'View', OC.PERMISSION_READ, '', odfViewer.dispatch);
++ FileActions.register(mime, 'View', OC.PERMISSION_READ, '', odfViewer.onView);
+ FileActions.setDefault(mime, 'View');
+ }
++ for (var i = 0; i < odfViewer.supportedMimesUpdate.length; ++i) {
++ var mime = odfViewer.supportedMimesUpdate[i];
++ FileActions.register(
++ mime,
++ t('documents', 'Edit'),
++ OC.PERMISSION_UPDATE,
++ OC.imagePath('core', 'actions/rename'),
++ odfViewer.onEdit
++ );
++ }
+ },
+
+ dispatch : function(filename){
+ if (odfViewer.supportedMimesUpdate.indexOf(FileActions.getCurrentMimeType()) !== -1
+ && FileActions.getCurrentPermissions() & OC.PERMISSION_UPDATE
+ ){
+ odfViewer.onEdit(filename);
+ } else {
+ odfViewer.onView(filename);
+ }
+ },
+
+ onEdit : function(){
+ var fileId = FileActions.currentFile.parent().attr('data-id');
- window.location = OC.linkTo('documents', 'index.php') + '#' + fileId;
++ window.open(OC.linkTo('documents', 'index.php') + '#' + fileId);
+ },
+
+ onView: function(filename) {
- OC.addStyle('documents', 'viewer/webodf');
- OC.addStyle('documents', 'viewer/odfviewer');
++ var webodfSource = (oc_debug === true) ? 'webodf-debug' : 'webodf',
++ attachTo = odfViewer.isDocuments ? '#documents-content' : 'table',
++ attachToolbarTo = odfViewer.isDocuments ? '#content-wrapper' : '#controls';
++
++ if (odfViewer.isDocuments){
++ //Documents view
++ var location = filename;
++ } else {
++ //Public page, files app, etc
++ var location = fileDownloadPath($('#dir').val(), filename);
++ OC.addStyle('documents', 'viewer/webodf');
++ }
+
- var webodfSource = (oc_debug === true) ? 'webodf-debug' : 'webodf';
++ OC.addStyle('documents', 'viewer/odfviewer');
+
+ OC.addScript('documents', '3rdparty/webodf/' + webodfSource, function() {
- var location = fileDownloadPath($('#dir').val(), filename);
-
+ // fade out files menu and add odf menu
+ $('#controls div').fadeOut('slow').promise().done(function() {
+ // odf action toolbar
+ var odfToolbarHtml =
+ '<div id="odf-toolbar">' +
+ '<button id="odf_close">' + t('documents', 'Close') +
+ '</button></div>';
- $('#controls').append(odfToolbarHtml);
-
++ if (odfViewer.isDocuments){
++ $(attachToolbarTo).prepend(odfToolbarHtml);
++ $('#odf-toolbar').css({position:'fixed'});
++ } else {
++ $(attachToolbarTo).append(odfToolbarHtml);
++ }
+ });
+
+ // fade out file list and show pdf canvas
- $('table').fadeOut('slow').promise().done(function() {
++ $('table, #documents-content').fadeOut('slow').promise().done(function() {
+ var canvashtml = '<div id="odf-canvas"></div>';
- $('table').after(canvashtml);
++ $(attachTo).after(canvashtml);
+ // in case we are on the public sharing page we shall display the odf into the preview tag
+ $('#preview').html(canvashtml);
+
+ var odfelement = document.getElementById("odf-canvas");
+ var odfcanvas = new odf.OdfCanvas(odfelement);
+ odfcanvas.load(location);
+ });
+ });
+ },
+
+ onClose: function() {
+ // Fade out odf-toolbar
+ $('#odf-toolbar').fadeOut('slow');
+ // Fade out editor
+ $('#odf-canvas').fadeOut('slow', function() {
+ $('#odf-toolbar').remove();
+ $('#odf-canvas').remove();
+ $('#controls div').not('.hidden').fadeIn('slow');
- $('table').fadeIn('slow');
++ $('table, #documents-content').fadeIn('slow');
+ });
+ }
+};
+
+$(document).ready(function() {
+ if (typeof FileActions !== 'undefined') {
+ odfViewer.register();
+ }
+
+ $('#odf_close').live('click', odfViewer.onClose);
+});
diff --cc apps/documents/lib/file.php
index 43c69c6,0000000..265e6c7
mode 100644,000000..100644
--- a/apps/documents/lib/file.php
+++ b/apps/documents/lib/file.php
@@@ -1,233 -1,0 +1,263 @@@
+<?php
+/**
+ * ownCloud - Documents App
+ *
+ * @author Victor Dubiniuk
+ * @copyright 2013 Victor Dubiniuk victor.dubiniuk at gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OCA\Documents;
+
+class File {
+ protected $fileId;
+ protected $owner;
+ protected $path;
+ protected $sharing;
+ protected $passwordProtected = false;
+
+
+ public function __construct($fileId, $shareOps = null){
+ if (!$fileId){
+ throw new \Exception('No valid file has been passed');
+ }
+
+ $this->fileId = $fileId;
+
+ //if you know how to get sharing info by fileId via API,
+ //please send me a link to video tutorial :/
+ if (!is_null($shareOps)){
+ $this->sharing = $shareOps;
+ } else {
+ $this->sharing = $this->getSharingOps();
+ }
+ }
+
+ public static function getByShareToken($token){
+ $linkItem = \OCP\Share::getShareByToken($token);
+ if (is_array($linkItem) && isset($linkItem['uid_owner'])) {
+ // seems to be a valid share
+ $rootLinkItem = \OCP\Share::resolveReShare($linkItem);
+ $fileOwner = $rootLinkItem['uid_owner'];
+ } else {
+ throw new \Exception('This file was probably unshared');
+ }
+
+ if (!isset($rootLinkItem['path']) && isset($rootLinkItem['file_target'])){
+ $rootLinkItem['path'] = 'files/' . $rootLinkItem['file_target'];
+ }
+ $file = new File($rootLinkItem['file_source'], array($rootLinkItem));
++
++
++ if (isset($rootLinkItem['uid_owner'])){
++ \OC_Util::tearDownFS();
++ \OC_Util::setupFS($rootLinkItem['uid_owner']);
++ $file->setOwner($rootLinkItem['uid_owner']);
++ $file->setPath('/files' . \OC\Files\Filesystem::getPath($linkItem['file_source']));
++ }
++
+ if (isset($linkItem['share_with']) && !empty($linkItem['share_with'])){
+ $file->setPasswordProtected(true);
+ }
+
+ return $file;
+ }
+
+ public function getFileId(){
+ return $this->fileId;
+ }
+
+ public function setOwner($owner){
+ $this->owner = $owner;
+ }
+
+ public function setPath($path){
+ $this->path = $path;
+ }
+
+ public function isPublicShare(){
+ foreach ($this->sharing as $share){
+ if (
+ $share['share_type'] == \OCP\Share::SHARE_TYPE_LINK
+ || $share['share_type'] == \OCP\Share::SHARE_TYPE_EMAIL
+ ){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public function isPasswordProtected(){
+ return $this->passwordProtected;
+ }
+
+ public function checkPassword($password){
+ $shareId = $this->getShareId();
+ if (!$this->isPasswordProtected()
+ || (\OC::$session->exists('public_link_authenticated')
+ && \OC::$session->get('public_link_authenticated') === $shareId)
+ ){
+ return true;
+ }
+
+ // Check Password
+ $forcePortable = (CRYPT_BLOWFISH != 1);
+ $hasher = new \PasswordHash(8, $forcePortable);
+ if ($hasher->CheckPassword($password.\OC_Config::getValue('passwordsalt', ''),
+ $this->getPassword())) {
+ // Save item id in session for future request
+ \OC::$session->set('public_link_authenticated', $shareId);
+ return true;
+ }
+ return false;
+ }
+
+ public function setPasswordProtected($value){
+ $this->passwordProtected = $value;
+ }
++
++ public function getPermissions(){
++ if (count($this->sharing)){
++ if ($this->isPublicShare()){
++ $permissions = \OCP\PERMISSION_READ | \OCP\PERMISSION_UPDATE;
++ } else {
++ $permissions = $this->sharing[0]['permissions'];
++ }
++ } else {
++ list($owner, $path) = $this->getOwnerViewAndPath();
++ $permissions = 0;
++ if (\OC\Files\Filesystem::isReadable($path)){
++ $permissions |= \OCP\PERMISSION_READ;
++ }
++ if (\OC\Files\Filesystem::isUpdatable($path)){
++ $permissions |= \OCP\PERMISSION_UPDATE;
++ }
++
++ }
++ return $permissions;
++ }
+
+ /**
+ *
+ * @return string owner of the current file item
+ * @throws \Exception
+ */
+ public function getOwnerViewAndPath(){
+ if (!$this->owner || !$this->path){
+ $info = $this->getSharedFileOwnerAndPath();
+ if (is_array($info) && count($info)){
+ $owner = $info[0];
+ $path = $info[1];
+ } else {
+ list($owner, $path) = $this->getLocalFileOwnerAndPath();
+ }
+
+ if (!$path){
+ throw new \Exception($this->fileId . ' can not be resolved');
+ }
+
+ $this->path = $path;
+ $this->owner = $owner;
+ }
+
+ /* to emit hooks properly, view root should contain /user/files */
+
+ if (strpos($this->path, 'files') === 0){
+ $this->path = preg_replace('|^files|', '', $this->path);
+ $view = new View('/' . $this->owner . '/files');
+ } else {
+ $view = new View('/' . $this->owner);
+ }
+
+ if (!$view->file_exists($this->path)){
+ throw new \Exception($this->path . ' doesn\'t exist');
+ }
+
+ return array($view, $this->path);
+ }
+
+ public function getOwner(){
+ if (!$this->owner){
+ $this->getOwnerViewAndPath();
+ }
+ return $this->owner;
+ }
+
+ protected function getSharedFileOwnerAndPath(){
+ $result = array();
+ foreach ($this->sharing as $share){
+ return array(
+ $share['uid_owner'],
+ $share['path']
+ );
+ }
+
+ return $result;
+ }
+
+
+ protected function getLocalFileOwnerAndPath(){
+ $fileInfo = \OC\Files\Cache\Cache::getById($this->fileId);
+ $owner = \OCP\User::getUser();
+ if (!$owner){
+ throw new Exception('Guest users can\'t access local files. This one was probably unshared recently.');
+ }
+
+ return array ($owner, @$fileInfo[1]);
+ }
+
+ protected function getPassword(){
+ return $this->sharing[0]['share_with'];
+ }
+
+ protected function getShareId(){
+ return $this->sharing[0]['id'];
+ }
+
+ protected function getSharingOps(){
+
+ $where = 'AND `file_source`=?';
+ $values = array($this->fileId);
+
+ if (\OCP\User::isLoggedIn()){
+ $where .= ' AND ((`share_type`=' . \OCP\Share::SHARE_TYPE_USER . ' AND `share_with`=?) OR `share_type`=' . \OCP\Share::SHARE_TYPE_LINK . ')';
+ $values[] = \OCP\User::getUser();
+ } else {
+ $where .= ' AND (`share_type`=' . \OCP\Share::SHARE_TYPE_LINK . ')';
+ }
+
+ $query = \OC_DB::prepare('SELECT `*PREFIX*share`.`id`, `item_type`, `*PREFIX*share`.`parent`, `uid_owner`, '
+ .'`share_type`, `share_with`, `file_source`, `path`, `file_target`, '
+ .'`permissions`, `expiration`, `storage`, `*PREFIX*filecache`.`parent` as `file_parent`, '
+ .'`name`, `mtime`, `mimetype`, `mimepart`, `size`, `encrypted`, `etag`'
+ .'FROM `*PREFIX*share` INNER JOIN `*PREFIX*filecache` ON `file_source` = `*PREFIX*filecache`.`fileid` WHERE `item_type` = \'file\' ' . $where);
+ $result = $query->execute($values);
+ $shares = $result->fetchAll();
+
+ $origins = array();
+ if (is_array($shares)){
+ foreach ($shares as $share){
+ $origin = \OCP\Share::resolveReShare($share);
+ if (!isset($origin['path']) && isset($origin['file_target'])){
+ $origin['path'] = 'files/' . $origin['file_target'];
+ }
+ $origins[] = $origin;
+ }
+ }
+ return $origins;
+ }
+}
diff --cc apps/documents/lib/genesis.php
index 1994339,0000000..bb61d70
mode 100644,000000..100644
--- a/apps/documents/lib/genesis.php
+++ b/apps/documents/lib/genesis.php
@@@ -1,100 -1,0 +1,109 @@@
+<?php
+/**
+ * ownCloud - Documents App
+ *
+ * @author Victor Dubiniuk
+ * @copyright 2013 Victor Dubiniuk victor.dubiniuk at gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Documents;
+
+class Genesis {
+
+ const DOCUMENTS_DIRNAME='/documents';
+
+ protected $view;
+
+ protected $path;
+
+ protected $hash;
+
+
+ /**
+ * Create new genesis document
+ * @param OCA\Documents\View $view Filesystem view with root '/user/files'
+ * @param string $path relative path
+ * @param string $owner file owner
+ * */
+ public function __construct(\OCA\Documents\View $view, $path, $owner){
+ $this->view = new View('/' . $owner);
- $this->hash = $this->getDocumentHash($view, $path);
+
+ if (!$this->view->file_exists(self::DOCUMENTS_DIRNAME)){
+ $this->view->mkdir(self::DOCUMENTS_DIRNAME );
+ }
+
++ $this->hash = $this->getDocumentHash($view, $path);
+ $this->path = self::DOCUMENTS_DIRNAME . '/' . $this->hash . '.odt';
-
+ if (!$this->view->file_exists($this->path)){
+ //copy new genesis to /user/documents/{hash}.odt
++ // get decrypted content
++ $content = $view->file_get_contents($path);
++
+ $proxyStatus = \OC_FileProxy::$enabled;
- \OC_FileProxy::$enabled = false;
- $this->view->copy('/files' . $path, $this->path);
++ \OC_FileProxy::$enabled = false;
++
++ $this->view->file_put_contents($this->path, $content);
+ \OC_FileProxy::$enabled = $proxyStatus;
+ }
+
+ try {
+ $this->validate($this->view, $this->path);
+ } catch (\Exception $e){
+ throw new \Exception('Failed to copy genesis');
+ }
+ }
+
+ public function getPath(){
+ return $this->path;
+ }
+
+ public function getHash(){
+ return $this->hash;
+ }
+
+ public static function getHashByPath($path){
+ return preg_replace('|([a-zA-Z0-9])*\..*$|', '\1', $path);
+ }
+
+ protected function getDocumentHash($view, $path){
+ $this->validate($view, $path);
- return sha1($view->file_get_contents($path));
++ $proxyStatus = \OC_FileProxy::$enabled;
++ \OC_FileProxy::$enabled = false;
++
++ $hash = sha1($view->file_get_contents($path));
++
++ \OC_FileProxy::$enabled = $proxyStatus;
++ return $hash;
+ }
+
+ /**
+ * Check if genesis is valid
+ * @param OCA\Documents\View $view
+ * @param string $path relative to the view
+ * @throws \Exception
+ */
+ protected function validate($view, $path){
+ if (!$view->file_exists($path)){
+ throw new \Exception('Document not found ' . $path);
+ }
+ if (!$view->is_file($path)){
+ throw new \Exception('Object ' . $path . ' is not a file.');
+ }
+ //TODO check if it is a valid odt
+ }
+
+}
diff --cc apps/files_encryption/lib/helper.php
index 9aa631d,17bcac5..17bcac5
mode 100644,100755..100644
--- a/apps/files_encryption/lib/helper.php
+++ b/apps/files_encryption/lib/helper.php
diff --cc apps/files_external/lib/config.php
index aaa6c5b,12836c7..12836c7
mode 100644,100755..100644
--- a/apps/files_external/lib/config.php
+++ b/apps/files_external/lib/config.php
diff --cc apps/search_lucene/ajax/lucene.php
index a73f583,0000000..3291849
mode 100644,000000..100644
--- a/apps/search_lucene/ajax/lucene.php
+++ b/apps/search_lucene/ajax/lucene.php
@@@ -1,89 -1,0 +1,84 @@@
+<?php
+
+OCP\JSON::checkLoggedIn();
+OCP\JSON::callCheck();
+OCP\JSON::checkAppEnabled('search_lucene');
+session_write_close();
+
- //FIXME refactor this into the lib folder
++//FIXME refactor db queries and logic into the lib folder
+
+function index() {
+ if ( isset($_GET['fileid']) ){
+ $fileIds = array($_GET['fileid']);
+ } else {
+ $fileIds = OCA\Search_Lucene\Indexer::getUnindexed();
+ }
+
+ $eventSource = new OC_EventSource();
+ $eventSource->send('count', count($fileIds));
+
+ $skippedDirs = explode(';', OCP\Config::getUserValue(OCP\User::getUser(), 'search_lucene', 'skipped_dirs', '.git;.svn;.CVS;.bzr'));
+
- $query = OC_DB::prepare('INSERT INTO `*PREFIX*lucene_status` VALUES (?,?)');
-
+ foreach ($fileIds as $id) {
+ $skipped = false;
++
++ $fileStatus = OCA\Search_Lucene\Status::fromFileId($id);
+
+ try{
+ //before we start mark the file as error so we know there was a problem when the php execution dies
- $result = $query->execute(array($id, 'E'));
++ $fileStatus->markError();
+
+ $path = OC\Files\Filesystem::getPath($id);
+ $eventSource->send('indexing', $path);
+
- //clean jobs for indexed file
- $param=json_encode(array('path'=>$path,'user'=>OCP\User::getUser()));
- $cleanjobquery = OC_DB::prepare('DELETE FROM `*PREFIX*queuedtasks` WHERE `app`=? AND `parameters`=?');
- $cleanjobquery->execute(array('search_lucene',$param));
-
+ foreach ($skippedDirs as $skippedDir) {
+ if (strpos($path, '/' . $skippedDir . '/') !== false //contains dir
+ || strrpos($path, '/' . $skippedDir) === strlen($path) - (strlen($skippedDir) + 1) // ends with dir
+ ) {
- $result = $query->execute(array($id, 'S'));
++ $result = $fileStatus->markSkipped();
+ $skipped = true;
+ break;
+ }
+ }
+ if (!$skipped) {
+ if (OCA\Search_Lucene\Indexer::indexFile($path, OCP\User::getUser())) {
- $result = $query->execute(array($id, 'I'));
++ $result = $fileStatus->markIndexed();
+ }
+ }
+
+ if (!$result) {
+ OC_JSON::error(array('message' => 'Could not index file.'));
+ $eventSource->send('error', $path);
+ }
+ } catch (Exception $e) { //sqlite might report database locked errors when stock filescan is in progress
+ //this also catches db locked exception that might come up when using sqlite
+ \OCP\Util::writeLog('search_lucene',
+ $e->getMessage() . ' Trace:\n' . $e->getTraceAsString(),
+ \OCP\Util::ERROR);
+ OC_JSON::error(array('message' => 'Could not index file.'));
+ $eventSource->send('error', $e->getMessage());
+ //try to mark the file as new to let it reindex
- $query->execute(array($id, 'N')); // Add UI to trigger rescan of files with status 'E'rror?
++ $fileStatus->markNew(); // Add UI to trigger rescan of files with status 'E'rror?
+ }
+ }
+
+ $eventSource->send('done', '');
+ $eventSource->close();
+}
+
+function handleOptimize() {
+ OCA\Search_Lucene\Lucene::optimizeIndex();
+}
+
+if ($_GET['operation']) {
+ switch ($_GET['operation']) {
+ case 'index':
+ index();
+ break;
+ case 'optimize':
+ handleOptimize();
+ break;
+ default:
+ OCP\JSON::error(array('cause' => 'Unknown operation'));
+ }
+}
diff --cc apps/search_lucene/appinfo/update.php
index db78e20,0000000..4cb29e8
mode 100644,000000..100644
--- a/apps/search_lucene/appinfo/update.php
+++ b/apps/search_lucene/appinfo/update.php
@@@ -1,11 -1,0 +1,28 @@@
+<?php
+
+$currentVersion=OC_Appconfig::getValue('search_lucene', 'installed_version');
+if (version_compare($currentVersion, '0.5.0', '<')) {
+ //force reindexing of files
+ $stmt = OCP\DB::prepare('DELETE FROM `*PREFIX*lucene_status` WHERE 1=1');
+ $stmt->execute();
+ //clear old background jobs
+ $stmt = OCP\DB::prepare('DELETE FROM `*PREFIX*queuedtasks` WHERE `app`=?');
+ $stmt->execute(array('search_lucene'));
+}
++
++if (version_compare($currentVersion, '0.5.2', '<')) {
++ //delete duplicate id entries
++ $stmt = OCP\DB::prepare('
++ DELETE FROM `*PREFIX*lucene_status`
++ WHERE `fileid` IN (
++ SELECT `fileid`
++ FROM (
++ SELECT `fileid`
++ FROM `*PREFIX*lucene_status`
++ GROUP BY `fileid`
++ HAVING count(`status`) > 1
++ ) AS `mysqlerr1093hack`
++ )
++ ');
++ $stmt->execute();
++}
diff --cc apps/search_lucene/appinfo/version
index 5d4294b,0000000..2411653
mode 100644,000000..100644
--- a/apps/search_lucene/appinfo/version
+++ b/apps/search_lucene/appinfo/version
@@@ -1,1 -1,0 +1,1 @@@
- 0.5.1
++0.5.2
diff --cc apps/search_lucene/lib/status.php
index 0000000,0000000..5b243f2
new file mode 100644
--- /dev/null
+++ b/apps/search_lucene/lib/status.php
@@@ -1,0 -1,0 +1,85 @@@
++<?php
++
++
++namespace OCA\Search_Lucene;
++
++/**
++ * @author Jörn Dreyer <jfd at butonic.de>
++ */
++class Status {
++
++ const STATUS_NEW = 'N';
++ const STATUS_INDEXED = 'I';
++ const STATUS_SKIPPED = 'S';
++ const STATUS_ERROR = 'E';
++
++ private $fileId;
++ private $status;
++
++ public function __construct($fileId, $status = null) {
++ $this->fileId = $fileId;
++ $this->status = $status;
++ }
++ public static function fromFileId($fileId) {
++ $status = self::get($fileId);
++ if ($status) {
++ return new Status($fileId, $status);
++ } else {
++ return new Status($fileId, null);
++ }
++ }
++ // always write status to db immediately
++ public function markNew() {
++ $this->status = self::STATUS_NEW;
++ return $this->store();
++ }
++ public function markIndexed() {
++ $this->status = self::STATUS_INDEXED;
++ return $this->store();
++ }
++ public function markSkipped() {
++ $this->status = self::STATUS_SKIPPED;
++ return $this->store();
++ }
++ public function markError() {
++ $this->status = self::STATUS_ERROR;
++ return $this->store();
++ }
++ private function store() {
++ $savedStatus = self::get($this->fileId);
++ if ($savedStatus) {
++ return self::update($this->fileId, $this->status);
++ } else {
++ return self::insert($this->fileId, $this->status);
++ }
++ }
++
++ private static function get($fileId) {
++ $query = \OC_DB::prepare('
++ SELECT `status`
++ FROM `*PREFIX*lucene_status`
++ WHERE `fileid` = ?
++ ');
++ $result = $query->execute(array($fileId));
++ $row = $result->fetchRow();
++ if ($row) {
++ return $row['status'];
++ } else {
++ return null;
++ }
++ }
++ private static function insert($fileId, $status) {
++ $query = \OC_DB::prepare('
++ INSERT INTO `*PREFIX*lucene_status` VALUES (?,?)
++ ');
++ return $query->execute(array($fileId, $status));
++ }
++ private static function update($fileId, $status) {
++ $query = \OC_DB::prepare('
++ UPDATE `*PREFIX*lucene_status`
++ SET `status` = ?
++ WHERE `fileid` = ?
++ ');
++ return $query->execute(array($status, $fileId));
++ }
++}
diff --cc core/skeleton/ownCloudUserManual.pdf
index b68c767,0000000..54ac200
mode 100644,000000..100644
Binary files differ
diff --cc lib/private/util.php
index 38de07a,a73564b..a73564b
mode 100644,100755..100644
--- a/lib/private/util.php
+++ b/lib/private/util.php
diff --cc settings/admin.php
index 0d3868a,c0e4570..c0e4570
mode 100644,100755..100644
--- a/settings/admin.php
+++ b/settings/admin.php
diff --cc version.php
index d61ebb9,3ad77f2..018d81b
--- a/version.php
+++ b/version.php
@@@ -1,6 -1,17 +1,6 @@@
-<?php
-
-// We only can count up. The 4. digit is only for the internal patchlevel to trigger DB upgrades between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel when updating major/minor version number.
-$OC_Version=array(6, 00, 0, 11);
-
-// The human readable string
-$OC_VersionString='6.0 RC3';
-
-// The ownCloud edition
-$OC_Edition='';
-
-// The ownCloud channel
-$OC_Channel='git';
-
-// The build number
-$OC_Build='';
-
+<?php
- $OC_Version = array(6,0,0,10);
- $OC_VersionString = '6.0 RC2';
++$OC_Version = array(6,0,0,11);
++$OC_VersionString = '6.0 RC3';
+$OC_Edition = '';
+$OC_Channel = 'testing';
- $OC_Build = '2013-12-01T23:23:19+00:00';
++$OC_Build = '2013-12-05T11:18:30+00:00';
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/owncloud.git
More information about the Pkg-owncloud-commits
mailing list