[Pkg-owncloud-commits] [owncloud] 25/28: Imported Upstream version 6.0.0~rc4+dfsg

David Prévot taffit at moszumanska.debian.org
Sat Dec 7 02:33:33 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 a48c6bd67d43a81bf08213c0b5330c569427fe51
Merge: 9da0817 734fdbd
Author: David Prévot <taffit at debian.org>
Date:   Fri Dec 6 21:51:43 2013 -0400

    Imported Upstream version 6.0.0~rc4+dfsg

 apps/documents/ajax/otpoll.php                     |    1 +
 apps/documents/ajax/sessionController.php          |   18 +
 apps/documents/appinfo/routes.php                  |    4 +
 apps/documents/css/style.css                       |   19 +-
 apps/documents/css/viewer/webodf.css               |  320 -----
 .../js/3rdparty/webodf/editor/MemberListView.js    |    4 +-
 apps/documents/js/3rdparty/webodf/webodf-debug.js  |  727 +++++------
 apps/documents/js/3rdparty/webodf/webodf.js        | 1270 ++++++++++----------
 apps/documents/js/documents.js                     |  109 +-
 apps/documents/js/viewer/viewer.js                 |    2 +-
 apps/documents/lib/db/op.php                       |   30 +-
 apps/documents/lib/file.php                        |   18 +-
 .../src/patches/MemberListView-OCavatar.patch      |   20 +-
 apps/documents/src/updateWebODF.sh                 |    3 +-
 apps/documents/templates/documents.php             |    2 +-
 apps/files/templates/index.php                     |   19 +-
 apps/files_encryption/hooks/hooks.php              |   51 +-
 apps/files_encryption/lib/util.php                 |   58 +-
 .../templates/settings-personal.php                |    2 +-
 apps/files_sharing/lib/updater.php                 |    8 +-
 apps/files_texteditor/css/style.css                |    1 +
 apps/gallery/js/slideshow.js                       |   10 +-
 apps/user_ldap/lib/ldap.php                        |    2 +-
 core/doc/user/_sources/files/encryption.txt        |   12 +-
 core/doc/user/files/encryption.html                |   12 +-
 core/skeleton/ownCloudUserManual.pdf               |  Bin 1393379 -> 1393288 bytes
 core/templates/installation.php                    |   11 +-
 cron.php                                           |    6 +-
 lib/base.php                                       |    1 -
 lib/private/backgroundjob/job.php                  |   23 +-
 lib/private/backgroundjob/queuedjob.php            |    5 +-
 lib/private/backgroundjob/timedjob.php             |    6 +-
 lib/private/files.php                              |    3 +
 lib/private/files/cache/cache.php                  |    4 +
 lib/private/files/cache/scanner.php                |    2 +-
 lib/public/share.php                               |   35 +-
 version.php                                        |    6 +-
 37 files changed, 1369 insertions(+), 1455 deletions(-)

diff --cc apps/documents/ajax/otpoll.php
index 0d85e49,0000000..e3d7c0a
mode 100644,000000..100644
--- a/apps/documents/ajax/otpoll.php
+++ b/apps/documents/ajax/otpoll.php
@@@ -1,115 -1,0 +1,116 @@@
 +<?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 BadRequestException extends \Exception {
 +
 +	protected $body = "";
 +
 +	public function setBody($body){
 +		$this->body = $body;
 +	}
 +
 +	public function getBody(){
 +		return $this->body;
 +	}
 +}
 +
 +$response = array();
 +
 +try{
 +	$request = new Request();
 +	$esId = $request->getParam('args/es_id');
 +	
 +	$session = new Db_Session();
 +	$sessionData = $session->load($esId)->getData();
 +
 +	try {
 +		$file = new File(@$sessionData['file_id']);
 +	} catch (\Exception $e){
 +		Helper::warnLog('Error. Session no longer exists. ' . $e->getMessage());
 +		$ex = new BadRequestException();
 +		$ex->setBody("{err:'bad request: [" . $request->getRawRequest() . "]'}");
 +		throw $ex;
 +	}
 +	if (!$file->isPublicShare()){
 +		Controller::preDispatch(false);
 +	} else {
 +		Controller::preDispatchGuest(false);
 +	}
 +	
 +	$command = $request->getParam('command');
 +	switch ($command){
 +		case 'sync_ops':
 +			$seqHead = (string) $request->getParam('args/seq_head');
 +			if (!is_null($seqHead)){
 +				$memberId = $request->getParam('args/member_id');
 +				$ops = $request->getParam('args/client_ops');
 +				$hasOps = is_array($ops) && count($ops)>0;
 +
 +				$op = new Db_Op();
 +				$currentHead = $op->getHeadSeq($esId);
 +				
 +				$member = new Db_Member();
 +				try {
 +					$member->updateActivity($memberId);
 +				} catch (\Exception $e){
 +				}
 +
 +				// TODO handle the case ($currentHead == "") && ($seqHead != "")
 +				if ($seqHead == $currentHead) {
 +					// matching heads
 +					if ($hasOps) {
 +						// incoming ops without conflict
 +						// Add incoming ops, respond with a new head
 +						$newHead = Db_Op::addOpsArray($esId, $memberId, $ops);
 +						$response["result"] = 'added';
 +						$response["head_seq"] = $newHead ? $newHead : $currentHead;
 +					} else {
 +						// no incoming ops (just checking for new ops...)
 +						$response["result"] = 'new_ops';
 +						$response["ops"] = array();
 +						$response["head_seq"] = $currentHead;
 +					}
 +				} else { // HEADs do not match
 +					$response["ops"] = $op->getOpsAfterJson($esId, $seqHead);
 +					$response["head_seq"] = $currentHead;
 +					$response["result"] = $hasOps ? 'conflict' : 'new_ops';
 +				}
 +				
 +				$inactiveMembers = $member->updateByTimeout($esId);
 +				foreach ($inactiveMembers as $inactive){
 +					$op->removeCursor($esId, $inactive);
++					$op->removeMember($esId, $inactive);
 +				}
 +			
 +			} else {
 +				// Error - no seq_head passed
 +				throw new BadRequestException();
 +			}
 +
 +			break;
 +		default:
 +			$ex = new BadRequestException();
 +			$ex->setBody("{err:'bad request: [" . $request->getRawRequest() . "]'}");
 +			throw $ex;
 +			break;
 +	}
 +
 +	\OCP\JSON::success($response);
 +} catch (BadRequestException $e){
 +	header('HTTP/1.1 400: BAD REQUEST');
 +	print("");
 +	print($e->getBody());
 +	print("");
 +}
 +exit();
diff --cc apps/documents/ajax/sessionController.php
index 008f1a9,0000000..df2ba10
mode 100644,000000..100644
--- a/apps/documents/ajax/sessionController.php
+++ b/apps/documents/ajax/sessionController.php
@@@ -1,199 -1,0 +1,217 @@@
 +<?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 renameDocument($args){
++		$fileId = intval(@$args['file_id']);
++		$name = @$_POST['name'];
++		$file = new File($fileId);
++		$l = new \OC_L10n('documents');
++
++		if (isset($name) && $file->getPermissions() & \OCP\PERMISSION_UPDATE) {
++			if ($file->renameTo($name)) {
++				// TODO: propagate to other clients
++				\OCP\JSON::success();
++				return;
++			}
++		}
++		\OCP\JSON::error(array(
++			'message' => $l->t('You don\'t have permission to rename this document')
++		));
++	}
++
 +	public static function joinAsUser($args){
 +		$uid = self::preDispatch();
 +		$fileId = intval(@$args['file_id']);
 +		$file = new File($fileId);
 +		
 +		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::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/appinfo/routes.php
index 6ea9b07,0000000..8c4c2d5
mode 100644,000000..100644
--- a/apps/documents/appinfo/routes.php
+++ b/apps/documents/appinfo/routes.php
@@@ -1,103 -1,0 +1,107 @@@
 +<?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.
 + */
 +
 +/**
 + * Document routes
 + */
 +
 +$this->create('documents_documents_create', 'ajax/documents/create')
 +	->post()
 +	->action('\OCA\Documents\DocumentController', 'create')
 +;
 +$this->create('documents_genesis', 'ajax/genesis/{es_id}')
 +	->post()
 +	->action('\OCA\Documents\DocumentController', 'serve')
 +;
 +$this->create('documents_genesis', 'ajax/genesis/{es_id}')
 +	->get()
 +	->action('\OCA\Documents\DocumentController', 'serve')
 +;
 +
 +$this->create('documents_documents_list', 'ajax/documents/list')
 +	->get()
 +	->action('\OCA\Documents\DocumentController', 'listAll')
 +;
 +
 +/**
 + * Session routes
 + */
 +$this->create('documents_session_list', 'ajax/session/list')
 +	->get()
 +	->action('\OCA\Documents\SessionController', 'listAll')
 +;
 +$this->create('documents_session_list', 'ajax/session/list')
 +	->post()
 +	->action('\OCA\Documents\SessionController', 'listAll')
 +;
 +
 +$this->create('documents_session_info', 'ajax/session/info')
 +	->post()
 +	->action('\OCA\Documents\SessionController', 'info')
 +;
 +
 +$this->create('documents_session_listhtml', 'ajax/session/listHtml')
 +	->get()
 +	->action('\OCA\Documents\SessionController', 'listAllHtml')
 +;
 +$this->create('documents_session_listhtml', 'ajax/session/listHtml')
 +	->post()
 +	->action('\OCA\Documents\SessionController', 'listAllHtml')
 +;
 +
 +$this->create('documents_session_joinasuser', 'ajax/session/joinasuser/{file_id}')
 +	->get()
 +	->action('\OCA\Documents\SessionController', 'joinAsUser')
 +;
 +$this->create('documents_session_joinasuser', 'ajax/session/joinasuser/{file_id}')
 +	->post()
 +	->action('\OCA\Documents\SessionController', 'joinAsUser')
 +;
 +$this->create('documents_session_joinasguest', 'ajax/session/joinasguest/{token}')
 +	->get()
 +	->action('\OCA\Documents\SessionController', 'joinAsGuest')
 +;
 +$this->create('documents_session_joinasguest', 'ajax/session/joinasguest/{token}')
 +	->post()
 +	->action('\OCA\Documents\SessionController', 'joinAsGuest')
 +;
++$this->create('documents_session_renamedocument', 'ajax/session/renamedocument/{file_id}')
++	->post()
++	->action('\OCA\Documents\SessionController', 'renameDocument')
++;
 +
 +$this->create('documents_session_save', 'ajax/session/save')
 +	->post()
 +	->action('\OCA\Documents\SessionController', 'save')
 +;
 +
 +/**
 + * User routes
 + */
 +$this->create('documents_user_avatar', 'ajax/user/avatar')
 +	->get()
 +	->action('\OCA\Documents\UserController', 'sendAvatar')
 +;
 +
 +$this->create('documents_user_disconnect', 'ajax/user/disconnect/{member_id}')
 +	->post()
 +	->action('\OCA\Documents\UserController', 'disconnectUser')
 +;
 +
 +$this->create('documents_user_disconnectGuest', 'ajax/user/disconnectGuest/{member_id}')
 +	->post()
 +	->action('\OCA\Documents\UserController', 'disconnectGuest')
 +;
 +
 +$this->create('documents_user_invite', 'ajax/user/invite')
 +	->post()
 +	->action('\OCA\Documents\UserController', 'invite')
 +;
diff --cc apps/documents/css/style.css
index 5146f73,0000000..4eec772
mode 100644,000000..100644
--- a/apps/documents/css/style.css
+++ b/apps/documents/css/style.css
@@@ -1,283 -1,0 +1,300 @@@
 +#editor ::-webkit-scrollbar-thumb {
 +	background-color: #fff;
 +}
 +
 +.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 .progress div{
++	margin-top: 144px;
++	text-align: center;
++}
++
 +.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%;*/
 +}
++#document-title>input {
++	height:9px;
++	margin: 0;
++	padding-top:4px;
++	width: 300px;
++}
++
 +#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;}
++.dojoTabular th,.dojoTabular td {padding: 0.25em 0.5em;}
++
++/* raise notification z-index above the documents app */
++#odf-toolbar + #notification-container {
++	z-index: 501;
++}
diff --cc apps/documents/js/3rdparty/webodf/editor/MemberListView.js
index f9fbb83,0000000..9f604c7
mode 100644,000000..100644
--- a/apps/documents/js/3rdparty/webodf/editor/MemberListView.js
+++ b/apps/documents/js/3rdparty/webodf/editor/MemberListView.js
@@@ -1,212 -1,0 +1,214 @@@
 +/**
 + * @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 */
 +
 +define("webodf/editor/MemberListView",
 +       ["webodf/editor/EditorSession"],
 +
 +  function (EditorSession) {
 +    "use strict";
 +
 +    /**
 +     * @param {!Element} memberListDiv
 +     * @constructor
 +     */
 +    return function MemberListView(memberListDiv) {
 +        var editorSession = null;
 +
 +        runtime.assert(memberListDiv, "memberListDiv unavailable");
 +
 +        /**
 +         * @param {!string} memberId
 +         * @return {undefined}
 +         */
 +        function updateAvatarButton(memberId, memberDetails) {
 +            var node = memberListDiv.firstChild;
 +
 +           // this takes care of incorrectly implemented MemberModels,
 +           // which might end up returning undefined member data
 +           if (!memberDetails) {
 +                runtime.log("MemberModel sent undefined data for member \"" + memberId + "\".");
 +                return;
 +            }
 +
 +            while (node) {
 +                if (node.memberId === memberId) {
 +                    node = node.firstChild;
 +                    while (node) {
 +                        if (node.localName === "img") {
 +                            // update avatar image
 +                            node.src = memberDetails.imageUrl;
 +                            // update border color
 +                            node.style.borderColor = memberDetails.color;
 +						} else if (node.localName === "span" && memberDetails.imageUrl){
- 							$(node).avatar(memberDetails.imageUrl, 60);
++							try {
++								$(node).avatar(memberDetails.imageUrl, 60);
++							} catch (e){}
 +							node.style.borderColor = memberDetails.color;
 +                        } else if (node.localName === "div") {
 +                            node.setAttribute('fullname', memberDetails.fullName);
 +                        }
 +                        node = node.nextSibling;
 +                    }
 +                    return;
 +                }
 +                node = node.nextSibling;
 +            }
 +        }
 +
 +        /**
 +         * @param {!string} memberId
 +         * @return {undefined}
 +         */
 +        function createAvatarButton(memberId) {
 +            var doc = memberListDiv.ownerDocument,
 +                htmlns = doc.documentElement.namespaceURI,
 +                avatarDiv = doc.createElementNS(htmlns, "div"),
 +                imageElement = doc.createElement("span"),
 +                fullnameNode = doc.createElement("div");
 +
 +            avatarDiv.className = "memberListButton";
 +            fullnameNode.className = "memberListLabel";
 +            avatarDiv.appendChild(imageElement);
 +            avatarDiv.appendChild(fullnameNode);
 +            avatarDiv.memberId = memberId; // TODO: namespace?
 +
 +            avatarDiv.onmouseover = function () {
 +                //avatar.getCaret().showHandle();
 +            };
 +            avatarDiv.onmouseout = function () {
 +                //avatar.getCaret().hideHandle();
 +            };
 +            avatarDiv.onclick = function () {
 +                var caret = editorSession.sessionView.getCaret(memberId);
 +                if (caret) {
 +                    //caret.toggleHandleVisibility();
 +                }
 +            };
 +            memberListDiv.appendChild(avatarDiv);
 +        }
 +
 +        /**
 +         * @param {!string} memberId
 +         * @return {undefined}
 +         */
 +        function removeAvatarButton(memberId) {
 +            var node = memberListDiv.firstChild;
 +            while (node) {
 +                if (node.memberId === memberId) {
 +                    memberListDiv.removeChild(node);
 +                    return;
 +                }
 +                node = node.nextSibling;
 +            }
 +        }
 +
 +        /**
 +         * @param {!string} memberId
 +         * @return {undefined}
 +         */
 +        function addMember(memberId) {
 +            var member = editorSession.getMember(memberId),
 +                properties = member.getProperties();
 +            createAvatarButton(memberId);
 +            updateAvatarButton(memberId, properties);
 +        }
 +
 +        /**
 +         * @param {!string} memberId
 +         * @return {undefined}
 +         */
 +        function updateMember(memberId) {
 +            var member = editorSession.getMember(memberId),
 +                properties = member.getProperties();
 +
 +            updateAvatarButton(memberId, properties);
 +        }
 +
 +        /**
 +         * @param {!string} memberId
 +         * @return {undefined}
 +         */
 +        function removeMember(memberId) {
 +            removeAvatarButton(memberId);
 +        }
 +
 +        function disconnectFromEditorSession() {
 +            var node, nextNode;
 +
 +            if (editorSession) {
 +                // unsubscribe from editorSession
 +                editorSession.unsubscribe(EditorSession.signalMemberAdded, addMember);
 +                editorSession.unsubscribe(EditorSession.signalMemberUpdated, updateMember);
 +                editorSession.unsubscribe(EditorSession.signalMemberRemoved, removeMember);
 +                // remove all current avatars
 +                node = memberListDiv.firstChild;
 +                while (node) {
 +                    nextNode = node.nextSibling;
 +                    memberListDiv.removeChild(node);
 +                    node = nextNode;
 +                }
 +            }
 +        }
 +
 +        /**
 +         * @param {!EditorSession} session
 +         * @return {undefined}
 +         */
 +        this.setEditorSession = function(session) {
 +            disconnectFromEditorSession();
 +
 +            editorSession = session;
 +            if (editorSession) {
 +                editorSession.subscribe(EditorSession.signalMemberAdded, addMember);
 +                editorSession.subscribe(EditorSession.signalMemberUpdated, updateMember);
 +                editorSession.subscribe(EditorSession.signalMemberRemoved, removeMember);
 +            }
 +        };
 +
 +        /**
 +         * @param {!function(!Object=)} callback, passing an error object in case of error
 +         * @return {undefined}
 +         */
 +        this.destroy = function (callback) {
 +            disconnectFromEditorSession();
 +            callback();
 +        };
 +    };
 +});
diff --cc apps/documents/js/3rdparty/webodf/webodf-debug.js
index 0781352,0000000..4bb2eff
mode 100644,000000..100644
--- a/apps/documents/js/3rdparty/webodf/webodf-debug.js
+++ b/apps/documents/js/3rdparty/webodf/webodf-debug.js
@@@ -1,18164 -1,0 +1,18193 @@@
- var webodf_version = "0.4.2-1556-gf8a94ee";
++var webodf_version = "0.4.2-1579-gfc3a4e6";
 +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 = 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 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, 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 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 = null;
 +    try {
 +      xmlDocument = builder.parse(file)
 +    }catch(err) {
 +      print(err);
 +      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.", null)
 +    }else {
 +      data = readFile(path, rhinoencoding);
 +      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), 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, 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) {
 +    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
 +  }
 +}
 +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 dependencies = {}, loadedFiles = {};
 +  function loadManifest(dir, manifests) {
 +    var path = dir + "/manifest.json", content, list, manifest, m;
 +    if(loadedFiles.hasOwnProperty(path)) {
 +      return
 +    }
 +    loadedFiles[path] = 1;
 +    try {
 +      content = runtime.readFileSync(path, "utf-8")
 +    }catch(e) {
 +      console.log(String(e));
 +      return
 +    }
 +    list = JSON.parse((content));
 +    manifest = (list);
 +    for(m in manifest) {
 +      if(manifest.hasOwnProperty(m)) {
 +        manifests[m] = {dir:dir, deps:manifest[m]}
 +      }
 +    }
 +  }
 +  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)
 +      }
 +    });
 +    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)
 +          }
 +        }
 +        stack.pop();
 +        sorted.push(path)
 +      }
 +    }
 +    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)
 +      }
 +    }
 +    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])
 +      }
 +    }
 +    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
 +      }
 +      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))
 +      }
 +    }
 +    evalArray(paths, contents)
 +  }
 +  runtime.loadClass = function(classname) {
 +    if(IS_COMPILED_CODE) {
 +      return
 +    }
 +    var classpath = classPath(classname), paths;
 +    if(loadedFiles.hasOwnProperty(classpath)) {
 +      return
 +    }
 +    loadManifests();
 +    paths = getDependencies(classname);
 +    loadFiles(paths)
 +  }
 +})();
 +(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));
 +        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.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.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)
 +  }
 +};
 +/*
 +
 + 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
 +  }
 +  core.DomUtils = function DomUtils() {
 +    var sharedRange = null;
 +    function getSharedRange(doc) {
 +      var range;
 +      if(sharedRange) {
 +        range = sharedRange
 +      }else {
 +        sharedRange = range = (doc.createRange())
 +      }
 +      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
 +        }
 +      }else {
 +        while(c.lastChild) {
 +          c = c.lastChild;
 +          offset = c.nodeType === Node.TEXT_NODE ? c.textContent.length : c.childNodes.length
 +        }
 +      }
 +      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)
 +          }
 +        }
 +      }
 +      return modifiedNodes
 +    }
 +    this.splitBoundaries = splitBoundaries;
 +    function containsRange(container, insideRange) {
 +      return container.compareBoundaryPoints(Range.START_TO_START, insideRange) <= 0 && container.compareBoundaryPoints(Range.END_TO_END, insideRange) >= 0
 +    }
 +    this.containsRange = containsRange;
 +    function rangesIntersect(range1, range2) {
 +      return range1.compareBoundaryPoints(Range.END_TO_START, range2) <= 0 && range1.compareBoundaryPoints(Range.START_TO_END, range2) >= 0
 +    }
 +    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()
 +      }
 +      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
 +        }
 +      }
 +      return mergedNode
 +    }
 +    function normalizeTextNodes(node) {
 +      if(node && node.nextSibling) {
 +        node = mergeTextNodes(node, node.nextSibling)
 +      }
 +      if(node && node.previousSibling) {
 +        mergeTextNodes(node.previousSibling, node)
 +      }
 +    }
 +    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
 +    }
 +    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
 +    }
 +    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
 +    }
 +    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
 +    }
 +    function comparePoints(c1, o1, c2, o2) {
 +      if(c1 === c2) {
 +        return o2 - o1
 +      }
 +      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
 +          }
 +        }
 +      }
 +      return comparison
 +    }
 +    this.comparePoints = comparePoints;
 +    function adaptRangeDifferenceToZoomLevel(inputNumber, zoomLevel) {
 +      if(getBrowserQuirks().unscaledRangeClientRects) {
 +        return inputNumber
 +      }
 +      return inputNumber / zoomLevel
 +    }
 +    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()
 +        }
 +      }
 +      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
 +        }else {
 +          runtime.log("Key ignored: " + key)
 +        }
 +      })
 +    }
 +    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
 +    }
 +    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))
 +          }
 +        }
 +      })
 +    }
 +    this.mapObjOntoNode = mapObjOntoNode;
 +    function init(self) {
 +      var appVersion, webKitOrSafari, ie, window = runtime.getWindow();
 +      if(window === null) {
 +        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
 +      }
 +    }
 +    init(this)
 +  };
 +  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)
 +    }
 +  };
 +  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.')
 +  };
 +  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!";
 +      }
 +    }
 +    if(maxChecks > 0) {
 +      checks += 1;
 +      if(checks > maxChecks) {
 +        runtime.log("alert", "watchdog loop overflow");
 +        throw"loop overflow";
 +      }
 +    }
 +  }
 +  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
 +    }
 +  }
 +  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.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
 +      }
 +    }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
 +          }
 +        }
 +      }
 +    }
 +    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(walker.lastChild() !== null) {
 +          setAtEnd()
 +        }else {
 +          if(currentNode === root) {
 +            moved = false
 +          }else {
 +            currentPos = 0
 +          }
 +        }
 +      }
 +    }
 +    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
 +      }
 +    }else {
 +      if(nodeType === ELEMENT_NODE && currentPos === 1) {
 +        n = null
 +      }
 +    }
 +    return n
 +  };
 +  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
 +        }
 +      }
 +    }
 +    return n
 +  };
 +  this.getCurrentNode = function() {
 +    var n = (walker.currentNode);
 +    return n
 +  };
 +  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
 +      }
 +      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
 +    }
 +  }
 +  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
 +    }
 +    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) {
 +      y -= c[j];
 +      if(y < 0) {
 +        this.status = 2;
 +        this.m = mm;
 +        return
 +      }
 +    }
 +    y -= c[i];
 +    if(y < 0) {
 +      this.status = 2;
 +      this.m = mm;
 +      return
 +    }
 +    c[i] += y;
 +    x[1] = j = 0;
 +    p = c;
 +    pidx = 1;
 +    xp = 2;
 +    while(--i > 0) {
 +      j += p[pidx++];
 +      x[xp++] = j
 +    }
 +    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;
 +    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 = 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) {
 +              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 core.zip_HuftNode
 +          }
 +          if(tail === null) {
 +            tail = this.root = new core.zip_HuftList
 +          }else {
 +            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].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].t = r.t
 +        }
 +        for(j = 1 << k - 1;(i & j) !== 0;j >>= 1) {
 +          i ^= j
 +        }
 +        i ^= j;
 +        while((i & (1 << w) - 1) !== x[h]) {
 +          w -= lx[h];
 +          h--
 +        }
 +      }
 +    }
 +    this.m = lx[1];
 +    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++]
 +  }
 +  function zip_NEEDBITS(n) {
 +    while(zip_bit_len < n) {
 +      zip_bit_buf |= zip_GET_BYTE() << zip_bit_len;
 +      zip_bit_len += 8
 +    }
 +  }
 +  function zip_GETBITS(n) {
 +    return zip_bit_buf & zip_MASK_BITS[n]
 +  }
 +  function zip_DUMPBITS(n) {
 +    zip_bit_buf >>= n;
 +    zip_bit_len -= n
 +  }
 +  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) {
 +          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) {
 +        zip_wp &= zip_WSIZE - 1;
 +        buff[off + n++] = zip_slide[zip_wp++] = t.n;
 +        if(n === size) {
 +          return size
 +        }
 +      }else {
 +        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
 +          }
 +          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
 +  }
 +  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)) {
 +      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) {
 +      zip_method = -1
 +    }
 +    return n
 +  }
 +  var zip_fixed_bd;
 +  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 = 144;i < 256;i++) {
 +        l[i] = 9
 +      }
 +      for(i = 256;i < 280;i++) {
 +        l[i] = 7
 +      }
 +      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) {
 +        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);
 +      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)
 +  }
 +  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 = 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) {
 +      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) {
 +          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) {
 +            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.status = 1
 +    }
 +    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);
 +    zip_td = h.root;
 +    zip_bd = h.m;
 +    if(zip_bd === 0 && nl > 257) {
 +      return-1
 +    }
 +    if(h.status !== 0) {
 +      return-1
 +    }
 +    return zip_inflate_codes(buff, off, size)
 +  }
 +  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
 +  }
 +  function zip_inflate_internal(buff, off, size) {
 +    var n = 0, i;
 +    while(n < size) {
 +      if(zip_eof && zip_method === -1) {
 +        return n
 +      }
 +      if(zip_copy_leng > 0) {
 +        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];
 +            n += 1;
 +            zip_wp += 1;
 +            zip_copy_dist += 1
 +          }
 +        }else {
 +          while(zip_copy_leng > 0 && n < size) {
 +            zip_copy_leng -= 1;
 +            zip_wp &= zip_WSIZE - 1;
 +            zip_NEEDBITS(8);
 +            buff[off + n] = zip_slide[zip_wp] = zip_GETBITS(8);
 +            n += 1;
 +            zip_wp += 1;
 +            zip_DUMPBITS(8)
 +          }
 +          if(zip_copy_leng === 0) {
 +            zip_method = -1
 +          }
 +        }
 +        if(n === size) {
 +          return n
 +        }
 +      }
 +      if(zip_method === -1) {
 +        if(zip_eof) {
 +          break
 +        }
 +        zip_NEEDBITS(1);
 +        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) {
 +            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) {
 +            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(zip_eof) {
 +          return 0
 +        }
 +        return-1
 +      }
 +      n += i
 +    }
 +    return n
 +  }
 +  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 = new Uint8Array(new ArrayBuffer(0));
 +    return buff
 +  }
 +  this.inflate = zip_inflate
 +};
 +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
 +    }
 +    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)
 +  }
 +  function areNodesEqual(a, b) {
 +    var an, bn, atype = a.nodeType, btype = b.nodeType;
 +    if(atype !== btype) {
 +      testFailed("Nodetype '" + atype + "' should be '" + btype + "'");
 +      return false
 +    }
 +    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
 +  }
 +  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 false
 +  }
 +  function stringify(v) {
 +    if(v === 0 && 1 / v < 0) {
 +      return"-0"
 +    }
 +    return String(v)
 +  }
 +  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 {
 +        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 + ").")
 +        }
 +      }
 +    }
 +  }
 +  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 {
 +        testFailed(a + " should be non-null. Was " + av)
 +      }
 +    }
 +  }
 +  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 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}
 +    }
 +    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
 +    }
 +    if(inBrowser) {
 +      runtime.log("<span>Running " + link(testName, 'runSuite("' + testName + '");') + ": " + test.description() + "</span>")
 +    }else {
 +      runtime.log("Running " + testName + ": " + test.description)
 +    }
 +    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
 +      }
 +      if(inBrowser) {
 +        runtime.log("<span>Running " + link(tname, 'runTest("' + testName + '","' + tname + '")') + "</span>")
 +      }else {
 +        runtime.log("Running " + tname)
 +      }
 +      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
 +      }
 +      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))
 +      })
 +    }
 +    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
 +    }
 +    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.";
 +      }
 +      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 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
 +    }
 +    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
 +      }
 +      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)
 +      }
 +      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
 +      }
 +      entry.data = data;
 +      callback(null, data)
 +    }
 +    function load(callback) {
 +      if(entry.data !== null) {
 +        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)
 +        }
 +      })
 +    }
 +    this.load = load;
 +    function set(filename, data, compressed, date) {
 +      entry.filename = filename;
 +      entry.data = data;
 +      entry.compressed = compressed;
 +      entry.date = date
 +    }
 +    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");
 +    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
 +      }
 +      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
 +      }
 +    }
 +    if(entry) {
 +      if(entry.data) {
 +        callback(null, entry.data)
 +      }else {
 +        entry.load(callback)
 +      }
 +    }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
 +      }
 +      callback(null, dataurl)
 +    })
 +  }
 +  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 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 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
 +      }
 +    }
 +    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
 +    }
 +    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()
 +  };
 +  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.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() {
 +    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) 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 = {}
 +  };
 +  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
 +      }
 +    }
 +  }
 +};
 +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"};
++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", metans:"urn:oasis:names:tc:opendocument:xmlns:meta:1.0", numberns:"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0", officens:"urn:oasis:names:tc [...]
++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"};
 +(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])
 +    }
 +  }
 +};
 +odf.Namespaces.lookupNamespaceURI = function lookupNamespaceURI(prefix) {
 +  var r = null;
 +  if(odf.Namespaces.namespaceMap.hasOwnProperty(prefix)) {
 +    r = (odf.Namespaces.namespaceMap[prefix])
 +  }
 +  return r
 +};
 +odf.Namespaces.lookupPrefix = function lookupPrefix(namespaceURI) {
 +  var map = odf.Namespaces.prefixMap;
 +  return map.hasOwnProperty(namespaceURI) ? map[namespaceURI] : null
 +};
 +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
 +  }
 +  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")))
 +  }
 +  this.isCharacterFrame = isCharacterFrame;
++  function isAnnotation(e) {
++    var name = e && e.localName;
++    return name === "annotation" && e.namespaceURI === odf.Namespaces.officens
++  }
++  function isAnnotationWrapper(e) {
++    var name = e && e.localName;
++    return name === "div" && (e).className === "annotationWrapper"
++  }
++  function isInlineRoot(e) {
++    return isAnnotation(e) || isAnnotationWrapper(e)
++  }
++  this.isInlineRoot = isInlineRoot;
 +  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
 +    }
 +    return node
 +  }
 +  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 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)
 +  }
 +  this.isODFWhitespace = isODFWhitespace;
 +  function isGroupingElement(n) {
 +    if(n === null || n.nodeType !== Node.ELEMENT_NODE) {
 +      return false
 +    }
 +    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)
 +      }
 +    }
 +    return r
 +  }
 +  this.isCharacterElement = isCharacterElement;
++  function isAnchoredAsCharacterElement(e) {
++    return isCharacterElement(e) || (isCharacterFrame(e) || isInlineRoot(e))
++  }
++  this.isAnchoredAsCharacterElement = isAnchoredAsCharacterElement;
 +  function isSpaceElement(e) {
 +    var n = e && e.localName, ns, r = false;
 +    if(n) {
 +      ns = e.namespaceURI;
 +      if(ns === textns) {
 +        r = n === "s"
 +      }
 +    }
 +    return r
 +  }
 +  this.isSpaceElement = isSpaceElement;
 +  function firstChild(node) {
 +    while(node.firstChild !== null && isGroupingElement(node)) {
 +      node = node.firstChild
 +    }
 +    return node
 +  }
 +  this.firstChild = firstChild;
 +  function lastChild(node) {
 +    while(node.lastChild !== null && isGroupingElement(node)) {
 +      node = node.lastChild
 +    }
 +    return node
 +  }
 +  this.lastChild = lastChild;
 +  function previousNode(node) {
 +    while(!isParagraph(node) && node.previousSibling === null) {
 +      node = (node.parentNode)
 +    }
 +    return isParagraph(node) ? null : lastChild((node.previousSibling))
 +  }
 +  this.previousNode = previousNode;
 +  function nextNode(node) {
 +    while(!isParagraph(node) && node.nextSibling === null) {
 +      node = (node.parentNode)
 +    }
 +    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(isCharacterElement(node)) {
++        if(isAnchoredAsCharacterElement(node)) {
 +          r = isSpaceElement(node) === false;
 +          node = null
 +        }else {
 +          node = previousNode(node)
 +        }
 +      }
 +    }
 +    return r
 +  }
 +  this.scanLeftForNonSpace = scanLeftForNonSpace;
 +  function lookLeftForCharacter(node) {
 +    var text, r = 0, tl = 0;
 +    if(node.nodeType === Node.TEXT_NODE) {
 +      tl = (node).length
 +    }
 +    if(tl > 0) {
 +      text = (node).data;
 +      if(!isODFWhitespace(text.substr(tl - 1, 1))) {
 +        r = 1
 +      }else {
 +        if(tl === 1) {
 +          r = scanLeftForNonSpace(previousNode(node)) ? 2 : 0
 +        }else {
 +          r = isODFWhitespace(text.substr(tl - 2, 1)) ? 0 : 2
 +        }
 +      }
 +    }else {
-       if(isCharacterElement(node)) {
++      if(isAnchoredAsCharacterElement(node)) {
 +        r = 1
 +      }
 +    }
 +    return r
 +  }
 +  this.lookLeftForCharacter = lookLeftForCharacter;
 +  function lookRightForCharacter(node) {
 +    var r = false, l = 0;
 +    if(node && node.nodeType === Node.TEXT_NODE) {
 +      l = (node).length
 +    }
 +    if(l > 0) {
 +      r = !isODFWhitespace((node).data.substr(0, 1))
 +    }else {
-       if(isCharacterElement(node)) {
++      if(isAnchoredAsCharacterElement(node)) {
 +        r = true
 +      }
 +    }
 +    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 {
 +        l = 0
 +      }
 +      if(l > 0 && !isODFWhitespace((node).data)) {
 +        r = true;
 +        break
 +      }
-       if(isCharacterElement(node)) {
++      if(isAnchoredAsCharacterElement(node)) {
 +        r = true;
 +        break
 +      }
 +      node = previousNode(node)
 +    }
 +    return r
 +  }
 +  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
 +      }
 +      if(l > 0 && !isODFWhitespace((node).data)) {
 +        r = true;
 +        break
 +      }
-       if(isCharacterElement(node)) {
++      if(isAnchoredAsCharacterElement(node)) {
 +        r = true;
 +        break
 +      }
 +      node = nextNode(node)
 +    }
 +    return r
 +  }
 +  this.scanRightForAnyCharacter = scanRightForAnyCharacter;
 +  function isTrailingWhitespace(textnode, offset) {
 +    if(!isODFWhitespace(textnode.data.substr(offset))) {
 +      return false
 +    }
 +    return!scanRightForAnyCharacter(nextNode(textnode))
 +  }
 +  this.isTrailingWhitespace = isTrailingWhitespace;
 +  function isSignificantWhitespace(textNode, offset) {
 +    var text = textNode.data, result;
 +    if(!isODFWhitespace(text[offset])) {
 +      return false
 +    }
-     if(isCharacterElement(textNode.parentNode)) {
++    if(isAnchoredAsCharacterElement(textNode.parentNode)) {
 +      return false
 +    }
 +    if(offset > 0) {
 +      if(!isODFWhitespace(text[offset - 1])) {
 +        result = true
 +      }
 +    }else {
 +      if(scanLeftForNonSpace(previousNode(textNode))) {
 +        result = 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 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 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)
 +      }
 +    }
 +    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
 +  }
 +  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(domUtils.rangesIntersect(range, nodeRange)) {
 +          if(isAcceptedNode(node)) {
 +            return NodeFilter.FILTER_SKIP
 +          }
 +        }
 +      }
 +      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
 +      }
 +      if(node.nodeType === Node.TEXT_NODE) {
 +        if(includeNode(range, nodeRange, includePartial)) {
 +          if(includeInsignificantWhitespace || isSignificantTextContent((node))) {
 +            return NodeFilter.FILTER_ACCEPT
 +          }
 +        }
 +      }else {
-         if(isCharacterElement(node)) {
++        if(isAnchoredAsCharacterElement(node)) {
 +          if(includeNode(range, nodeRange, includePartial)) {
 +            return NodeFilter.FILTER_ACCEPT
 +          }
 +        }else {
 +          if(isAcceptedNode(node) || isGroupingElement(node)) {
 +            return NodeFilter.FILTER_SKIP
 +          }
 +        }
 +      }
 +      return NodeFilter.FILTER_REJECT
 +    }
 +    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
 +        }
 +      }else {
 +        if(isAcceptedNode(node) || isGroupingElement(node)) {
 +          return NodeFilter.FILTER_SKIP
 +        }
 +      }
 +      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
 +      }
 +      return NodeFilter.FILTER_SKIP
 +    }
 +    elements = domUtils.getNodesInRange(range, nodeFilter);
 +    nodeRange.detach();
 +    return elements
 +  }
 +};
 +/*
 +
 + 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) {
 +};
 +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
 +        }
 +      }
 +    }
 +    steps.push({location:location, predicates:predicates});
 +    return pos
 +  }
 +  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}
 +  }
 +  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
 +  };
 +  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
 +    }
 +  }
 +  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
 +    }
 +  }
 +  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
 +        }
 +      }
 +      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()
 +      }
 +      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() !== null
 +      })
 +    }
 +    return new ConditionIterator(it, function(node) {
 +      nit.setNode(node);
 +      pit.reset();
 +      var n = pit.next();
 +      return n ? n.nodeValue === value : false
 +    })
 +  }
 +  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 {
 +        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)
 +            }
 +          }
 +        }
 +      }
 +      for(j = 0;j < step.predicates.length;j += 1) {
 +        p = item(step.predicates, j);
 +        it = createPredicateFilteredIterator(it, p, namespaceResolver)
 +      }
 +    }
 +    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()
 +    }
 +    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()
 +      }
 +    }
 +    return elements
 +  }
 +  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)
 +      }
 +    }
 +  }
 +  function removeNode(node) {
 +    if(node.parentNode) {
 +      recentlyModifiedNodes.push(node.previousSibling);
 +      recentlyModifiedNodes.push(node.nextSibling);
 +      node.parentNode.removeChild(node)
 +    }
 +  }
 +  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))
 +      }
 +    }
 +    recentlyModifiedNodes.push(node.previousSibling);
 +    recentlyModifiedNodes.push(node.nextSibling)
 +  }
 +  function getStartNode() {
 +    return forwardSelection ? anchorNode : cursorNode
 +  }
 +  function getEndNode() {
 +    return forwardSelection ? cursorNode : anchorNode
 +  }
 +  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 selectedRange
 +  };
 +  this.setSelectedRange = function(range, isForwardSelection) {
 +    if(selectedRange && selectedRange !== range) {
 +      selectedRange.detach()
 +    }
 +    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)
 +    }
 +    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)
 +  }
 +  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
 +        }
 +      }
 +    }
 +    return FILTER_ACCEPT
 +  };
 +  this.addFilter = function(filterName, filterInstance) {
 +    filterChain[filterName] = filterInstance
 +  };
 +  this.removeFilter = function(filterName) {
 +    delete filterChain[filterName]
 +  }
 +};
 +/*
 +
 + 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)
 +    }
 +  }
 +  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)
 +      })
 +    }
 +    range.detach()
 +  }
 +  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)
 +      }
 +      container.parentNode.removeChild(container)
 +    }
 +  }
 +  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 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)"
 +  }
 +  function showAnnotationsPane(show) {
 +    var sizer = canvas.getSizer();
 +    if(show) {
 +      annotationsPane.style.display = "inline-block";
 +      sizer.style.paddingRight = window.getComputedStyle(annotationsPane).width
 +    }else {
 +      annotationsPane.style.display = "none";
 +      sizer.style.paddingRight = 0
 +    }
 +    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])
 +    }
 +  }
 +  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()
 +  }
 +  this.addAnnotation = addAnnotation;
 +  function forgetAnnotation(annotation) {
 +    var index = annotations.indexOf(annotation);
 +    unwrapAnnotation(annotation);
 +    unhighlightAnnotation(annotation);
 +    if(index !== -1) {
 +      annotations.splice(index, 1)
 +    }
 +    if(annotations.length === 0) {
 +      showAnnotationsPane(false)
 +    }
 +  }
 +  function forgetAnnotations() {
 +    while(annotations.length) {
 +      forgetAnnotation(annotations[0])
 +    }
 +  }
 +  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 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)
 +    }
 +    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(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)
 +            }
 +          }
 +        }
 +      }
 +    }
 +    runtime.assert(Boolean(rectangle), "No visible rectangle found");
 +    return(rectangle)
 +  }
 +  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(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)
 +    }
 +    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
 +    }
 +    runtime.clearTimeout(timeoutHandle);
 +    timeoutHandle = runtime.setTimeout(function() {
 +      cachedXOffset = undefined
 +    }, 2E3);
 +    range.detach();
 +    return positions - left
 +  }
 +  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 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
 +      }
 +    }
 +    return positions
 +  }
 +  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 stepsFilter2
 +  }
 +  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
 +        }
 +      }
 +    }
 +    return stepsFilter2
 +  }
 +  function countStepsPublic(steps, filter) {
 +    var iterator = getIteratorAtCursor();
 +    return countSteps(iterator, steps, filter)
 +  }
 +  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 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
 +    }
 +    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(bestContainer !== null) {
 +      iterator.setUnfilteredPosition(bestContainer, (bestOffset));
 +      steps = bestCount
 +    }else {
 +      steps = 0
 +    }
 +    range.detach();
 +    return steps
 +  }
 +  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 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
 +    }
 +    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
 +      }
 +    }
 +    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()
 +    }
 +    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()
 +    }
 +    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
 +        }
 +      }
 +    }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
 +  }
 +  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)
 +  }
 +  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
 +    }
 +  }
 +  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)
-     }
-     if(removedProperties) {
-       removedProperties.forEach(function(name) {
-         delete metadata[name]
-       });
-       domUtils.removeKeyElementsFromNode(metaElement, removedProperties, odf.Namespaces.lookupNamespaceURI)
-     }
-   }
-   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) 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
 +  }
 +};
 +/*
 +
 + 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 {
 +          if(node.namespaceURI === stylens && (node.localName === "page-layout" || node.localName === "default-page-layout")) {
 +            family = "page"
 +          }else {
 +            family = undefined
 +          }
 +        }
 +      }
 +      if(family) {
 +        name = node.getAttributeNS(stylens, "name");
 +        if(!name) {
 +          name = ""
 +        }
 +        if(stylemap.hasOwnProperty(family)) {
 +          style = stylemap[family]
 +        }else {
 +          stylemap[family] = style = {}
 +        }
 +        style[name] = node
 +      }
 +      node = node.nextElementSibling
 +    }
 +    return stylemap
 +  }
 +  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
 +        }
 +      }
 +    }
 +    return style
 +  }
 +  function addStyleToStyleTree(stylename, stylesmap, stylestree) {
 +    var style, parentname, parentstyle;
 +    if(!stylesmap.hasOwnProperty(stylename)) {
 +      return null
 +    }
 +    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 {
 +      stylestree[stylename] = style
 +    }
 +    delete stylesmap[stylename];
 +    return style
 +  }
 +  function addStyleMapToStyleTree(stylesmap, stylestree) {
 +    var name;
 +    for(name in stylesmap) {
 +      if(stylesmap.hasOwnProperty(name)) {
 +        addStyleToStyleTree(name, stylesmap, stylestree)
 +      }
 +    }
 +  }
 +  function createSelector(family, name) {
 +    var prefix = familynamespaceprefixes[family], namepart, selector;
 +    if(prefix === undefined) {
 +      return null
 +    }
 +    if(name) {
 +      namepart = "[" + prefix + '|style-name="' + name + '"]'
 +    }else {
 +      namepart = ""
 +    }
 +    if(prefix === "presentation") {
 +      prefix = "draw";
 +      if(name) {
 +        namepart = '[presentation|style-name="' + name + '"]'
 +      }else {
 +        namepart = ""
 +      }
 +    }
 +    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)
 +    }
 +    for(n in derivedStyles) {
 +      if(derivedStyles.hasOwnProperty(n)) {
 +        ss = getSelectors(family, n, derivedStyles[n]);
 +        selectors = selectors.concat(ss)
 +      }
 +    }
 +    return selectors
 +  }
 +  function getDirectChild(node, ns, name) {
 +    var e = node && node.firstElementChild;
 +    while(e) {
 +      if(e.namespaceURI === ns && e.localName === name) {
 +        break
 +      }
 +      e = e.nextElementSibling
 +    }
 +    return e
 +  }
 +  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 = ""
 +    }
 +    width = utils.parseLength(width);
 +    if(width && (width.unit === "pt" && width.value < 0.75)) {
 +      value = "0.75pt" + theRestOfBorderAttributes
 +    }
 +    return value
 +  }
 +  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)
 +        }
 +        if(r[2]) {
 +          rule += r[2] + ":" + value + ";"
 +        }
 +      }
 +    }
 +    return rule
 +  }
 +  function getFontSize(styleNode) {
 +    var props = getDirectChild(styleNode, stylens, "text-properties");
 +    if(props) {
 +      return utils.parseFoFontSize(props.getAttributeNS(fons, "font-size"))
 +    }
 +    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 {
 +      xp = "//style:default-style[@style:family='" + parentStyleFamily + "']"
 +    }
 +    parentStyleNode = xpath.getODFElementsWithXPath((odfRoot), xp, odf.Namespaces.lookupNamespaceURI)[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
 +    }
 +    fontName = props.getAttributeNS(stylens, "font-name") || props.getAttributeNS(fons, "font-family");
 +    if(fontName) {
 +      value = fontFaceDeclsMap[fontName];
 +      rule += "font-family: " + (value || fontName) + ";"
 +    }
 +    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)
 +    }
 +    if(!fontSizeRule) {
 +      fontSizeRule = "font-size: " + parseFloat(defaultFontSize) * sizeMultiplier + cssUnits.getUnits(defaultFontSize) + ";"
 +    }
 +    rule += fontSizeRule;
 +    return rule
 +  }
 +  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)
 +      }
 +    }
 +    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 rule
 +  }
 +  function matchToRgb(m, r, g, b) {
 +    return r + r + g + g + b + b
 +  }
 +  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 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 + ");"
 +        }
 +      }else {
 +        rule += "background: none;"
 +      }
 +    }else {
 +      if(fill === "none") {
 +        rule += "background: none;"
 +      }
 +    }
 +    return rule
 +  }
 +  function getDrawingPageProperties(props) {
 +    var rule = "";
 +    rule += applySimpleMapping(props, graphicPropertySimpleMapping);
 +    if(props.getAttributeNS(presentationns, "background-visible") === "true") {
 +      rule += "background: none;"
 +    }
 +    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;"
 +      }
 +    }
 +    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)
 +    }
 +    properties = getDirectChild(node.element, stylens, "paragraph-properties");
 +    if(properties) {
 +      rule += getParagraphProperties(properties)
 +    }
 +    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 {
 +      if(style) {
 +        content += ' "' + style + '"'
 +      }else {
 +        content += " ''"
 +      }
 +    }
 +    return"content:" + content + ' "' + suffix + '"'
 +  }
 +  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")
 +    }
 +    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)
 +      }
 +    }
 +    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)
 +    }
 +  }
 +  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
 +      }
 +    }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 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
 +    }
 +  }
 +  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)
 +      }
 +    }
 +  }
 +  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])
 +      }
 +    }
 +  }
 +  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])
 +          }
 +        }
 +      }
 +    }
 +  }
 +};
 +/*
 +
 + 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
 +    }
 +    return false
 +  }
 +  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
 +      }
 +    }
 +    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)
 +      }
 +    }
 +    e = element.firstElementChild;
 +    while(e) {
 +      prefixUsedStyleNames(e, prefix);
 +      e = e.nextElementSibling
 +    }
 +  }
 +  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
 +      }
 +    }
 +    if(ns) {
 +      styleElement.setAttributeNS(ns, nsprefixes[ns] + "name", prefix + stylename)
 +    }
 +  }
 +  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)
 +      }
 +    }
 +  }
 +  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
 +      }
 +    }
 +    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
 +    }
 +  }
 +  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 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
 +      }
 +      removeRegExpFromUsedStyleNames(styleElementsRoot, regExp);
 +      if(styleUsingElementsRoot) {
 +        removeRegExpFromUsedStyleNames(styleUsingElementsRoot, regExp)
 +      }
 +    }
 +  }
 +  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
 +      }
 +    }
 +    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
 +        }
 +      }
 +    }
 +    return usedStyles
 +  }
 +  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
 +    }
 +  }
 +  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(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
 +        }
 +      }
 +    }
 +    e = element.firstElementChild;
 +    while(e) {
 +      determineDependentStyles(e, styleScope, knownStyles);
 +      e = e.nextElementSibling
 +    }
 +    return knownStyles
 +  }
 +  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})
 +        }
 +      }
 +    }
 +    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, 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
 +      }
 +    }
 +    e = styleElement && styleElement.firstElementChild;
 +    while(e) {
 +      currentElement = e;
 +      localNames.forEach(collectByAttribute);
 +      collectUsedFontFaces(usedFontFaceDeclMap, currentElement);
 +      e = e.nextElementSibling
 +    }
 +  }
 +  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])
 +      }
 +    }
 +    e = styleElement && styleElement.firstElementChild;
 +    while(e) {
 +      currentElement = e;
 +      localNames.forEach(changeFontFaceNameByAttribute);
 +      changeFontFaceNames(currentElement, fontFaceNameChangeMap);
 +      e = e.nextElementSibling
 +    }
 +  }
 +  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.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/
 +*/
 +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 {
 +        if(nodeType === Node.TEXT_NODE && node.textContent) {
 +          s += node.textContent
 +        }
 +      }
 +    }
 +    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/
 +*/
 +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) {
++      if(odfUtils.isInlineRoot(leftNode) && odfUtils.isGroupingElement(rightNode)) {
++        return FILTER_REJECT
++      }
 +      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
 +  }
 +  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 {
 +      if(!odfUtils.isGroupingElement(container) || odfUtils.isWithinTrackedChanges(container, getRootNode())) {
 +        r = FILTER_REJECT
 +      }else {
 +        leftNode = iterator.leftNode();
 +        rightNode = iterator.rightNode();
 +        r = checkLeftRight(container, leftNode, rightNode)
 +      }
 +    }
 +    return r
 +  }
 +};
 +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
 +        }
 +      }
 +      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 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) {
 +      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)
 +        }
 +      }
 +    }
 +    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 + '"'
 +          }
 +        }
 +      }
 +    }
 +    s += attstr + ">";
 +    return s
 +  }
 +  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)
 +    }
 +    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(qname) {
 +      s += "</" + qname + ">";
 +      ns.pop()
 +    }
 +    return s
 +  }
 +  this.filter = null;
 +  this.writeToString = function(node, nsmap) {
 +    if(!node) {
 +      return""
 +    }
 +    var ns = new Namespaces(nsmap);
 +    return serializeNode(ns, node)
 +  }
 +};
 +/*
 +
 + 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
 +    }
 +    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
 +  };
 +  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.Base64");
 +runtime.loadClass("core.Zip");
++runtime.loadClass("core.DomUtils");
 +runtime.loadClass("xmldom.LSSerializer");
 +runtime.loadClass("odf.StyleInfo");
 +runtime.loadClass("odf.Namespaces");
 +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";
++  var styleInfo = new odf.StyleInfo, domUtils = new core.DomUtils, 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  [...]
++  documentContentScope = "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
 +      }
 +    }
 +    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
 +        }
 +      }
 +      return result
 +    }
 +  }
 +  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
 +    }
 +  }
 +  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
 +      }
 +      c = c.nextSibling
 +    }
 +    node.insertBefore(child, c)
 +  }
 +  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)
 +        }
 +      })
 +    }
 +  };
 +  odf.OdfPart.prototype.load = function() {
 +  };
 +  odf.OdfPart.prototype.getUrl = function() {
 +    if(this.data) {
 +      return"data:;base64," + base64.toBase64(this.data)
 +    }
 +    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 {
 +          if(n.nodeType === Node.PROCESSING_INSTRUCTION_NODE) {
 +            element.removeChild(n)
 +          }
 +        }
 +        n = next
 +      }
 +    }
 +    function setAutomaticStylesScope(stylesRootElement, scope) {
 +      var n = stylesRootElement && stylesRootElement.firstChild;
 +      while(n) {
 +        if(n.nodeType === Node.ELEMENT_NODE) {
 +          (n).setAttributeNS(webodfns, "scope", scope)
 +        }
 +        n = n.nextSibling
 +      }
 +    }
++    function getEnsuredMetaElement() {
++      var root = self.rootElement, meta = root.meta;
++      if(!meta) {
++        root.meta = meta = document.createElementNS(officens, "meta");
++        setChild(root, meta)
++      }
++      return meta
++    }
++    function getMetaData(metadataNs, metadataLocalName) {
++      var node = self.rootElement.meta, textNode;
++      node = node && node.firstChild;
++      while(node && (node.namespaceURI !== metadataNs || node.localName !== metadataLocalName)) {
++        node = node.nextSibling
++      }
++      node = node && node.firstChild;
++      while(node && node.nodeType !== Node.TEXT_NODE) {
++        node = node.nextSibling
++      }
++      if(node) {
++        textNode = (node);
++        return textNode.data
++      }
++      return null
++    }
 +    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 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
 +      }
 +      return result
 +    }
 +    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
 +      }
 +      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
 +        }
 +      }
 +      return copy
 +    }
 +    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
 +    }
-     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) {
 +        }
 +      }
 +      return node
 +    }
 +    function setState(state) {
 +      self.state = state;
 +      if(self.onchange) {
 +        self.onchange(self)
 +      }
 +      if(self.onstatereadychange) {
 +        self.onstatereadychange(self)
 +      }
 +    }
 +    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 handleFlatXml(xmldoc) {
 +      var root = importRootNode(xmldoc);
 +      if(!root || (root.localName !== "document" || root.namespaceURI !== officens)) {
 +        setState(OdfContainer.INVALID);
 +        return
 +      }
 +      setRootElement((root));
 +      setState(OdfContainer.DONE)
 +    }
 +    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)
 +    }
 +    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(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)
 +        }
 +      }
 +      node = getDirectChild(node, officens, "body");
 +      if(node === null) {
 +        throw"<office:body/> tag is mising.";
 +      }
 +      root.body = node;
 +      setChild(root, root.body)
 +    }
 +    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)
++      root.meta = getDirectChild(node, officens, "meta");
++      setChild(root, 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 {
 +        setState(OdfContainer.DONE)
 +      }
 +    }
 +    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 + '"'
 +      }
 +      odf.Namespaces.forEachPrefix(defineNamespace);
 +      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]))
 +        }
 +      }
 +      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 setMetadata(setProperties, removedPropertyNames) {
++      var metaElement = getEnsuredMetaElement();
++      if(setProperties) {
++        domUtils.mapKeyValObjOntoNode(metaElement, setProperties, odf.Namespaces.lookupNamespaceURI)
++      }
++      if(removedPropertyNames) {
++        domUtils.removeKeyElementsFromNode(metaElement, removedPropertyNames, odf.Namespaces.lookupNamespaceURI)
++      }
++    }
++    this.setMetadata = setMetadata;
++    this.incrementEditingCycles = function() {
++      var currentValueString = getMetaData(odf.Namespaces.metans, "editing-cycles"), currentCycles = currentValueString ? parseInt(currentValueString, 10) : 0;
++      if(isNaN(currentCycles)) {
++        currentCycles = 0
++      }
++      setMetadata({"meta:editing-cycles":currentCycles + 1}, null)
++    };
 +    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)
++      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) 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");
 +(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
 +    }
 +    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 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)
 +    }
 +  }
 +  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(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.hasOwnProperty(textProperties), "applyStyle without any text properties");
-     textPropsOnly[textProperties] = info[textProperties];
-     styleCache = new StyleManager(textPropsOnly);
-     styleLookup = new StyleLookup(textPropsOnly);
-     function apply(n) {
-       isStyled = styleLookup.isStyleApplied(n);
-       if(isStyled === false) {
-         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("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};
++  var 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 = {}
 +    }
 +    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
 +      }
 +      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
 +        }
 +      }
 +      node = node.nextElementSibling
 +    }
 +    return fontFaceDeclsMap
 +  }
 +  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
 +    }
 +    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
 +    }
 +    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
 +  }
 +  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
 +    }
 +    a = styleNode.attributes;
 +    for(i = 0;i < a.length;i += 1) {
 +      ai = (a.item(i));
 +      propertiesMap[ai.name] = ai.value
 +    }
 +    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
 +      }
 +    }
 +    node = getDefaultStyleElement(styleFamily);
 +    if(node) {
 +      propertiesMap = getStyleAttributes(node);
 +      inheritedPropertiesMap = utils.mergeObjects(propertiesMap, inheritedPropertiesMap)
 +    }
 +    if(includeSystemDefault) {
 +      propertiesMap = getSystemDefaultStyleAttributes(styleFamily);
 +      if(propertiesMap) {
 +        inheritedPropertiesMap = utils.mergeObjects(propertiesMap, inheritedPropertiesMap)
 +      }
 +    }
 +    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])
 +    }
 +    styleElement = getStyleElement(styleName, "paragraph", [styleElementList]);
 +    if(!styleElement) {
 +      return null
 +    }
 +    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
 +      }
 +      nodeStyles = styleInfo.determineStylesForNode(parent);
 +      if(nodeStyles) {
 +        appliedStyles.push(nodeStyles)
 +      }
 +      parent = parent.parentElement
 +    }
 +    function chainStyles(usedStyleMap) {
 +      Object.keys(usedStyleMap).forEach(function(styleFamily) {
 +        Object.keys(usedStyleMap[styleFamily]).forEach(function(styleName) {
 +          chainKey += "|" + styleFamily + ":" + styleName + "|"
 +        })
 +      })
 +    }
 +    if(foundContainer) {
 +      appliedStyles.forEach(chainStyles);
 +      if(collectedChains) {
 +        collectedChains[chainKey] = appliedStyles
 +      }
 +    }
 +    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
 +  };
-   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)
 +    }
 +  };
 +  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)
 +    }else {
 +      newStyleObject = {"style:parent-style-name":parentStyleName}
 +    }
 +    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
 +    }
 +    if(!tabStopDistance) {
 +      tabStopDistance = "1.25cm"
 +    }
 +    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
 +        }
 +        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)
 +        }
 +      }
 +    }
 +    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
 +      }
 +    }
 +    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 {
 +        defaultOrientedPageWidth = defaultPageFormatSettings.height;
 +        defaultOrientedPageHeight = defaultPageFormatSettings.width
 +      }
 +      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
 +      }
 +      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{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");
 +(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)
 +    }
 +    this.clearQueue = function() {
 +      queue.length = 0
 +    };
 +    this.addToQueue = function(loadingTask) {
 +      if(queue.length === 0 && !taskRunning) {
 +        return run(loadingTask)
 +      }
 +      queue.push(loadingTask)
 +    }
 +  }
 +  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)
 +    }
 +    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 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
 +      }
 +    }
 +  }
 +  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 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, masterPageElement = masterStyles.firstElementChild;
 +    while(masterPageElement) {
 +      if(masterPageElement.getAttributeNS(stylens, "name") === masterPageName && (masterPageElement.localName === "master-page" && masterPageElement.namespaceURI === stylens)) {
 +        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)
 +      }
 +    }
 +  }
 +  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 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))
 +      }
 +    }
 +  }
 +  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;"
 +      }else {
 +        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 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""
 +  }
 +  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)
 +      }
 +    }
 +    function onchange(p) {
 +      callback(p.url)
 +    }
 +    if(url) {
 +      try {
 +        part = container.getPart(url);
 +        part.onchange = onchange;
 +        part.load()
 +      }catch(e) {
 +        runtime.log("slight problem: " + String(e))
 +      }
 +    }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)
 +      }
 +    }
 +  }
 +  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"))
 +      }
 +    }
 +    tableCells = odffragment.getElementsByTagNameNS(tablens, "table-cell");
 +    for(i = 0;i < tableCells.length;i += 1) {
 +      node = (tableCells.item(i));
 +      modifyTableCell(node)
 +    }
 +  }
 +  function modifyLinks(odffragment) {
 +    var i, links, node;
 +    function modifyLink(node) {
 +      var url, clickHandler;
 +      if(!node.hasAttributeNS(xlinkns, "href")) {
 +        return
 +      }
 +      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)
 +        }
 +      }
 +      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"))
 +      }
 +    })
 +  }
 +  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)
 +        }
 +      }
 +    }
 +    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;
 +    node = odfbody.firstElementChild;
 +    while(node && node !== odfbody) {
 +      if(node.namespaceURI === drawns) {
 +        drawElements[drawElements.length] = node
 +      }
 +      if(node.firstElementChild) {
 +        node = node.firstElementChild
 +      }else {
 +        while(node && (node !== odfbody && !node.nextElementSibling)) {
 +          node = node.parentElement
 +        }
 +        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)
 +  }
 +  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"))
 +      }
 +      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");
 +        if(url) {
 +          source.setAttribute("src", url)
 +        }
 +        source.setAttribute("type", mimetype);
 +        video.appendChild(source);
 +        plugin.parentNode.appendChild(video)
 +      }else {
 +        plugin.innerHtml = "Unrecognised Plugin"
 +      }
 +    }
 +    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))
 +      }
 +    }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 += " ''"
 +      }
 +    }
 +    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)
 +          }
 +        }
 +      }
 +    }
 +    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
 +      }
 +    }
 +    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 + ");"
 +          }
 +          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)
 +        }
 +      }
 +    }
 +  }
 +  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
 +      }
 +      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, 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)
 +        })
 +      }
 +      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 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 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)
 +      }
 +    }
 +    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)
 +      }
 +    }
 +    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"
 +    }
 +    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 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")
 +      }
 +      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 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()
 +        }
 +      }
 +    }
 +    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])
 +        }
 +      }
 +      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.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 "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"), 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)
 +    }
 +    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.LoopWatchDog");
++runtime.loadClass("odf.Namespaces");
++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(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.hasOwnProperty(textProperties), "applyStyle without any text properties");
++    textPropsOnly[textProperties] = info[textProperties];
++    styleCache = new StyleManager(textPropsOnly);
++    styleLookup = new StyleLookup(textPropsOnly);
++    function apply(n) {
++      isStyled = styleLookup.isStyleApplied(n);
++      if(isStyled === false) {
++        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("odf.Namespaces");
 +runtime.loadClass("odf.OdfUtils");
 +gui.StyleHelper = function StyleHelper(formatting) {
-   var domUtils = new core.DomUtils, odfUtils = new odf.OdfUtils, textns = odf.Namespaces.textns;
++  var 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 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
 +      }
 +    }
 +    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
 +      }
 +    }
 +    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(!isDefaultParagraphStyleChecked) {
 +          pickDefaultParagraphStyleElement()
 +        }else {
 +          paragraphStyleElement = undefined
 +        }
 +      }
 +      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
 +        }
 +      }
 +      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"])
 +  }
 +};
 +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")
 +  }
 +  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
 +        }
 +      }
 +    }
 +    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
 +    }
 +    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
 +    }
 +    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
 +    }
 +    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
 +    }
 +    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
 +      }
 +      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
 +    }
 +  };
 +  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)
 +    }
 +  };
 +  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
 +    }
 +  };
 +  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 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
 +      }
 +    }
 +    if(!zip_eofile) {
 +      n = zip_read_buff(zip_window, zip_strstart + zip_lookahead, more);
 +      if(n <= 0) {
 +        zip_eofile = true
 +      }else {
 +        zip_lookahead += n
 +      }
 +    }
 +  };
 +  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
 +    }
 +    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
 +      }
 +      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]
 +      }
 +      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 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
 +      }
 +      zip_heap[k] = zip_heap[j];
 +      k = j;
 +      j <<= 1
 +    }
 +    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
 +    }
 +    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)
 +      }
 +    }
 +    if(overflow === 0) {
 +      return
 +    }
 +    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--
 +      }
 +    }
 +  };
 +  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
 +      }
 +      tree[n].fc = zip_bi_reverse(next_code[len]++, len)
 +    }
 +  };
 +  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
 +      }
 +    }
 +    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
 +      }
 +    }
 +    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++
 +          }
 +        }
 +      }
 +      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
 +        }
 +      }
 +    }
 +  };
 +  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
 +      }
 +    }
 +    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)
 +      }
 +    }
 +    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)
 +    }
 +    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
 +    }
 +    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)
 +        }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
 +        }
 +      }
 +    }
 +  };
 +  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)
 +    }
 +    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
 +    }
 +    for(n = 0;n < zip_D_CODES;n++) {
 +      zip_dyn_dtree[n].fc = 0
 +    }
 +    for(n = 0;n < zip_BL_CODES;n++) {
 +      zip_bl_tree[n].fc = 0
 +    }
 +    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(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 {
 +      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)
 +      }
 +    }
 +    zip_init_block();
 +    if(eof !== 0) {
 +      zip_bi_windup()
 +    }
 +  };
 +  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()
 +      }
 +    }
 +  };
 +  var zip_ct_init = function() {
 +    var n;
 +    var bits;
 +    var length;
 +    var code;
 +    var dist;
 +    if(zip_static_dtree[0].dl !== 0) {
 +      return
 +    }
 +    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
 +      }
 +    }
 +    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
 +      }
 +    }
 +    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(bits = 0;bits <= zip_MAX_BITS;bits++) {
 +      zip_bl_count[bits] = 0
 +    }
 +    n = 0;
 +    while(n <= 143) {
 +      zip_static_ltree[n++].dl = 8;
 +      zip_bl_count[8]++
 +    }
 +    while(n <= 255) {
 +      zip_static_ltree[n++].dl = 9;
 +      zip_bl_count[9]++
 +    }
 +    while(n <= 279) {
 +      zip_static_ltree[n++].dl = 7;
 +      zip_bl_count[7]++
 +    }
 +    while(n <= 287) {
 +      zip_static_ltree[n++].dl = 8;
 +      zip_bl_count[8]++
 +    }
 +    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 {
 +      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)
 +      }
 +    }
 +    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
 +};
 +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
 +    }
 +    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) {
 +        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) 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, 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
 +      }
 +      this.setIteratorPosition = function(iterator) {
 +        iterator.setUnfilteredPosition(paragraphNode.parentNode, positionInContainer(paragraphNode));
 +        do {
 +          if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
 +            break
 +          }
 +        }while(iterator.nextPosition())
 +      }
 +    }
 +    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())
 +      }
 +    }
 +    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(!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
 +        }
 +      }
 +      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
 +        }
 +      }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
 +        }
 +      }
 +    };
 +    this.setToClosestStep = function(steps, iterator) {
 +      var cacheBucket = getBucket(steps), cachePoint;
 +      while(!cachePoint && cacheBucket !== 0) {
 +        cachePoint = stepToDomPoint[cacheBucket];
 +        cacheBucket -= bucketSize
 +      }
 +      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
 +      }
 +      return bookmark
 +    }
 +    this.setToClosestDomPoint = function(node, offset, iterator) {
 +      var bookmark;
 +      if(node === rootNode && offset === 0) {
 +        bookmark = basePoint
 +      }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())
 +            }
 +          }
 +        }
 +      }
 +      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)
 +      }
 +    }
 +    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
 +        }
 +      })
 +    }
 +  };
 +  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
 +    }
 +  }
 +  function splitToDuos(e) {
 +    if(e.e.length <= 2) {
 +      return e
 +    }
 +    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 {
 +      prefix = r[0]
 +    }
 +    for(i in nsmap) {
 +      if(nsmap[i] === prefix) {
 +        r[0] = i
 +      }
 +    }
 +    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 {
 +        if(att.namespaceURI === xmlnsns) {
 +          nsmap[att.value] = att.localName
 +        }
 +      }
 +    }
 +    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
 +    }
 +    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
 +      }
 +    }
 +    return null
 +  }
 +  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 = ""
 +      }
 +    }else {
 +      delete a.ns
 +    }
 +    if(name === "name") {
 +      i = splitQName(text);
 +      a.ns = i[0];
 +      text = i[1]
 +    }
 +    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 {
 +      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 null
 +      }
 +    }
 +    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
 +        }
 +      }else {
 +        if(e[1].name === "empty") {
 +          name = def.name = e[0].name;
 +          def.names = e[0].names;
 +          e = def.e = e[0].e
 +        }
 +      }
 +    }
 +    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)
 +        }
 +      }
 +    }
 +  }
 +  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
 +    }
 +  }
 +  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)
 +      }
 +    }
 +    for(i = 0;i < elements.length;i += 1) {
 +      resolveDefines(elements[i], defines)
 +    }
 +    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)
 +      }
 +    }
 +    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)
 +    }
 +  };
 +  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("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)
 +  }
 +  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 getRoot(node) {
 +    while(node && !isRoot(node)) {
 +      node = (node.parentNode)
 +    }
 +    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
 +    }
 +  }
 +  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)
 +    }
 +    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()
++      nodeOffset = (iterator.unfilteredDomOffset());
++      if(lastTextNode.length > 0) {
++        if(nodeOffset > 0) {
++          lastTextNode = lastTextNode.splitText(nodeOffset)
++        }
++        lastTextNode.parentNode.insertBefore(getDOM().createTextNode(""), lastTextNode);
++        lastTextNode = (lastTextNode.previousSibling);
++        nodeOffset = 0
++      }
 +    }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(memberid) {
++      if(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)
 +      }
-       if(lastTextNode.length > 0 && lastTextNode.nextSibling !== cursorNode) {
-         lastTextNode = getDOM().createTextNode("");
-         nodeOffset = 0
++    }else {
++      while(lastTextNode.nextSibling && lastTextNode.nextSibling.localName === "cursor") {
++        lastTextNode.parentNode.insertBefore(lastTextNode.nextSibling, lastTextNode)
 +      }
-       cursorNode.parentNode.insertBefore(lastTextNode, cursorNode)
 +    }
 +    while(lastTextNode.previousSibling && lastTextNode.previousSibling.nodeType === Node.TEXT_NODE) {
 +      lastTextNode.previousSibling.appendData(lastTextNode.data);
-       nodeOffset = lastTextNode.previousSibling.length;
++      nodeOffset = (lastTextNode.previousSibling.length);
 +      lastTextNode = (lastTextNode.previousSibling);
 +      lastTextNode.parentNode.removeChild(lastTextNode.nextSibling)
 +    }
++    while(lastTextNode.nextSibling && lastTextNode.nextSibling.nodeType === Node.TEXT_NODE) {
++      lastTextNode.appendData(lastTextNode.nextSibling.data);
++      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)
 +    }
 +    return null
 +  }
 +  function handleOperationExecuted(op) {
-     var spec = op.spec(), memberId = spec.memberid, date = (new Date(spec.timestamp)).toISOString(), metadataManager = odfCanvas.odfContainer().getMetadataManager(), fullName;
++    var spec = op.spec(), memberId = spec.memberid, date = (new Date(spec.timestamp)).toISOString(), odfContainer = odfCanvas.odfContainer(), fullName;
 +    if(op.isEdit) {
 +      fullName = self.getMember(memberId).getProperties().fullName;
-       metadataManager.setMetadata({"dc:creator":fullName, "dc:date":date}, null);
++      odfContainer.setMetadata({"dc:creator":fullName, "dc:date":date}, null);
 +      if(!lastEditingOp) {
-         metadataManager.incrementEditingCycles();
++        odfContainer.incrementEditingCycles();
 +        if(!unsupportedMetadataRemoved) {
-           metadataManager.setMetadata(null, ["meta:editing-duration", "meta:document-statistic"])
++          odfContainer.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))
 +    }
 +    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()
 +    }
 +  }
 +  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]) {
++    while(!odfUtils.isSpaceElement(container) && container.childNodes[offset]) {
 +      container = container.childNodes[offset];
 +      offset = 0
 +    }
 +    if(container.nodeType === Node.TEXT_NODE) {
 +      container = container.parentNode
 +    }
 +    if(odfUtils.isDowngradableSpaceElement(container)) {
 +      firstSpaceElementChild = container.firstChild;
 +      lastSpaceElementChild = container.lastChild;
 +      domUtils.mergeIntoParent(container);
 +      if(lastSpaceElementChild !== firstSpaceElementChild) {
 +        domUtils.normalizeTextNodes(lastSpaceElementChild)
 +      }
 +      domUtils.normalizeTextNodes(firstSpaceElementChild)
 +    }
 +  };
 +  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.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.moveCursor = function(memberid, position, length, selectionType) {
++    var cursor = cursors[memberid], selectionRange = self.convertCursorToDomRange(position, length);
++    if(cursor && selectionRange) {
++      cursor.setSelectedRange(selectionRange, length >= 0);
++      cursor.setSelectionType(selectionType || ops.OdtCursor.RangeSelection)
++    }
++  };
 +  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()
 +  };
 +  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) 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() {
 +};
 +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])
 +          }
 +        }
 +      }
 +    }
 +    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", 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 valueMatch(context, pattern, text) {
 +    return pattern.nullable && /^\s+$/.test(text) || pattern.textDeriv(context, text).nullable
 +  }
 +  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
 +    }}
 +  }
 +  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
 +      }
 +    }
 +    return result
 +  };
 +  function attsDeriv(context, pattern, attributes, position) {
 +    if(pattern === notAllowed) {
 +      return notAllowed
 +    }
 +    if(position >= attributes.length) {
 +      return pattern
 +    }
 +    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(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 {
 +          p = p.textDeriv(context, childNode)
 +        }
 +      }else {
 +        walker.currentNode = childNode;
 +        p = childDeriv(context, p, walker)
 +      }
 +    }
 +    walker.currentNode = element;
 +    return p
 +  }
 +  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(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 {
 +        result = {hash:"anyName", contains:function() {
 +          return true
 +        }}
 +      }
 +    }
 +    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]
 +      }
 +    }
 +    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
 +    }
 +    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.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)
 +    }
 +  };
 +  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
 +    }
 +  }
 +  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 err
 +  }
 +  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 validateNonEmptyPattern(elementdef, walker, element, data)
 +  }
 +  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
 +    }
 +    if(att === undefined) {
 +      return[new RelaxNGParseError("Attribute not found: " + elementdef.names, element)]
 +    }
 +    return validatePattern(elementdef.e[1], walker, element, att)
 +  }
 +  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;
 +    }
 +    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
 +    }
 +    if(!node) {
 +      return[new RelaxNGParseError("Missing element " + elementdef.names)]
 +    }
 +    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(walker.parentNode() !== node) {
 +        return[new RelaxNGParseError("Implementation error.")]
 +      }
 +    }else {
 +      error = validateTop(elementdef.e[1], walker, node)
 +    }
 +    node = walker.nextSibling();
 +    return error
 +  }
 +  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
 +      }
 +      return null
 +    }
 +    err = validatePattern(elementdef.e[0], walker, element, data);
 +    if(err) {
 +      walker.currentNode = node;
 +      err = validateNonEmptyPattern(elementdef.e[1], walker, element, data)
 +    }
 +    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)]
 +          }
 +        }
 +        return null
 +      }
 +      todo = 0;
 +      for(i = 0;i < l;i += 1) {
 +        if(n[i] !== true) {
 +          todo += 1
 +        }
 +      }
 +    }
 +    return null
 +  }
 +  function validateGroup(elementdef, walker, element) {
 +    if(elementdef.e.length !== 2) {
 +      throw"Group with wrong # of members: " + elementdef.e.length;
 +    }
 +    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(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 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
 +  }
 +};
 +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
 +    }
 +    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 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)
 +    }
 +    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
 +      }
 +    }
 +    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 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"
 +    }
 +    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}
 +      }
 +      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
 +      }
 +    }
 +    if(caretRect.left < canvasContainerRect.left) {
 +      canvasContainerElement.scrollLeft -= canvasContainerRect.left - caretRect.left
 +    }else {
 +      if(caretRect.right > canvasContainerRect.right) {
 +        canvasContainerElement.scrollLeft += caretRect.right - canvasContainerRect.right
 +      }
 +    }
 +    handleUpdate()
 +  };
 +  this.destroy = function(callback) {
 +    avatar.destroy(function(err) {
 +      if(err) {
 +        callback(err)
 +      }else {
 +        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;
++  var window = (runtime.getWindow()), bindToDirectHandler = {"beforecut":true, "beforepaste":true}, bindToWindow, eventTrap;
++  function getCanvasElement() {
++    return odtDocument.getOdfCanvas().getElement()
++  }
 +  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)
 +      }
 +    }
 +  }
 +  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 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];
++    var delegate = bindToWindow[eventName], canvasElement = getCanvasElement();
 +    if(delegate) {
 +      delegate.handlers.push(handler);
 +      if(!delegate.isSubscribed) {
 +        delegate.isSubscribed = true;
 +        listenEvent((window), eventName, delegate.handleEvent);
-         listenEvent(canvasElement, eventName, delegate.handleEvent)
++        listenEvent(canvasElement, eventName, delegate.handleEvent);
++        listenEvent(eventTrap, eventName, delegate.handleEvent)
 +      }
 +    }else {
 +      listenEvent(canvasElement, eventName, handler)
 +    }
 +  };
 +  this.unsubscribe = function(eventName, handler) {
-     var delegate = window && bindToWindow[eventName], handlerIndex = delegate && delegate.handlers.indexOf(handler);
++    var delegate = bindToWindow[eventName], handlerIndex = delegate && delegate.handlers.indexOf(handler), canvasElement = getCanvasElement();
 +    if(delegate) {
 +      if(handlerIndex !== -1) {
 +        delegate.handlers.splice(handlerIndex, 1)
 +      }
 +    }else {
 +      removeEvent(canvasElement, eventName, handler)
 +    }
 +  };
 +  function hasFocus() {
-     var activeElement = odtDocument.getDOM().activeElement;
-     return activeElement === canvasElement
++    return odtDocument.getDOM().activeElement === getCanvasElement()
 +  }
-   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
++    return new WindowScrollState(window)
 +  }
 +  this.focus = function() {
-     var scrollParent;
++    var scrollParent, canvasElement = getCanvasElement(), selection = window.getSelection();
 +    if(!hasFocus()) {
 +      scrollParent = findScrollableParent(canvasElement);
 +      canvasElement.focus();
 +      if(scrollParent) {
 +        scrollParent.restore()
 +      }
 +    }
++    if(selection && selection.extend) {
++      if(eventTrap.parentNode !== canvasElement) {
++        canvasElement.appendChild(eventTrap)
++      }
++      selection.collapse(eventTrap.firstChild, 0);
++      selection.extend(eventTrap, eventTrap.childNodes.length)
++    }
 +  };
 +  function init() {
-     bindToWindow = {"mousedown":new EventDelegate, "mouseup":new EventDelegate}
++    var canvasElement = getCanvasElement(), doc = canvasElement.ownerDocument;
++    runtime.assert(Boolean(window), "EventManager requires a window object to operate correctly");
++    bindToWindow = {"mousedown":new EventDelegate, "mouseup":new EventDelegate, "focus":new EventDelegate};
++    eventTrap = doc.createElement("div");
++    eventTrap.id = "eventTrap";
++    eventTrap.setAttribute("contenteditable", "true");
++    eventTrap.style.position = "absolute";
++    eventTrap.style.left = "-10000px";
++    eventTrap.appendChild(doc.createTextNode("dummy content"));
++    canvasElement.appendChild(eventTrap)
 +  }
 +  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) 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
 +  }
 +  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
 +    }
 +  }
 +  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
 +      }
 +      if(isSameDirectionOfTravel(recentEditOps, thisOp)) {
 +        return true
 +      }
 +    }
 +    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 true
 +  }
 +  this.isPartOfOperationSet = isPartOfOperationSet
 +};
 +/*
 +
 + 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.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()
 +};
 +/*
 +
 + 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 createAnnotationEnd() {
 +    var annotationEnd;
 +    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)
 +      }
 +      parentNode.insertBefore(node, previousNode.nextSibling);
 +      if(previousNode.length === 0) {
 +        parentNode.removeChild(previousNode)
 +      }
 +    }
 +  }
 +  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
 +    }
 +    if(length) {
 +      annotation.end = createAnnotationEnd();
 +      if(!annotation.end) {
 +        return false
 +      }
 +      insertNodeAtPosition(odtDocument, annotation.end, position + length)
 +    }
 +    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)
 +    }
 +    odtDocument.getOdfCanvas().addAnnotation(annotation);
 +    odtDocument.fixCursorPositions();
 +    return true
 +  };
 +  this.spec = function() {
 +    return{optype:"AddAnnotation", memberid:memberid, timestamp:timestamp, position:position, length:length, name:name}
 +  }
 +};
 +/*
 +
 + 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) 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
 +    }
 +    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}
 +  }
 +};
 +/*
 +
 + 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(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 {
 +      odfContainer.rootElement.styles.appendChild(styleNode)
 +    }
 +    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("core.DomUtils");
 +runtime.loadClass("odf.OdfUtils");
++runtime.loadClass("odf.TextStyleApplicator");
 +ops.OpApplyDirectStyling = function OpApplyDirectStyling() {
-   var memberid, timestamp, position, length, setProperties, odfUtils = new odf.OdfUtils;
++  var memberid, timestamp, position, length, setProperties, odfUtils = new odf.OdfUtils, domUtils = new core.DomUtils;
 +  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
++  function applyStyle(odtDocument, range, info) {
++    var odfCanvas = odtDocument.getOdfCanvas(), odfContainer = odfCanvas.odfContainer(), nextTextNodes = domUtils.splitBoundaries(range), textNodes = odfUtils.getTextNodes(range, false), limits, textStyles;
++    limits = {startContainer:range.startContainer, startOffset:range.startOffset, endContainer:range.endContainer, endOffset:range.endOffset};
++    textStyles = new odf.TextStyleApplicator(new odf.ObjectNameGenerator((odfContainer), memberid), odtDocument.getFormatting(), odfContainer.rootElement.automaticStyles);
++    textStyles.applyStyle(textNodes, limits, info);
++    nextTextNodes.forEach(domUtils.normalizeTextNodes)
 +  }
 +  this.execute = function(odtDocument) {
-     var range = getRange(odtDocument), impactedParagraphs = odfUtils.getImpactedParagraphs(range), styleHelper = new gui.StyleHelper(odtDocument.getFormatting());
-     styleHelper.applyStyle(memberid, range, setProperties);
++    var range = odtDocument.convertCursorToDomRange(position, length), impactedParagraphs = odfUtils.getImpactedParagraphs(range);
++    applyStyle(odtDocument, 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}
 +  }
 +};
 +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
 +  }
 +  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;
++  var space = " ", tab = "\t", memberid, timestamp, position, text, moveCursor;
 +  this.init = function(data) {
 +    memberid = data.memberid;
 +    timestamp = data.timestamp;
 +    position = data.position;
-     text = data.text
++    text = data.text;
++    moveCursor = data.moveCursor === "true" || data.moveCursor === true
 +  };
 +  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;
++    var domPosition, previousNode, parentElement, nextNode = null, ownerDocument = odtDocument.getDOM(), paragraphElement, textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0", toInsertIndex = 0, spaceTag, spaceElement, cursor = odtDocument.getCursor(memberid), i;
 +    function insertTextNode(toInsertText) {
 +      parentElement.insertBefore(ownerDocument.createTextNode(toInsertText), nextNode)
 +    }
 +    odtDocument.upgradeWhitespacesAtPosition(position);
-     domPosition = odtDocument.getTextNodeAtStep(position, memberid);
++    domPosition = odtDocument.getTextNodeAtStep(position);
 +    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(cursor && moveCursor) {
++        odtDocument.moveCursor(memberid, position + text.length, 0);
++        odtDocument.emit(ops.OdtDocument.signalCursorMoved, cursor)
++      }
 +      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}
++    return{optype:"InsertText", memberid:memberid, timestamp:timestamp, position:position, text:text, moveCursor:moveCursor}
 +  }
 +};
 +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
 +    }
 +    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}
 +  }
 +};
 +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
 +    }
 +    if(container === null) {
 +      return false
 +    }
 +    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
 +    }
 +    odtDocument.getOdfCanvas().forgetAnnotations();
 +    cursors = domUtils.getElementsByTagNameNS(annotationNode, "urn:webodf:names:cursor", "cursor");
 +    while(cursors.length) {
 +      annotationNode.parentNode.insertBefore(cursors.pop(), annotationNode)
 +    }
 +    annotationNode.parentNode.removeChild(annotationNode);
 +    if(annotationEnd) {
 +      annotationEnd.parentNode.removeChild(annotationEnd)
 +    }
 +    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}
 +  }
 +};
 +/*
 +
 + 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.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}
 +  }
 +};
 +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.Member");
 +ops.OpRemoveMember = function OpRemoveMember() {
 +  var memberid, timestamp;
 +  this.init = function(data) {
 +    memberid = data.memberid;
 +    timestamp = parseInt(data.timestamp, 10)
 +  };
 +  this.isEdit = false;
 +  this.execute = function(odtDocument) {
 +    if(!odtDocument.getMember(memberid)) {
 +      return false
 +    }
 +    odtDocument.removeMember(memberid);
 +    odtDocument.emit(ops.OdtDocument.signalMemberRemoved, memberid);
 +    return true
 +  };
 +  this.spec = function() {
 +    return{optype:"RemoveMember", 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.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
 +    }
 +    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}
 +  }
 +};
 +ops.OpRemoveStyle.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("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(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
 +    }
 +    this.isEmpty = isEmpty;
 +    function isCollapsibleContainer(node) {
 +      return!odfUtils.isParagraph(node) && (node !== rootNode && isEmpty(node))
 +    }
 +    function mergeChildrenIntoParent(targetNode) {
 +      var parent;
 +      if(targetNode.nodeType === Node.TEXT_NODE) {
 +        parent = targetNode.parentNode;
 +        parent.removeChild(targetNode)
 +      }else {
 +        parent = domUtils.removeUnwantedNodes(targetNode, shouldRemove)
 +      }
 +      if(isCollapsibleContainer(parent)) {
 +        return mergeChildrenIntoParent(parent)
 +      }
 +      return parent
 +    }
 +    this.mergeChildrenIntoParent = mergeChildrenIntoParent
 +  }
 +  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)
 +      }
 +      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)
 +      }
 +    }
 +    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}
 +  }
 +};
 +ops.OpRemoveText.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.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.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")
 +      }
 +      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}
 +  }
 +};
 +ops.OpSetParagraphStyle.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.OpSplitParagraph = function OpSplitParagraph() {
-   var memberid, timestamp, position, odfUtils;
++  var memberid, timestamp, position, moveCursor, odfUtils;
 +  this.init = function(data) {
 +    memberid = data.memberid;
 +    timestamp = data.timestamp;
 +    position = data.position;
++    moveCursor = data.moveCursor === "true" || data.moveCursor === true;
 +    odfUtils = new odf.OdfUtils
 +  };
 +  this.isEdit = true;
 +  this.execute = function(odtDocument) {
-     var domPosition, paragraphNode, targetNode, node, splitNode, splitChildNode, keptChildNode;
++    var domPosition, paragraphNode, targetNode, node, splitNode, splitChildNode, keptChildNode, cursor = odtDocument.getCursor(memberid);
 +    odtDocument.upgradeWhitespacesAtPosition(position);
-     domPosition = odtDocument.getTextNodeAtStep(position, memberid);
++    domPosition = odtDocument.getTextNodeAtStep(position);
 +    if(!domPosition) {
 +      return false
 +    }
 +    paragraphNode = odtDocument.getParagraphElement(domPosition.textNode);
 +    if(!paragraphNode) {
 +      return false
 +    }
 +    if(odfUtils.isListItem(paragraphNode.parentNode)) {
 +      targetNode = paragraphNode.parentNode
 +    }else {
 +      targetNode = paragraphNode
 +    }
 +    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))
 +      }
 +    }
 +    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
 +    }
 +    if(odfUtils.isListItem(splitChildNode)) {
 +      splitChildNode = splitChildNode.childNodes[0]
 +    }
 +    if(domPosition.textNode.length === 0) {
 +      domPosition.textNode.parentNode.removeChild(domPosition.textNode)
 +    }
 +    odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position:position, length:1});
++    if(cursor && moveCursor) {
++      odtDocument.moveCursor(memberid, position + 1, 0);
++      odtDocument.emit(ops.OdtDocument.signalCursorMoved, cursor)
++    }
 +    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{optype:"SplitParagraph", memberid:memberid, timestamp:timestamp, position:position, moveCursor:moveCursor}
 +  }
 +};
 +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.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.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.isEdit = true;
 +  this.execute = function(odtDocument) {
-     var metadataManager = odtDocument.getOdfCanvas().odfContainer().getMetadataManager(), removedPropertiesArray = [], blockedProperties = ["dc:date", "dc:creator", "meta:editing-cycles"];
++    var odfContainer = odtDocument.getOdfCanvas().odfContainer(), 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);
++    odfContainer.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("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.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)
 +    }else {
 +      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 false
 +  };
 +  this.spec = function() {
 +    return{optype:"UpdateParagraphStyle", memberid:memberid, timestamp:timestamp, styleName:styleName, setProperties:setProperties, removedProperties:removedProperties}
 +  }
 +};
 +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/
 +*/
 +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)
 +    }
 +    return op
 +  };
 +  function constructor(OperationType) {
 +    return function() {
 +      return new OperationType
 +    }
 +  }
 +  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/
 +*/
 +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() {
 +};
 +/*
 +
 + 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 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)
 +    }
 +    return isBackwards
 +  }
 +  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 dropStyleReferencingAttributes(setProperties, deletedStyleName) {
 +    if(setProperties) {
 +      ["style:parent-style-name", "style:next-style-name"].forEach(function(attributeName) {
 +        if(setProperties[attributeName] === deletedStyleName) {
 +          delete setProperties[attributeName]
 +        }
 +      })
 +    }
 +  }
 +  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 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
 +        }
 +      }
 +      if(removedPropertyNames.length > 0) {
 +        minorRemovedProperties.attributes = removedPropertyNames.join(",")
 +      }else {
 +        delete minorRemovedProperties.attributes
 +      }
 +    }
 +    return{majorChanged:majorChanged, minorChanged:minorChanged}
 +  }
 +  function hasProperties(properties) {
 +    var key;
 +    for(key in properties) {
 +      if(properties.hasOwnProperty(key)) {
 +        return true
 +      }
 +    }
 +    return false
 +  }
 +  function hasRemovedProperties(properties) {
 +    var key;
 +    for(key in properties) {
 +      if(properties.hasOwnProperty(key)) {
 +        if(key !== "attributes" || properties.attributes.length > 0) {
 +          return true
 +        }
 +      }
 +    }
 +    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)
 +    }
 +    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)
 +      }
 +      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
 +        }
 +      }
 +    }
 +    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
 +      }
 +    }
 +    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 {
 +          applyDirectStylingSpec.position = removeTextSpec.position;
 +          if(removeTextSpecEnd < applyDirectStylingSpecEnd) {
 +            applyDirectStylingSpec.length = applyDirectStylingSpecEnd - removeTextSpecEnd
 +          }else {
 +            applyDirectStylingSpecResult = []
 +          }
 +        }
 +      }
 +    }
 +    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
 +      }
 +    }
 +    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
 +      }
 +    }
 +    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
 +      }
 +    }
 +    if(isMoveCursorSpecRangeInverted) {
 +      invertMoveCursorSpecRange(moveCursorSpec)
 +    }
 +    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
 +      }
 +    }
 +    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 {
 +        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 = []
 +        }
 +      }
 +    }
 +    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 = []
 +      }
 +    }
 +    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 {
 +        if(splitParagraphSpecA.position === splitParagraphSpecB.position) {
 +          if(hasAPriority) {
 +            splitParagraphSpecB.position += 1
 +          }else {
 +            splitParagraphSpecA.position += 1
 +          }
-           return null
 +        }
 +      }
 +    }
 +    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
 +          }
 +        }
 +      }
 +    }
 +    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(isMoveCursorSpecRangeInverted) {
 +      invertMoveCursorSpecRange(moveCursorSpec)
 +    }
 +    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 = ""
 +    }
 +    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 {
 +              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 = []
 +            }
 +          }
 +        }
 +      }
 +    }
 +    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")
 +    }
 +    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
 +      }
 +      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
 +  };
 +  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)
 +    }
 +    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 {
 +        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")
 +    }
 +  };
 +  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()
 +    }
 +  }
 +  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}));
++      operations.push(createOp(new ops.OpSplitParagraph, {memberid:inputMemberId, position:cursorPosition, moveCursor:true}));
 +      cursorPosition += 1;
-       operations.push(createOp(new ops.OpInsertText, {memberid:inputMemberId, position:cursorPosition, text:text}));
++      operations.push(createOp(new ops.OpInsertText, {memberid:inputMemberId, position:cursorPosition, text:text, moveCursor:true}));
 +      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 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
 +          }
 +        }
 +      }
 +      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
 +          }
 +        }
 +      }
 +      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
 +    }
 +    if(!lastVisibleRect(lastRange, nodes)) {
 +      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
 +      }else {
 +        originalRect = getBoundingRect(originalRect, newRect)
 +      }
 +    }
 +    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 getRectFromNodeAfterFiltering(node) {
 +      var rect = null;
 +      if(acceptNode(node) === FILTER_ACCEPT) {
 +        rect = domUtils.getBoundingClientRect(node)
 +      }
 +      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)
 +      }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(!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 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)
 +  };
 +  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/
 +*/
 +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) 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 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.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()
 +    }
 +    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})
 +    }
 +  };
 +  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
 +  };
 +  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
 +  }
 +};
 +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.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.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.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)
 +      }else {
 +        odtDocument.close(callback)
 +      }
 +    })
 +  };
 +  this.destroy = function(callback) {
 +    odtDocument.destroy(callback)
 +  };
 +  function init() {
 +    self.setOperationRouter(new ops.TrivialOperationRouter)
 +  }
 +  init()
 +};
 +/*
 +
 + 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 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 = false;
 +    if(cursorNode) {
 +      newIsAnnotatable = !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
 +})();
 +/*
 +
 + 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
 +    }
 +    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()
 +    }
 +  }
 +  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
 +    }
 +    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()
 +  };
 +  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) 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
 +    }
 +    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 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()
 +    }
 +  }
 +  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 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
 +    }
 +    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)
 +  }
 +};
 +/*
 +
 + 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});
++    op.init({memberid:inputMemberId, position:selection.position, moveCursor:true});
 +    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});
++    op.init({memberid:inputMemberId, position:selection.position, text:text, moveCursor:true});
 +    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;
++    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, 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 cancelEvent(event) {
 +      if(event.preventDefault) {
 +        event.preventDefault()
 +      }else {
 +        event.returnValue = false
 +      }
 +    }
 +    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
 +    }
 +    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())
 +      }
 +      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())
 +    }
 +    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 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
 +      }
 +      if(startInsideCanvas && endInsideCanvas) {
 +        if(clickCount === 2) {
 +          expandToWordBoundaries(range)
 +        }else {
 +          if(clickCount >= 3) {
 +            expandToParagraphBoundaries(range)
 +          }
 +        }
 +      }
 +      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)
 +      }
 +    }
 +    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)
 +      }else {
 +        moveCursorByAdjustment(steps)
 +      }
 +    }
 +    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)
 +        }
 +      }
 +      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())
 +        }
 +      }
 +      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 {
 +        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 {
-             suppressFocusEvent = true;
-             selection.removeAllRanges();
-             selection.addRange(range.cloneRange());
-             (odtDocument.getOdfCanvas().getElement()).setActive();
-             runtime.setTimeout(function() {
-               suppressFocusEvent = false
-             }, 0)
-           }
++    function redrawRegionSelection() {
++      var cursor = odtDocument.getCursor(inputMemberId), imageElement;
++      if(cursor && cursor.getSelectionType() === ops.OdtCursor.RegionSelection) {
++        imageElement = odfUtils.getImageElements(cursor.getSelectedRange())[0];
++        if(imageElement) {
++          imageSelector.select((imageElement.parentNode));
++          return
 +        }
-       }else {
-         imageSelector.clearSelection()
-       }
-     }
-     function delayedMaintainCursor() {
-       if(suppressFocusEvent === false) {
-         runtime.setTimeout(maintainCursorSelection, 0)
 +      }
++      imageSelector.clearSelection()
 +    }
 +    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
 +    }
 +    function handleCut(e) {
 +      var cursor = odtDocument.getCursor(inputMemberId), selectedRange = cursor.getSelectedRange();
 +      if(selectedRange.collapsed) {
++        e.preventDefault();
 +        return
 +      }
 +      if(clipboard.setDataFromRange(e, selectedRange)) {
 +        textManipulator.removeCurrentSelection()
 +      }else {
 +        runtime.log("Cut operation failed")
 +      }
 +    }
 +    function handleBeforeCut() {
 +      var cursor = odtDocument.getCursor(inputMemberId), selectedRange = cursor.getSelectedRange();
 +      return selectedRange.collapsed !== false
 +    }
 +    function handleCopy(e) {
 +      var cursor = odtDocument.getCursor(inputMemberId), selectedRange = cursor.getSelectedRange();
 +      if(selectedRange.collapsed) {
++        e.preventDefault();
 +        return
 +      }
 +      if(!clipboard.setDataFromRange(e, selectedRange)) {
-         runtime.log("Cut operation failed")
++        runtime.log("Copy operation failed")
 +      }
 +    }
 +    function handlePaste(e) {
 +      var plainText;
 +      if(window.clipboardData && window.clipboardData.getData) {
 +        plainText = window.clipboardData.getData("Text")
 +      }else {
 +        if(e.clipboardData && e.clipboardData.getData) {
 +          plainText = e.clipboardData.getData("text/plain")
 +        }
 +      }
 +      if(plainText) {
 +        textManipulator.removeCurrentSelection();
-         session.enqueue(pasteHandler.createPasteOps(plainText));
-         cancelEvent(e)
++        session.enqueue(pasteHandler.createPasteOps(plainText))
 +      }
++      cancelEvent(e)
 +    }
 +    function handleBeforePaste() {
 +      return false
 +    }
 +    function updateUndoStack(op) {
 +      if(undoManager) {
 +        undoManager.onOperationExecuted(op)
 +      }
 +    }
 +    function forwardUndoStackChange(e) {
 +      odtDocument.emit(ops.OdtDocument.signalUndoStackChanged, e)
 +    }
 +    function undo() {
 +      if(undoManager) {
 +        undoManager.moveBackward(1);
 +        redrawRegionSelectionTask.trigger();
 +        return true
 +      }
 +      return false
 +    }
 +    function redo() {
 +      if(undoManager) {
 +        undoManager.moveForward(1);
 +        redrawRegionSelectionTask.trigger();
 +        return true
 +      }
 +      return 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)
 +        }
 +      }
 +    }
++    function synchronizeWindowSelection(cursor) {
++      var selection = window.getSelection(), 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 {
++        selection.removeAllRanges();
++        selection.addRange(range.cloneRange());
++        (odtDocument.getOdfCanvas().getElement()).setActive()
++      }
++    }
 +    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)
++        }else {
++          synchronizeWindowSelection(cursor)
 +        }
 +        if(clickCount > 1) {
 +          updateShadowCursor()
 +        }
 +      }
 +    }
 +    function mutableSelection(selection) {
 +      if(selection) {
 +        return{anchorNode:selection.anchorNode, anchorOffset:selection.anchorOffset, focusNode:selection.focusNode, focusOffset:selection.focusOffset}
 +      }
 +      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)
++        selectImage(target.parentNode);
++        eventManager.focus()
 +      }else {
 +        if(clickStartedWithinContainer && !imageSelector.isSelectorElement(target)) {
 +          if(isMouseMoved) {
-             selectRange(shadowCursor.getSelectedRange(), shadowCursor.hasForwardSelection(), event.detail)
++            selectRange(shadowCursor.getSelectedRange(), shadowCursor.hasForwardSelection(), event.detail);
++            eventManager.focus()
 +          }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
++                if(caretPos) {
++                  selection.anchorNode = (caretPos.container);
++                  selection.anchorOffset = caretPos.offset;
++                  selection.focusNode = selection.anchorNode;
++                  selection.focusOffset = selection.anchorOffset
 +                }
-                 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)
++              if(selection.anchorNode && selection.focusNode) {
++                selectionRange = selectionToRange(selection);
++                selectRange(selectionRange.range, selectionRange.hasForwardSelection, eventDetails.detail)
++              }
++              eventManager.focus()
 +            }, 0)
 +          }
 +        }
 +      }
 +      clickCount = 0;
 +      clickStartedWithinContainer = false;
 +      isMouseMoved = false
 +    }
++    function handleDragEnd() {
++      if(clickStartedWithinContainer) {
++        eventManager.focus()
++      }
++      clickCount = 0;
++      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)
 +      }
 +    }
 +    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);
++      eventManager.subscribe("dragend", handleDragEnd);
 +      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);
++      eventManager.unsubscribe("dragend", handleDragEnd);
 +      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
 +      }
 +    }
 +    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);
++      redrawRegionSelectionTask = new core.ScheduledTask(redrawRegionSelection, 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 {
 +        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)
 +      }
 +      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("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]
 +    })
 +  }
 +  function getCanvasElement() {
 +    return sessionController.getSession().getOdtDocument().getOdfCanvas().getElement()
 +  }
 +  function removeCaret(memberId) {
 +    if(memberId === sessionController.getInputMemberId()) {
 +      getCanvasElement().removeAttribute("tabindex")
 +    }
 +    delete carets[memberId]
 +  }
 +  function refreshLocalCaretBlinking(cursor) {
 +    var caret, memberId = cursor.getMemberId();
 +    if(memberId === sessionController.getInputMemberId()) {
 +      caret = getCaret(memberId);
 +      if(caret) {
 +        caret.refreshCursorBlinking()
 +      }
 +    }
 +  }
 +  function executeEnsureCaretVisible() {
 +    var caret = getCaret(sessionController.getInputMemberId());
 +    scrollIntoViewScheduled = false;
 +    if(caret) {
 +      caret.ensureVisible()
 +    }
 +  }
 +  function scheduleCaretVisibilityCheck() {
 +    var caret = getCaret(sessionController.getInputMemberId());
 +    if(caret) {
 +      caret.handleUpdate();
 +      if(!scrollIntoViewScheduled) {
 +        scrollIntoViewScheduled = true;
 +        runtime.setTimeout(executeEnsureCaretVisible, 50)
 +      }
 +    }
 +  }
 +  function ensureLocalCaretVisible(info) {
 +    if(info.memberId === sessionController.getInputMemberId()) {
 +      scheduleCaretVisibilityCheck()
 +    }
 +  }
 +  function focusLocalCaret() {
 +    var caret = getCaret(sessionController.getInputMemberId());
 +    if(caret) {
 +      caret.setFocus()
 +    }
 +  }
 +  function blurLocalCaret() {
 +    var caret = getCaret(sessionController.getInputMemberId());
 +    if(caret) {
 +      caret.removeFocus()
 +    }
 +  }
 +  function showLocalCaret() {
 +    var caret = getCaret(sessionController.getInputMemberId());
 +    if(caret) {
 +      caret.show()
 +    }
 +  }
 +  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.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)
 +  }
 +  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("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
 +      }
 +      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 {
 +        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))
 +    }
 +    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()
 +  }
 +  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 [...]
 +
diff --cc apps/documents/js/3rdparty/webodf/webodf.js
index f483b7d,0000000..688b4a1
mode 100644,000000..100644
--- a/apps/documents/js/3rdparty/webodf/webodf.js
+++ b/apps/documents/js/3rdparty/webodf/webodf.js
@@@ -1,3100 -1,0 +1,3078 @@@
 +// Input 0
- var webodf_version="0.4.2-1556-gf8a94ee";
++var webodf_version="0.4.2-1579-gfc3a4e6";
 +// Input 1
- 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 [...]
++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,f,p){};Runtime.prototype.readFile=function(g,l,f){};Runtime.prototype.readFileSync=function(g,l){};Runtime.prototype.loadXML=function(g,l){};Runtime.prototype.writeFile=function(g,l,f){};
++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.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,l,f){};var IS_COMPILED_CODE=!0;
++Runtime.byteArrayToString=function(g,l){function f(f){var h="",d,m=f.length;for(d=0;d<m;d+=1)h+=String.fromCharCode(f[d]&255);return h}function p(f){var h="",d,m=f.length,c=[],e,a,b,q;for(d=0;d<m;d+=1)e=f[d],128>e?c.push(e):(d+=1,a=f[d],194<=e&&224>e?c.push((e&31)<<6|a&63):(d+=1,b=f[d],224<=e&&240>e?c.push((e&15)<<12|(a&63)<<6|b&63):(d+=1,q=f[d],240<=e&&245>e&&(e=(e&7)<<18|(a&63)<<12|(b&63)<<6|q&63,e-=65536,c.push((e>>10)+55296,(e&1023)+56320))))),1E3===c.length&&(h+=String.fromCharCode [...]
++c),c.length=0);return h+String.fromCharCode.apply(null,c)}var r;"utf8"===l?r=p(g):("binary"!==l&&this.log("Unsupported encoding: "+l),r=f(g));return r};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(d,m){var c,e,a;void 0!==m?a=d:m=d;g?(e=g.ownerDocument,a&&(c=e.createElement("span"),c.className=a,c.appendChild(e.createTextNode(a)),g.appendChild(c),g.appendChild(e.createTextNode(" "))),c=e.createElement("span"),0<m.length&&"<"===m[0]?c.innerHTML=m:c.appendChild(e.createTextNode(m)),g.appendChild(c),g.appendChild(e.createElement("br"))):console&&console.log(m);"alert"===a&&alert(m)}function f(d,m,c){if(0!==c.status||c.responseText)if(200===c.stat [...]
++"string"!==typeof c.response)"binary"===m?(m=c.response,m=new Uint8Array(m)):m=String(c.response);else if("binary"===m)if(null!==c.responseBody&&"undefined"!==String(typeof VBArray)){m=(new VBArray(c.responseBody)).toArray();c=m.length;var e,a=new Uint8Array(new ArrayBuffer(c));for(e=0;e<c;e+=1)a[e]=m[e];m=a}else m=n.byteArrayFromString(c.responseText,"binary");else m=c.responseText;h[d]=m;d={err:null,data:m}}else d={err:c.responseText||c.statusText,data:null};else d={err:"File "+d+" is [...]
++return d}function p(d,m,c){var e=new XMLHttpRequest;e.open("GET",d,c);e.overrideMimeType&&("binary"!==m?e.overrideMimeType("text/plain; charset="+m):e.overrideMimeType("text/plain; charset=x-user-defined"));return e}function r(d,m,c){function e(){var b;4===a.readyState&&(b=f(d,m,a),c(b.err,b.data))}if(h.hasOwnProperty(d))c(null,h[d]);else{var a=p(d,m,!0);a.onreadystatechange=e;try{a.send(null)}catch(b){c(b.message,null)}}}var n=this,h={};this.byteArrayFromString=function(d,m){var c;if(" [...]
++d.length;var e,a,b,q=0;for(a=0;a<c;a+=1)b=d.charCodeAt(a),q+=1+(128<b)+(2048<b);e=new Uint8Array(new ArrayBuffer(q));for(a=q=0;a<c;a+=1)b=d.charCodeAt(a),128>b?(e[q]=b,q+=1):2048>b?(e[q]=192|b>>>6,e[q+1]=128|b&63,q+=2):(e[q]=224|b>>>12&15,e[q+1]=128|b>>>6&63,e[q+2]=128|b&63,q+=3)}else for("binary"!==m&&n.log("unknown encoding: "+m),c=d.length,e=new Uint8Array(new ArrayBuffer(c)),a=0;a<c;a+=1)e[a]=d.charCodeAt(a)&255;return c=e};this.byteArrayToString=Runtime.byteArrayToString;this.getVa [...]
++this.fromJson=Runtime.fromJson;this.toJson=Runtime.toJson;this.readFile=r;this.read=function(d,m,c,e){r(d,"binary",function(a,b){var q=null;if(b){if("string"===typeof b)throw"This should not happen.";q=b.subarray(m,m+c)}e(a,q)})};this.readFileSync=function(d,m){var c=p(d,m,!1),e;try{c.send(null);e=f(d,m,c);if(e.err)throw e.err;if(null===e.data)throw"No data read from "+d+".";}catch(a){throw a;}return e.data};this.writeFile=function(d,m,c){h[d]=m;var e=new XMLHttpRequest,a;e.open("PUT",d [...]
++function(){4===e.readyState&&(0!==e.status||e.responseText?200<=e.status&&300>e.status||0===e.status?c(null):c("Status "+String(e.status)+": "+e.responseText||e.statusText):c("File "+d+" is empty."))};a=m.buffer&&!e.sendAsBinary?m.buffer:n.byteArrayToString(m,"binary");try{e.sendAsBinary?e.sendAsBinary(a):e.send(a)}catch(b){n.log("HUH? "+b+" "+m),c(b.message)}};this.deleteFile=function(d,m){delete h[d];var c=new XMLHttpRequest;c.open("DELETE",d,!0);c.onreadystatechange=function(){4===c. [...]
++(200>c.status&&300<=c.status?m(c.responseText):m(null))};c.send(null)};this.loadXML=function(d,m){var c=new XMLHttpRequest;c.open("GET",d,!0);c.overrideMimeType&&c.overrideMimeType("text/xml");c.onreadystatechange=function(){4===c.readyState&&(0!==c.status||c.responseText?200===c.status||0===c.status?m(null,c.responseXML):m(c.responseText,null):m("File "+d+" is empty.",null))};try{c.send(null)}catch(e){m(e.message,null)}};this.isFile=function(d,m){n.getFileSize(d,function(c){m(-1!==c)}) [...]
++function(d,m){if(h.hasOwnProperty(d)&&"string"!==typeof h[d])m(h[d].length);else{var c=new XMLHttpRequest;c.open("HEAD",d,!0);c.onreadystatechange=function(){if(4===c.readyState){var e=c.getResponseHeader("Content-Length");e?m(parseInt(e,10)):r(d,"binary",function(a,b){a?m(-1):m(b.length)})}};c.send(null)}};this.log=l;this.assert=function(d,m,c){if(!d)throw l("alert","ASSERTION FAILED:\n"+m),c&&c(),m;};this.setTimeout=function(d,m){return setTimeout(function(){d()},m)};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(d){return(new DOMParser).parseFromString(d,"text/xml")};this.exit=function(d){l("Calling exit with code "+String(d)+", but exit() is not implemented.")};this.getWindow=function(){return window}}
++function NodeJSRuntime(){function g(d){var c=d.length,e,a=new Uint8Array(new ArrayBuffer(c));for(e=0;e<c;e+=1)a[e]=d[e];return a}function l(d,c,e){function a(a,c){if(a)return e(a,null);if(!c)return e("No data for "+d+".",null);if("string"===typeof c)return e(a,c);e(a,g(c))}d=r.resolve(n,d);"binary"!==c?p.readFile(d,c,a):p.readFile(d,null,a)}var f=this,p=require("fs"),r=require("path"),n="",h,d;this.byteArrayFromString=function(d,c){var e=new Buffer(d,c),a,b=e.length,q=new Uint8Array(new [...]
++for(a=0;a<b;a+=1)q[a]=e[a];return q};this.byteArrayToString=Runtime.byteArrayToString;this.getVariable=Runtime.getVariable;this.fromJson=Runtime.fromJson;this.toJson=Runtime.toJson;this.readFile=l;this.loadXML=function(d,c){l(d,"utf-8",function(e,a){if(e)return c(e,null);if(!a)return c("No data for "+d+".",null);c(null,f.parseXML(a))})};this.writeFile=function(d,c,e){c=new Buffer(c);d=r.resolve(n,d);p.writeFile(d,c,"binary",function(a){e(a||null)})};this.deleteFile=function(d,c){d=r.res [...]
++p.unlink(d,c)};this.read=function(d,c,e,a){d=r.resolve(n,d);p.open(d,"r+",666,function(b,q){if(b)a(b,null);else{var k=new Buffer(e);p.read(q,k,0,e,c,function(b){p.close(q);a(b,g(k))})}})};this.readFileSync=function(d,c){var e;e=p.readFileSync(d,"binary"===c?null:c);if(null===e)throw"File "+d+" could not be read.";"binary"===c&&(e=g(e));return e};this.isFile=function(d,c){d=r.resolve(n,d);p.stat(d,function(e,a){c(!e&&a.isFile())})};this.getFileSize=function(d,c){d=r.resolve(n,d);p.stat(d [...]
++a){e?c(-1):c(a.size)})};this.log=function(d,c){var e;void 0!==c?e=d:c=d;"alert"===e&&process.stderr.write("\n!!!!! ALERT !!!!!\n");process.stderr.write(c+"\n");"alert"===e&&process.stderr.write("!!!!! ALERT !!!!!\n")};this.assert=function(d,c,e){d||(process.stderr.write("ASSERTION FAILED: "+c),e&&e())};this.setTimeout=function(d,c){return setTimeout(function(){d()},c)};this.clearTimeout=function(d){clearTimeout(d)};this.libraryPaths=function(){return[__dirname]};this.setCurrentDirectory [...]
++d};this.currentDirectory=function(){return n};this.type=function(){return"NodeJSRuntime"};this.getDOMImplementation=function(){return d};this.parseXML=function(d){return h.parseFromString(d,"text/xml")};this.exit=process.exit;this.getWindow=function(){return null};h=new (require("xmldom").DOMParser);d=f.parseXML("<a/>").implementation}
++function RhinoRuntime(){function g(d,h){var c;void 0!==h?c=d:h=d;"alert"===c&&print("\n!!!!! ALERT !!!!!");print(h);"alert"===c&&print("!!!!! ALERT !!!!!")}var l=this,f={},p=f.javax.xml.parsers.DocumentBuilderFactory.newInstance(),r,n,h="";p.setValidating(!1);p.setNamespaceAware(!0);p.setExpandEntityReferences(!1);p.setSchema(null);n=f.org.xml.sax.EntityResolver({resolveEntity:function(d,h){var c=new f.java.io.FileReader(h);return new f.org.xml.sax.InputSource(c)}});r=p.newDocumentBuild [...]
++this.byteArrayFromString=function(d,h){var c,e=d.length,a=new Uint8Array(new ArrayBuffer(e));for(c=0;c<e;c+=1)a[c]=d.charCodeAt(c)&255;return a};this.byteArrayToString=Runtime.byteArrayToString;this.getVariable=Runtime.getVariable;this.fromJson=Runtime.fromJson;this.toJson=Runtime.toJson;this.loadXML=function(d,h){var c=new f.java.io.File(d),e=null;try{e=r.parse(c)}catch(a){return print(a),h(a,null)}h(null,e)};this.readFile=function(d,m,c){h&&(d=h+"/"+d);var e=new f.java.io.File(d),a="b [...]
++"latin1":m;e.isFile()?((d=readFile(d,a))&&"binary"===m&&(d=l.byteArrayFromString(d,"binary")),c(null,d)):c(d+" is not a file.",null)};this.writeFile=function(d,m,c){h&&(d=h+"/"+d);d=new f.java.io.FileOutputStream(d);var e,a=m.length;for(e=0;e<a;e+=1)d.write(m[e]);d.close();c(null)};this.deleteFile=function(d,m){h&&(d=h+"/"+d);var c=new f.java.io.File(d),e=d+Math.random(),e=new f.java.io.File(e);c.rename(e)?(e.deleteOnExit(),m(null)):m("Could not delete "+d)};this.read=function(d,m,c,e){ [...]
++d);var a;a=d;var b="binary";(new f.java.io.File(a)).isFile()?("binary"===b&&(b="latin1"),a=readFile(a,b)):a=null;a?e(null,this.byteArrayFromString(a.substring(m,m+c),"binary")):e("Cannot read "+d,null)};this.readFileSync=function(d,h){if(!h)return"";var c=readFile(d,h);if(null===c)throw"File could not be read.";return c};this.isFile=function(d,m){h&&(d=h+"/"+d);var c=new f.java.io.File(d);m(c.isFile())};this.getFileSize=function(d,m){h&&(d=h+"/"+d);var c=new f.java.io.File(d);m(c.length [...]
++g;this.assert=function(d,h,c){d||(g("alert","ASSERTION FAILED: "+h),c&&c())};this.setTimeout=function(d){d();return 0};this.clearTimeout=function(){};this.libraryPaths=function(){return["lib"]};this.setCurrentDirectory=function(d){h=d};this.currentDirectory=function(){return h};this.type=function(){return"RhinoRuntime"};this.getDOMImplementation=function(){return r.getDOMImplementation()};this.parseXML=function(d){d=new f.java.io.StringReader(d);d=new f.org.xml.sax.InputSource(d);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. [...]
++(function(){function g(h,d){var f=h+"/manifest.json",c,e;if(!n.hasOwnProperty(f)){n[f]=1;try{c=runtime.readFileSync(f,"utf-8")}catch(a){console.log(String(a));return}f=JSON.parse(c);for(e in f)f.hasOwnProperty(e)&&(d[e]={dir:h,deps:f[e]})}}function l(h,d,f){var c=d[h].deps,e={};f[h]=e;c.forEach(function(a){e[a]=1});c.forEach(function(a){f[a]||l(a,d,f)});c.forEach(function(a){Object.keys(f[a]).forEach(function(a){e[a]=1})})}function f(h,d){function f(a,b){var c,k=d[a];if(-1===e.indexOf(a [...]
++for(c=0;c<h.length;c+=1)k[h[c]]&&f(h[c],b);b.pop();e.push(a)}}var c,e=[];for(c=0;c<h.length;c+=1)f(h[c],[]);return e}function p(h,d){for(var f=0;f<h.length&&void 0!==d[f];)null!==d[f]&&(eval(d[f]),d[f]=null),f+=1}var r={},n={};runtime.loadClass=function(h){if(!IS_COMPILED_CODE){var d=h.replace(".","/")+".js";if(!n.hasOwnProperty(d)){if(!(0<Object.keys(r).length)){var m=runtime.libraryPaths(),d={},c;runtime.currentDirectory()&&g(runtime.currentDirectory(),d);for(c=0;c<m.length;c+=1)g(m[c [...]
++c={};for(e in d)d.hasOwnProperty(e)&&l(e,d,c);for(e in d)d.hasOwnProperty(e)&&(m=Object.keys(c[e]),d[e].deps=f(m,c),d[e].deps.push(e));r=d}e=h.replace(".","/")+".js";h=[];e=r[e].deps;for(d=0;d<e.length;d+=1)n.hasOwnProperty(e[d])||h.push(e[d]);e=[];e.length=h.length;for(d=h.length-1;0<=d;d-=1)n[h[d]]=1,void 0===e[d]&&(m=h[d],m=r[m].dir+"/"+m,c=runtime.readFileSync(m,"utf-8"),c+="\n//# sourceURL="+m,c+="\n//@ sourceURL="+m,e[d]=c);p(h,e)}}}})();
++(function(){var g=function(g){return g};runtime.getTranslator=function(){return g};runtime.setTranslator=function(l){g=l};runtime.tr=function(l){var f=g(l);return f&&"string"===String(typeof f)?f:l}})();
++(function(g){function l(f){if(f.length){var g=f[0];runtime.readFile(g,"utf8",function(l,n){function h(){var c;(c=eval(m))&&runtime.exit(c)}var d="",m=n;-1!==g.indexOf("/")&&(d=g.substring(0,g.indexOf("/")));runtime.setCurrentDirectory(d);l?(runtime.log(l),runtime.exit(1)):null===m?(runtime.log("No code found for "+g),runtime.exit(1)):h.apply(null,f)})}}g=g?Array.prototype.slice.call(g):[];"NodeJSRuntime"===runtime.type()?l(process.argv.slice(2)):"RhinoRuntime"===runtime.type()?l(g):l(g. [...]
 +String(typeof arguments)&&arguments);
 +// Input 2
- 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)}};
++core.Async=function(){this.forEach=function(g,l,f){function p(d){h!==n&&(d?(h=n,f(d)):(h+=1,h===n&&f(null)))}var r,n=g.length,h=0;for(r=0;r<n;r+=1)l(g[r],p)};this.destroyAll=function(g,l){function f(p,r){if(r)l(r);else if(p<g.length)g[p](function(g){f(p+1,g)});else l()}f(0,void 0)}};
 +// Input 3
- 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();
++function makeBase64(){function g(a){var b,c=a.length,e=new Uint8Array(new ArrayBuffer(c));for(b=0;b<c;b+=1)e[b]=a.charCodeAt(b)&255;return e}function l(a){var b,c="",e,q=a.length-2;for(e=0;e<q;e+=3)b=a[e]<<16|a[e+1]<<8|a[e+2],c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b>>>18],c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b>>>12&63],c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b>>>6&63],c+="ABCDEFGHIJKLMNOPQRSTUV [...]
++63];e===q+1?(b=a[e]<<4,c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b>>>6],c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b&63],c+="=="):e===q&&(b=a[e]<<10|a[e+1]<<2,c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b>>>12],c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b>>>6&63],c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b&63],c+="=");return c}function f(a){a=a.replace( [...]
++"");var b=a.length,c=new Uint8Array(new ArrayBuffer(3*b)),e=a.length%4,q=0,d,f;for(d=0;d<b;d+=4)f=(k[a.charAt(d)]||0)<<18|(k[a.charAt(d+1)]||0)<<12|(k[a.charAt(d+2)]||0)<<6|(k[a.charAt(d+3)]||0),c[q]=f>>16,c[q+1]=f>>8&255,c[q+2]=f&255,q+=3;b=3*b-[0,0,2,1][e];return c.subarray(0,b)}function p(a){var b,c,e=a.length,q=0,k=new Uint8Array(new ArrayBuffer(3*e));for(b=0;b<e;b+=1)c=a[b],128>c?k[q++]=c:(2048>c?k[q++]=192|c>>>6:(k[q++]=224|c>>>12&15,k[q++]=128|c>>>6&63),k[q++]=128|c&63);return k. [...]
++q)}function r(a){var b,c,e,q,k=a.length,d=new Uint8Array(new ArrayBuffer(k)),f=0;for(b=0;b<k;b+=1)c=a[b],128>c?d[f++]=c:(b+=1,e=a[b],224>c?d[f++]=(c&31)<<6|e&63:(b+=1,q=a[b],d[f++]=(c&15)<<12|(e&63)<<6|q&63));return d.subarray(0,f)}function n(a){return l(g(a))}function h(a){return String.fromCharCode.apply(String,f(a))}function d(a){return r(g(a))}function m(a){a=r(a);for(var b="",c=0;c<a.length;)b+=String.fromCharCode.apply(String,a.subarray(c,c+45E3)),c+=45E3;return b}function c(a,b,c [...]
++k,d="";for(k=b;k<c;k+=1)b=a.charCodeAt(k)&255,128>b?d+=String.fromCharCode(b):(k+=1,e=a.charCodeAt(k)&255,224>b?d+=String.fromCharCode((b&31)<<6|e&63):(k+=1,q=a.charCodeAt(k)&255,d+=String.fromCharCode((b&15)<<12|(e&63)<<6|q&63)));return d}function e(a,b){function e(){var d=k+1E5;d>a.length&&(d=a.length);q+=c(a,k,d);k=d;d=k===a.length;b(q,d)&&!d&&runtime.setTimeout(e,0)}var q="",k=0;1E5>a.length?b(c(a,0,a.length),!0):("string"!==typeof a&&(a=a.slice()),e())}function a(a){return p(g(a))} [...]
++p(a))}function q(a){return String.fromCharCode.apply(String,p(g(a)))}var k=function(a){var b={},c,e;c=0;for(e=a.length;c<e;c+=1)b[a.charAt(c)]=c;return b}("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),t,A,w=runtime.getWindow(),x,v;w&&w.btoa?(x=w.btoa,t=function(a){return x(q(a))}):(x=n,t=function(b){return l(a(b))});w&&w.atob?(v=w.atob,A=function(a){a=v(a);return c(a,0,a.length)}):(v=h,A=function(a){return m(f(a))});core.Base64=function(){this.convertByteArrayToBas [...]
++l;this.convertBase64ToByteArray=this.convertBase64ToUTF8Array=f;this.convertUTF16ArrayToByteArray=this.convertUTF16ArrayToUTF8Array=p;this.convertByteArrayToUTF16Array=this.convertUTF8ArrayToUTF16Array=r;this.convertUTF8StringToBase64=n;this.convertBase64ToUTF8String=h;this.convertUTF8StringToUTF16Array=d;this.convertByteArrayToUTF16String=this.convertUTF8ArrayToUTF16String=m;this.convertUTF8StringToUTF16String=e;this.convertUTF16StringToByteArray=this.convertUTF16StringToUTF8Array=a;th [...]
++b;this.convertUTF16StringToUTF8String=q;this.convertUTF16StringToBase64=t;this.convertBase64ToUTF16String=A;this.fromBase64=h;this.toBase64=n;this.atob=v;this.btoa=x;this.utob=q;this.btou=e;this.encode=t;this.encodeURI=function(a){return t(a).replace(/[+\/]/g,function(a){return"+"===a?"-":"_"}).replace(/\\=+$/,"")};this.decode=function(a){return A(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,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]}};
++core.ByteArray=function(g){this.pos=0;this.data=g;this.readUInt32LE=function(){this.pos+=4;var g=this.data,f=this.pos;return g[--f]<<24|g[--f]<<16|g[--f]<<8|g[--f]};this.readUInt16LE=function(){this.pos+=2;var g=this.data,f=this.pos;return g[--f]<<8|g[--f]}};
 +// Input 5
- 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}};
++core.ByteArrayWriter=function(g){function l(f){f>r-p&&(r=Math.max(2*r,p+f),f=new Uint8Array(new ArrayBuffer(r)),f.set(n),n=f)}var f=this,p=0,r=1024,n=new Uint8Array(new ArrayBuffer(r));this.appendByteArrayWriter=function(h){f.appendByteArray(h.getByteArray())};this.appendByteArray=function(f){var d=f.length;l(d);n.set(f,p);p+=d};this.appendArray=function(f){var d=f.length;l(d);n.set(f,p);p+=d};this.appendUInt16LE=function(h){f.appendArray([h&255,h>>8&255])};this.appendUInt32LE=function( [...]
++255,h>>8&255,h>>16&255,h>>24&255])};this.appendString=function(h){f.appendByteArray(runtime.byteArrayFromString(h,g))};this.getLength=function(){return p};this.getByteArray=function(){var f=new Uint8Array(new ArrayBuffer(p));f.set(n.subarray(0,p));return f}};
 +// Input 6
- 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)}};
++core.CSSUnits=function(){var g=this,l={"in":1,cm:2.54,mm:25.4,pt:72,pc:12};this.convert=function(f,g,r){return f*l[r]/l[g]};this.convertMeasure=function(f,l){var r,n;f&&l?(r=parseFloat(f),n=f.replace(r.toString(),""),r=g.convert(r,n,l).toString()):r="";return r};this.getUnits=function(f){return f.substr(f.length-2,f.length)}};
 +// Input 7
 +/*
 +
 + 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(){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)})( [...]
++(function(){function g(){var f,g,r,n,h;void 0===l&&(h=(f=runtime.getWindow())&&f.document,l={rangeBCRIgnoresElementBCR:!1,unscaledRangeClientRects:!1},h&&(n=h.createElement("div"),n.style.position="absolute",n.style.left="-99999px",n.style.transform="scale(2)",n.style["-webkit-transform"]="scale(2)",g=h.createElement("div"),n.appendChild(g),h.body.appendChild(n),f=h.createRange(),f.selectNode(g),l.rangeBCRIgnoresElementBCR=0===f.getClientRects().length,g.appendChild(h.createTextNode("Re [...]
++g=g.getBoundingClientRect(),r=f.getBoundingClientRect(),l.unscaledRangeClientRects=2<Math.abs(g.height-r.height),f.detach(),h.body.removeChild(n),f=Object.keys(l).map(function(d){return d+":"+String(l[d])}).join(", "),runtime.log("Detected browser quirks - "+f)));return l}var l;core.DomUtils=function(){function f(a,b){return 0>=a.compareBoundaryPoints(Range.START_TO_START,b)&&0<=a.compareBoundaryPoints(Range.END_TO_END,b)}function l(a,b){return 0>=a.compareBoundaryPoints(Range.END_TO_ST [...]
++a.compareBoundaryPoints(Range.START_TO_END,b)}function r(a,b){var c=null;a.nodeType===Node.TEXT_NODE&&(0===a.length?(a.parentNode.removeChild(a),b.nodeType===Node.TEXT_NODE&&(c=b)):(b.nodeType===Node.TEXT_NODE&&(a.appendData(b.data),b.parentNode.removeChild(b)),c=a));return c}function n(a){for(var b=a.parentNode;a.firstChild;)b.insertBefore(a.firstChild,a);b.removeChild(a);return b}function h(a,b){for(var c=a.parentNode,e=a.firstChild,d;e;)d=e.nextSibling,h(e,b),e=d;b(a)&&(c=n(a));retur [...]
++b){return a===b||Boolean(a.compareDocumentPosition(b)&Node.DOCUMENT_POSITION_CONTAINED_BY)}function m(a,b){for(var c=0,e;a.parentNode!==b;)runtime.assert(null!==a.parentNode,"parent is null"),a=a.parentNode;for(e=b.firstChild;e!==a;)c+=1,e=e.nextSibling;return c}function c(a,b,e){Object.keys(b).forEach(function(k){var d=k.split(":"),f=d[1],h=e(d[0]),d=b[k];"object"===typeof d&&Object.keys(d).length?(k=h?a.getElementsByTagNameNS(h,f)[0]||a.ownerDocument.createElementNS(h,k):a.getElements [...]
++a.ownerDocument.createElement(k),a.appendChild(k),c(k,d,e)):h&&a.setAttributeNS(h,k,String(d))})}var e=null;this.splitBoundaries=function(a){var b=[],c,e;if(a.startContainer.nodeType===Node.TEXT_NODE||a.endContainer.nodeType===Node.TEXT_NODE){if(c=a.endContainer){c=a.endOffset;e=a.endContainer;if(c<e.childNodes.length)for(e=e.childNodes.item(c),c=0;e.firstChild;)e=e.firstChild;else for(;e.lastChild;)e=e.lastChild,c=e.nodeType===Node.TEXT_NODE?e.textContent.length:e.childNodes.length;c={ [...]
++offset:c}}a.setEnd(c.container,c.offset);c=a.endContainer;0!==a.endOffset&&c.nodeType===Node.TEXT_NODE&&(e=c,a.endOffset!==e.length&&(b.push(e.splitText(a.endOffset)),b.push(e)));c=a.startContainer;0!==a.startOffset&&c.nodeType===Node.TEXT_NODE&&(e=c,a.startOffset!==e.length&&(c=e.splitText(a.startOffset),b.push(e),b.push(c),a.setStart(c,0)))}return b};this.containsRange=f;this.rangesIntersect=l;this.getNodesInRange=function(a,b){for(var c=[],e=a.commonAncestorContainer,d,f=a.startConta [...]
++Node.TEXT_NODE?e.parentNode:e,NodeFilter.SHOW_ALL,b,!1),e=f.currentNode=a.startContainer;e;){d=b(e);if(d===NodeFilter.FILTER_ACCEPT)c.push(e);else if(d===NodeFilter.FILTER_REJECT)break;e=e.parentNode}c.reverse();for(e=f.nextNode();e;)c.push(e),e=f.nextNode();return c};this.normalizeTextNodes=function(a){a&&a.nextSibling&&(a=r(a,a.nextSibling));a&&a.previousSibling&&r(a.previousSibling,a)};this.rangeContainsNode=function(a,b){var c=b.ownerDocument.createRange(),e=b.ownerDocument.createRa [...]
++a.startOffset);c.setEnd(a.endContainer,a.endOffset);e.selectNodeContents(b);d=f(c,e);c.detach();e.detach();return d};this.mergeIntoParent=n;this.removeUnwantedNodes=h;this.getElementsByTagNameNS=function(a,b,c){var e=[];a=a.getElementsByTagNameNS(b,c);e.length=c=a.length;for(b=0;b<c;b+=1)e[b]=a.item(b);return e};this.rangeIntersectsNode=function(a,b){var c=b.ownerDocument.createRange(),e;c.selectNodeContents(b);e=l(a,c);c.detach();return e};this.containsNode=function(a,b){return a===b|| [...]
++this.comparePoints=function(a,b,c,e){if(a===c)return e-b;var d=a.compareDocumentPosition(c);2===d?d=-1:4===d?d=1:10===d?(b=m(a,c),d=b<e?1:-1):(e=m(c,a),d=e<b?-1:1);return d};this.adaptRangeDifferenceToZoomLevel=function(a,b){return g().unscaledRangeClientRects?a:a/b};this.getBoundingClientRect=function(a){var b=a.ownerDocument,c=g();if((!1===c.unscaledRangeClientRects||c.rangeBCRIgnoresElementBCR)&&a.nodeType===Node.ELEMENT_NODE)return a.getBoundingClientRect();var d;e?d=e:e=d=b.createR [...]
++b.selectNode(a);return b.getBoundingClientRect()};this.mapKeyValObjOntoNode=function(a,b,c){Object.keys(b).forEach(function(e){var d=e.split(":"),f=d[1],d=c(d[0]),h=b[e];d?(f=a.getElementsByTagNameNS(d,f)[0],f||(f=a.ownerDocument.createElementNS(d,e),a.appendChild(f)),f.textContent=h):runtime.log("Key ignored: "+e)})};this.removeKeyElementsFromNode=function(a,b,c){b.forEach(function(b){var e=b.split(":"),d=e[1];(e=c(e[0]))?(d=a.getElementsByTagNameNS(e,d)[0])?d.parentNode.removeChild(d) [...]
++b+" not found."):runtime.log("Property Name ignored: "+b)})};this.getKeyValRepresentationOfNode=function(a,b){for(var c={},e=a.firstElementChild,d;e;){if(d=b(e.namespaceURI))c[d+":"+e.localName]=e.textContent;e=e.nextElementSibling}return c};this.mapObjOntoNode=c;(function(a){var b,c;c=runtime.getWindow();null!==c&&(b=c.navigator.appVersion.toLowerCase(),c=-1===b.indexOf("chrome")&&(-1!==b.indexOf("applewebkit")||-1!==b.indexOf("safari")),b=b.indexOf("msie"),c||b)&&(a.containsNode=d)})( [...]
 +// Input 8
 +/*
 +
 + 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(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]=[]})()};
++core.EventNotifier=function(g){var l={};this.emit=function(f,g){var r,n;runtime.assert(l.hasOwnProperty(f),'unknown event fired "'+f+'"');n=l[f];for(r=0;r<n.length;r+=1)n[r](g)};this.subscribe=function(f,g){runtime.assert(l.hasOwnProperty(f),'tried to subscribe to unknown event "'+f+'"');l[f].push(g);runtime.log('event "'+f+'" subscribed.')};this.unsubscribe=function(f,g){var r;runtime.assert(l.hasOwnProperty(f),'tried to unsubscribe from unknown event "'+f+'"');r=l[f].indexOf(g);runtim [...]
++r,'tried to unsubscribe unknown callback from event "'+f+'"');-1!==r&&l[f].splice(r,1);runtime.log('event "'+f+'" unsubscribed.')};(function(){var f,p;for(f=0;f<g.length;f+=1)p=g[f],runtime.assert(!l.hasOwnProperty(p),'Duplicated event ids: "'+p+'" registered more than once.'),l[p]=[]})()};
 +// Input 9
 +/*
 +
 + 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(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";}};
++core.LoopWatchDog=function(g,l){var f=Date.now(),p=0;this.check=function(){var r;if(g&&(r=Date.now(),r-f>g))throw runtime.log("alert","watchdog timeout"),"timeout!";if(0<l&&(p+=1,p>l))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)};
++core.PositionIterator=function(g,l,f,p){function r(){this.acceptNode=function(a){return!a||a.nodeType===b&&0===a.length?t:k}}function n(a){this.acceptNode=function(c){return!c||c.nodeType===b&&0===c.length?t:a.acceptNode(c)}}function h(){var a=c.currentNode,d=a.nodeType;e=d===b?a.length-1:d===q?1:0}function d(){if(null===c.previousSibling()){if(!c.parentNode()||c.currentNode===g)return c.firstChild(),!1;e=0}else h();return!0}var m=this,c,e,a,b=Node.TEXT_NODE,q=Node.ELEMENT_NODE,k=NodeFi [...]
++t=NodeFilter.FILTER_REJECT;this.nextPosition=function(){var a=c.currentNode,d=a.nodeType;if(a===g)return!1;if(0===e&&d===q)null===c.firstChild()&&(e=1);else if(d===b&&e+1<a.length)e+=1;else if(null!==c.nextSibling())e=0;else if(c.parentNode())e=1;else return!1;return!0};this.previousPosition=function(){var a=!0,q=c.currentNode;0===e?a=d():q.nodeType===b?e-=1:null!==c.lastChild()?h():q===g?a=!1:e=0;return a};this.previousNode=d;this.container=function(){var a=c.currentNode,d=a.nodeType;0 [...]
++b&&(a=a.parentNode);return a};this.rightNode=function(){var d=c.currentNode,f=d.nodeType;if(f===b&&e===d.length)for(d=d.nextSibling;d&&a(d)!==k;)d=d.nextSibling;else f===q&&1===e&&(d=null);return d};this.leftNode=function(){var b=c.currentNode;if(0===e)for(b=b.previousSibling;b&&a(b)!==k;)b=b.previousSibling;else if(b.nodeType===q)for(b=b.lastChild;b&&a(b)!==k;)b=b.previousSibling;return b};this.getCurrentNode=function(){return c.currentNode};this.unfilteredDomOffset=function(){if(c.cur [...]
++b)return e;for(var a=0,d=c.currentNode,d=1===e?d.lastChild:d.previousSibling;d;)a+=1,d=d.previousSibling;return a};this.getPreviousSibling=function(){var a=c.currentNode,b=c.previousSibling();c.currentNode=a;return b};this.getNextSibling=function(){var a=c.currentNode,b=c.nextSibling();c.currentNode=a;return b};this.setUnfilteredPosition=function(d,q){var f,h;runtime.assert(null!==d&&void 0!==d,"PositionIterator.setUnfilteredPosition called without container");c.currentNode=d;if(d.nodeT [...]
++q,runtime.assert(q<=d.length,"Error in setPosition: "+q+" > "+d.length),runtime.assert(0<=q,"Error in setPosition: "+q+" < 0"),q===d.length&&(c.nextSibling()?e=0:c.parentNode()?e=1:runtime.assert(!1,"Error in setUnfilteredPosition: position not valid.")),!0;f=a(d);for(h=d.parentNode;h&&h!==g&&f===k;)f=a(h),f!==k&&(c.currentNode=h),h=h.parentNode;q<d.childNodes.length&&f!==NodeFilter.FILTER_REJECT?(c.currentNode=d.childNodes.item(q),f=a(c.currentNode),e=0):e=1;f===NodeFilter.FILTER_REJEC [...]
++k)return m.nextPosition();runtime.assert(a(c.currentNode)===k,"PositionIterater.setUnfilteredPosition call resulted in an non-visible node being set");return!0};this.moveToEnd=function(){c.currentNode=g;e=1};this.moveToEndOfNode=function(a){a.nodeType===b?m.setUnfilteredPosition(a,a.length):(c.currentNode=a,e=1)};this.getNodeFilter=function(){return a};a=(f?new n(f):new r).acceptNode;a.acceptNode=a;l=l||4294967295;runtime.assert(g.nodeType!==Node.TEXT_NODE,"Internet Explorer doesn't all [...]
++c=g.ownerDocument.createTreeWalker(g,l,a,p);e=0;null===c.firstChild()&&(e=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}};
++core.RawInflate=function(){function g(a,b,c,e,d,q){this.BMAX=16;this.N_MAX=288;this.status=0;this.root=null;this.m=0;var f=Array(this.BMAX+1),k,h,I,g,m,s,l,n=Array(this.BMAX+1),r,p,v,t=new core.zip_HuftNode,W=Array(this.BMAX);g=Array(this.N_MAX);var u,y=Array(this.BMAX+1),z,Q,B;B=this.root=null;for(m=0;m<f.length;m++)f[m]=0;for(m=0;m<n.length;m++)n[m]=0;for(m=0;m<W.length;m++)W[m]=null;for(m=0;m<g.length;m++)g[m]=0;for(m=0;m<y.length;m++)y[m]=0;k=256<b?a[256]:this.BMAX;r=a;p=0;m=b;do f[ [...]
++while(0<--m);if(f[0]===b)this.root=null,this.status=this.m=0;else{for(s=1;s<=this.BMAX&&0===f[s];s++);l=s;q<s&&(q=s);for(m=this.BMAX;0!==m&&0===f[m];m--);I=m;q>m&&(q=m);for(z=1<<s;s<m;s++,z<<=1)if(z-=f[s],0>z){this.status=2;this.m=q;return}z-=f[m];if(0>z)this.status=2,this.m=q;else{f[m]+=z;y[1]=s=0;r=f;p=1;for(v=2;0<--m;)s+=r[p++],y[v++]=s;r=a;m=p=0;do s=r[p++],0!==s&&(g[y[s]++]=m);while(++m<b);b=y[I];y[0]=m=0;r=g;p=0;g=-1;u=n[0]=0;v=null;Q=0;for(l=l-1+1;l<=I;l++)for(a=f[l];0<a--;){for( [...]
++n[1+g];g++;Q=I-u;Q=Q>q?q:Q;s=l-u;h=1<<s;if(h>a+1)for(h-=a+1,v=l;++s<Q;){h<<=1;if(h<=f[++v])break;h-=f[v]}u+s>k&&u<k&&(s=k-u);Q=1<<s;n[1+g]=s;v=Array(Q);for(h=0;h<Q;h++)v[h]=new core.zip_HuftNode;B=null===B?this.root=new core.zip_HuftList:B.next=new core.zip_HuftList;B.next=null;B.list=v;W[g]=v;0<g&&(y[g]=m,t.b=n[g],t.e=16+s,t.t=v,s=(m&(1<<u)-1)>>u-n[g],W[g-1][s].e=t.e,W[g-1][s].b=t.b,W[g-1][s].n=t.n,W[g-1][s].t=t.t)}t.b=l-u;p>=b?t.e=99:r[p]<c?(t.e=256>r[p]?16:15,t.n=r[p++]):(t.e=d[r[p]- [...]
++c]);h=1<<l-u;for(s=m>>u;s<Q;s+=h)v[s].e=t.e,v[s].b=t.b,v[s].n=t.n,v[s].t=t.t;for(s=1<<l-1;0!==(m&s);s>>=1)m^=s;for(m^=s;(m&(1<<u)-1)!==y[g];)u-=n[g],g--}this.m=n[1];this.status=0!==z&&1!==I?1:0}}}function l(c){for(;b<c;){var e=a,d;d=s.length===H?-1:s[H++];a=e|d<<b;b+=8}}function f(b){return a&y[b]}function p(c){a>>=c;b-=c}function r(a,b,c){var e,k,I;if(0===c)return 0;for(I=0;;){l(v);k=w.list[f(v)];for(e=k.e;16<e;){if(99===e)return-1;p(k.b);e-=16;l(e);k=k.t[f(e)];e=k.e}p(k.b);if(16===e)d [...]
++I++]=h[d++]=k.n;else{if(15===e)break;l(e);t=k.n+f(e);p(e);l(u);k=x.list[f(u)];for(e=k.e;16<e;){if(99===e)return-1;p(k.b);e-=16;l(e);k=k.t[f(e)];e=k.e}p(k.b);l(e);A=d-k.n-f(e);for(p(e);0<t&&I<c;)t--,A&=32767,d&=32767,a[b+I++]=h[d++]=h[A++]}if(I===c)return c}q=-1;return I}function n(a,b,c){var e,d,q,k,h,m,s,n=Array(316);for(e=0;e<n.length;e++)n[e]=0;l(5);m=257+f(5);p(5);l(5);s=1+f(5);p(5);l(4);e=4+f(4);p(4);if(286<m||30<s)return-1;for(d=0;d<e;d++)l(3),n[Q[d]]=f(3),p(3);for(d=e;19>d;d++)n[ [...]
++7;d=new g(n,19,19,null,null,v);if(0!==d.status)return-1;w=d.root;v=d.m;k=m+s;for(e=q=0;e<k;)if(l(v),h=w.list[f(v)],d=h.b,p(d),d=h.n,16>d)n[e++]=q=d;else if(16===d){l(2);d=3+f(2);p(2);if(e+d>k)return-1;for(;0<d--;)n[e++]=q}else{17===d?(l(3),d=3+f(3),p(3)):(l(7),d=11+f(7),p(7));if(e+d>k)return-1;for(;0<d--;)n[e++]=0;q=0}v=9;d=new g(n,m,257,B,L,v);0===v&&(d.status=1);if(0!==d.status)return-1;w=d.root;v=d.m;for(e=0;e<s;e++)n[e]=n[e+m];u=6;d=new g(n,s,0,I,W,u);x=d.root;u=d.m;return 0===u&&25 [...]
++-1:r(a,b,c)}var h=[],d,m=null,c,e,a,b,q,k,t,A,w,x,v,u,s,H,y=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535],B=[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],L=[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],I=[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],W=[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],Q=[16,17,18, [...]
++10,5,11,4,12,3,13,2,14,1,15],z;this.inflate=function(y,Q){h.length=65536;b=a=d=0;q=-1;k=!1;t=A=0;w=null;s=y;H=0;var G=new Uint8Array(new ArrayBuffer(Q));a:for(var Z=0,O;Z<Q&&(!k||-1!==q);){if(0<t){if(0!==q)for(;0<t&&Z<Q;)t--,A&=32767,d&=32767,G[0+Z]=h[d]=h[A],Z+=1,d+=1,A+=1;else{for(;0<t&&Z<Q;)t-=1,d&=32767,l(8),G[0+Z]=h[d]=f(8),Z+=1,d+=1,p(8);0===t&&(q=-1)}if(Z===Q)break}if(-1===q){if(k)break;l(1);0!==f(1)&&(k=!0);p(1);l(2);q=f(2);p(2);w=null;t=0}switch(q){case 0:O=G;var aa=0+Z,J=Q-Z,F [...]
++b&7;p(F);l(16);F=f(16);p(16);l(16);if(F!==(~a&65535))O=-1;else{p(16);t=F;for(F=0;0<t&&F<J;)t--,d&=32767,l(8),O[aa+F++]=h[d++]=f(8),p(8);0===t&&(q=-1);O=F}break;case 1:if(null!==w)O=r(G,0+Z,Q-Z);else b:{O=G;aa=0+Z;J=Q-Z;if(null===m){for(var C=void 0,F=Array(288),C=void 0,C=0;144>C;C++)F[C]=8;for(C=144;256>C;C++)F[C]=9;for(C=256;280>C;C++)F[C]=7;for(C=280;288>C;C++)F[C]=8;e=7;C=new g(F,288,257,B,L,e);if(0!==C.status){alert("HufBuild error: "+C.status);O=-1;break b}m=C.root;e=C.m;for(C=0;3 [...]
++5;z=5;C=new g(F,30,0,I,W,z);if(1<C.status){m=null;alert("HufBuild error: "+C.status);O=-1;break b}c=C.root;z=C.m}w=m;x=c;v=e;u=z;O=r(O,aa,J)}break;case 2:O=null!==w?r(G,0+Z,Q-Z):n(G,0+Z,Q-Z);break;default:O=-1}if(-1===O)break a;Z+=O}s=new Uint8Array(new ArrayBuffer(0));return G}};
 +// Input 12
- 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()}};
++core.ScheduledTask=function(g,l){function f(){n&&(runtime.clearTimeout(r),n=!1)}function p(){f();g.apply(void 0,h);h=null}var r,n=!1,h=[];this.trigger=function(){h=Array.prototype.slice.call(arguments);n||(n=!0,r=runtime.setTimeout(p,l))};this.triggerImmediate=function(){h=Array.prototype.slice.call(arguments);p()};this.processRequests=function(){n&&p()};this.cancel=f;this.destroy=function(d){f();d()}};
 +// Input 13
 +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}};
++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 f="<?xml version='1.0' encoding='UTF-8'?>",f=f+"<office:document";Object.keys(l).forEach(function(g){f+=" xmlns:"+g+'="'+l[g]+'"'});f+=">";f+=g;f+="</office:document>";return runtime.parseXML(f)};
++core.UnitTestRunner=function(){function g(d){h+=1;runtime.log("fail",d)}function l(d,c){var e;try{if(d.length!==c.length)return g("array of length "+d.length+" should be "+c.length+" long"),!1;for(e=0;e<d.length;e+=1)if(d[e]!==c[e])return g(d[e]+" should be "+c[e]+" at array index "+e),!1}catch(a){return!1}return!0}function f(d,c,e){var a=d.attributes,b=a.length,q,k,h;for(q=0;q<b;q+=1)if(k=a.item(q),"xmlns"!==k.prefix&&"urn:webodf:names:steps"!==k.namespaceURI){h=c.getAttributeNS(k.name [...]
++if(!c.hasAttributeNS(k.namespaceURI,k.localName))return g("Attribute "+k.localName+" with value "+k.value+" was not present"),!1;if(h!==k.value)return g("Attribute "+k.localName+" was "+h+" should be "+k.value),!1}return e?!0:f(c,d,!0)}function p(d,c){var e,a;e=d.nodeType;a=c.nodeType;if(e!==a)return g("Nodetype '"+e+"' should be '"+a+"'"),!1;if(e===Node.TEXT_NODE){if(d.data===c.data)return!0;g("Textnode data '"+d.data+"' should be '"+c.data+"'");return!1}runtime.assert(e===Node.ELEMENT [...]
++if(d.namespaceURI!==c.namespaceURI)return g("namespace '"+d.namespaceURI+"' should be '"+c.namespaceURI+"'"),!1;if(d.localName!==c.localName)return g("localName '"+d.localName+"' should be '"+c.localName+"'"),!1;if(!f(d,c,!1))return!1;e=d.firstChild;for(a=c.firstChild;e;){if(!a)return g("Nodetype '"+e.nodeType+"' is unexpected here."),!1;if(!p(e,a))return!1;e=e.nextSibling;a=a.nextSibling}return a?(g("Nodetype '"+a.nodeType+"' is missing here."),!1):!0}function r(f,c){return 0===c?f===c [...]
++c:f===c?!0:"number"===typeof c&&isNaN(c)?"number"===typeof f&&isNaN(f):Object.prototype.toString.call(c)===Object.prototype.toString.call([])?l(f,c):"object"===typeof c&&"object"===typeof f?c.constructor===Element||c.constructor===Node?p(c,f):d(c,f):!1}function n(d,c,e){"string"===typeof c&&"string"===typeof e||runtime.log("WARN: shouldBe() expects string arguments");var a,b;try{b=eval(c)}catch(q){a=q}d=eval(e);a?g(c+" should be "+d+". Threw exception "+a):r(b,d)?runtime.log("pass",c+"  [...]
++String(typeof d)?(e=0===b&&0>1/b?"-0":String(b),g(c+" should be "+d+". Was "+e+".")):g(c+" should be "+d+" (of type "+typeof d+"). Was "+b+" (of type "+typeof b+").")}var h=0,d;d=function(d,c){var e=Object.keys(d),a=Object.keys(c);e.sort();a.sort();return l(e,a)&&Object.keys(d).every(function(a){var e=d[a],f=c[a];return r(e,f)?!0:(g(e+" should be "+f+" for key "+a),!1)})};this.areNodesEqual=p;this.shouldBeNull=function(d,c){n(d,c,"null")};this.shouldBeNonNull=function(d,c){var e,a;try{a [...]
++b}e?g(c+" should be non-null. Threw exception "+e):null!==a?runtime.log("pass",c+" is non-null."):g(c+" should be non-null. Was "+a)};this.shouldBe=n;this.countFailedTests=function(){return h};this.name=function(d){var c,e,a=[],b=d.length;a.length=b;for(c=0;c<b;c+=1){e=Runtime.getFunctionName(d[c])||"";if(""===e)throw"Found a function without a name.";a[c]={f:d[c],name:e}}return a}};
++core.UnitTester=function(){function g(f,g){return"<span style='color:blue;cursor:pointer' onclick='"+g+"'>"+f+"</span>"}var l=0,f={};this.runTests=function(p,r,n){function h(a){if(0===a.length)f[d]=e,l+=m.countFailedTests(),r();else{b=a[0].f;var q=a[0].name;runtime.log("Running "+q);k=m.countFailedTests();c.setUp();b(function(){c.tearDown();e[q]=k===m.countFailedTests();h(a.slice(1))})}}var d=Runtime.getFunctionName(p)||"",m=new core.UnitTestRunner,c=new p(m),e={},a,b,q,k,t="BrowserRunt [...]
++if(f.hasOwnProperty(d))runtime.log("Test "+d+" has already run.");else{t?runtime.log("<span>Running "+g(d,'runSuite("'+d+'");')+": "+c.description()+"</span>"):runtime.log("Running "+d+": "+c.description);q=c.tests();for(a=0;a<q.length;a+=1)b=q[a].f,p=q[a].name,n.length&&-1===n.indexOf(p)||(t?runtime.log("<span>Running "+g(p,'runTest("'+d+'","'+p+'")')+"</span>"):runtime.log("Running "+p),k=m.countFailedTests(),c.setUp(),b(),c.tearDown(),e[p]=k===m.countFailedTests());h(c.asyncTests())} [...]
++function(){return l};this.results=function(){return f}};
 +// Input 14
- 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}};
++core.Utils=function(){function g(l,f){if(f&&Array.isArray(f)){l=l||[];if(!Array.isArray(l))throw"Destination is not an array.";l=l.concat(f.map(function(f){return g(null,f)}))}else if(f&&"object"===typeof f){l=l||{};if("object"!==typeof l)throw"Destination is not an object.";Object.keys(f).forEach(function(p){l[p]=g(l[p],f[p])})}else l=f;return l}this.hashString=function(g){var f=0,p,r;p=0;for(r=g.length;p<r;p+=1)f=(f<<5)-f+g.charCodeAt(p),f|=0;return f};this.mergeObjects=function(l,f){ [...]
++g(l[p],f[p])});return l}};
 +// Input 15
 +/*
 +
 + 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,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 [...]
++core.Zip=function(g,l){function f(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 [...]
 +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],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)})})};
++2932959818,3654703836,1088359270,936918E3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117],c,e,d=a.length,q=0,q=0;c=-1;for(e=0;e<d;e+=1)q=(c^a[e])&255,q=b[q],c=c>>>8^q;return c^-1}function p(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 r(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 c,e,d,q,f,h,g,m=this;this.load=function(b){if(null!==m.data)b(null,m.data);else{var c=f+34+e+d+256;c+g>k&&(c=k-g);runtime.read(a,g,c,function(c,e){if(c||null===e)b(c,e);else a:{var d=e,k=new core.ByteArray(d),g=k.readUInt32LE(),s;if(67324752!==g)b("File entry signature is wrong."+g.toString()+" "+d.length.toString(),null);else{k.pos+=22;g=k.readUInt16LE();s=k.readUInt16LE();k.p [...]
++d.subarray(k.pos,k.pos+f);if(f!==d.length){b("The amount of compressed bytes read was "+d.length.toString()+" instead of "+f.toString()+" for "+m.filename+" in "+a+".",null);break a}d=A(d,h)}else d=d.subarray(k.pos,k.pos+h);h!==d.length?b("The amount of bytes read was "+d.length.toString()+" instead of "+h.toString()+" for "+m.filename+" in "+a+".",null):(m.data=d,b(null,d))}}})}};this.set=function(a,b,c,e){m.filename=a;m.data=b;m.compressed=c;m.date=e};this.error=null;b&&(c=b.readUInt3 [...]
++c?this.error="Central directory entry has wrong signature at position "+(b.pos-4).toString()+' for file "'+a+'": '+b.data.length.toString():(b.pos+=6,q=b.readUInt16LE(),this.date=p(b.readUInt32LE()),b.readUInt32LE(),f=b.readUInt32LE(),h=b.readUInt32LE(),e=b.readUInt16LE(),d=b.readUInt16LE(),c=b.readUInt16LE(),b.pos+=8,g=b.readUInt32LE(),this.filename=runtime.byteArrayToString(b.data.subarray(b.pos,b.pos+e),"utf8"),this.data=null,b.pos+=e+d+c))}function h(a,b){if(22!==a.length)b("Central [...]
++w);else{var c=new core.ByteArray(a),e;e=c.readUInt32LE();101010256!==e?b("Central directory signature is wrong: "+e.toString(),w):(e=c.readUInt16LE(),0!==e?b("Zip files with non-zero disk numbers are not supported.",w):(e=c.readUInt16LE(),0!==e?b("Zip files with non-zero disk numbers are not supported.",w):(e=c.readUInt16LE(),t=c.readUInt16LE(),e!==t?b("Number of entries is inconsistent.",w):(e=c.readUInt32LE(),c=c.readUInt16LE(),c=k-22-e,runtime.read(g,c,k-c,function(a,c){if(a||null=== [...]
++new core.ByteArray(c),d,f;q=[];for(d=0;d<t;d+=1){f=new n(g,e);if(f.error){b(f.error,w);break a}q[q.length]=f}b(null,w)}})))))}}function d(a,b){var c=null,e,d;for(d=0;d<q.length;d+=1)if(e=q[d],e.filename===a){c=e;break}c?c.data?b(null,c.data):c.load(b):b(a+" not found.",null)}function m(a){var b=new core.ByteArrayWriter("utf8"),c=0;b.appendArray([80,75,3,4,20,0,0,0,0,0]);a.data&&(c=a.data.length);b.appendUInt32LE(r(a.date));b.appendUInt32LE(a.data?f(a.data):0);b.appendUInt32LE(c);b.appen [...]
++b.appendUInt16LE(a.filename.length);b.appendUInt16LE(0);b.appendString(a.filename);a.data&&b.appendByteArray(a.data);return b}function c(a,b){var c=new core.ByteArrayWriter("utf8"),e=0;c.appendArray([80,75,1,2,20,0,20,0,0,0,0,0]);a.data&&(e=a.data.length);c.appendUInt32LE(r(a.date));c.appendUInt32LE(a.data?f(a.data):0);c.appendUInt32LE(e);c.appendUInt32LE(e);c.appendUInt16LE(a.filename.length);c.appendArray([0,0,0,0,0,0,0,0,0,0,0,0]);c.appendUInt32LE(b);c.appendString(a.filename);return [...]
++b){if(a===q.length)b(null);else{var c=q[a];null!==c.data?e(a+1,b):c.load(function(c){c?b(c):e(a+1,b)})}}function a(a,b){e(0,function(e){if(e)b(e);else{var d,f,k=new core.ByteArrayWriter("utf8"),h=[0];for(d=0;d<q.length;d+=1)k.appendByteArrayWriter(m(q[d])),h.push(k.getLength());e=k.getLength();for(d=0;d<q.length;d+=1)f=q[d],k.appendByteArrayWriter(c(f,h[d]));d=k.getLength()-e;k.appendArray([80,75,5,6,0,0,0,0]);k.appendUInt16LE(q.length);k.appendUInt16LE(q.length);k.appendUInt32LE(d);k.a [...]
++k.appendArray([0,0]);a(k.getByteArray())}})}function b(b,c){a(function(a){runtime.writeFile(b,a,c)},c)}var q,k,t,A=(new core.RawInflate).inflate,w=this,x=new core.Base64;this.load=d;this.save=function(a,b,c,e){var d,f;for(d=0;d<q.length;d+=1)if(f=q[d],f.filename===a){f.set(a,b,c,e);return}f=new n(g);f.set(a,b,c,e);q.push(f)};this.remove=function(a){var b,c;for(b=0;b<q.length;b+=1)if(c=q[b],c.filename===a)return q.splice(b,1),!0;return!1};this.write=function(a){b(g,a)};this.writeAs=b;thi [...]
++a;this.loadContentXmlAsFragments=function(a,b){w.loadAsString(a,function(a,c){if(a)return b.rootElementReady(a);b.rootElementReady(null,c,!0)})};this.loadAsString=function(a,b){d(a,function(a,c){if(a||null===c)return b(a,null);var e=runtime.byteArrayToString(c,"utf8");b(null,e)})};this.loadAsDOM=function(a,b){w.loadAsString(a,function(a,c){if(a||null===c)b(a,null);else{var e=(new DOMParser).parseFromString(c,"text/xml");b(null,e)}})};this.loadAsDataURL=function(a,b,c){d(a,function(a,e){ [...]
++null);var d=0,f;b||(b=80===e[1]&&78===e[2]&&71===e[3]?"image/png":255===e[0]&&216===e[1]&&255===e[2]?"image/jpeg":71===e[0]&&73===e[1]&&70===e[2]?"image/gif":"");for(f="data:"+b+";base64,";d<e.length;)f+=x.convertUTF8ArrayToBase64(e.subarray(d,Math.min(d+45E3,e.length))),d+=45E3;c(null,f)})};this.getEntries=function(){return q.slice()};k=-1;null===l?q=[]:runtime.getFileSize(g,function(a){k=a;0>k?l("File '"+g+"' cannot be read.",w):runtime.read(g,k-22,22,function(a,b){a||null===l||null== [...]
++h(b,l)})})};
 +// 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)})()};
++gui.Avatar=function(g,l){var f=this,p,r,n;this.setColor=function(f){r.style.borderColor=f};this.setImageUrl=function(h){f.isVisible()?r.src=h:n=h};this.isVisible=function(){return"block"===p.style.display};this.show=function(){n&&(r.src=n,n=void 0);p.style.display="block"};this.hide=function(){p.style.display="none"};this.markAsFocussed=function(f){p.className=f?"active":""};this.destroy=function(f){g.removeChild(p);f()};(function(){var f=g.ownerDocument,d=f.documentElement.namespaceURI [...]
++"div");r=f.createElementNS(d,"img");r.width=64;r.height=64;p.appendChild(r);p.style.width="64px";p.style.height="70px";p.style.position="absolute";p.style.top="-80px";p.style.left="-34px";p.style.display=l?"block":"none";g.appendChild(p)})()};
 +// 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)};
++gui.EditInfoHandle=function(g){var l=[],f,p=g.ownerDocument,r=p.documentElement.namespaceURI;this.setEdits=function(g){l=g;var h,d,m,c;f.innerHTML="";for(g=0;g<l.length;g+=1)h=p.createElementNS(r,"div"),h.className="editInfo",d=p.createElementNS(r,"span"),d.className="editInfoColor",d.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",l[g].memberid),m=p.createElementNS(r,"span"),m.className="editInfoAuthor",m.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",l[g [...]
++c=p.createElementNS(r,"span"),c.className="editInfoTime",c.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",l[g].memberid),c.innerHTML=l[g].time,h.appendChild(d),h.appendChild(m),h.appendChild(c),f.appendChild(h)};this.show=function(){f.style.display="block"};this.hide=function(){f.style.display="none"};this.destroy=function(l){g.removeChild(f);l()};f=p.createElementNS(r,"div");f.setAttribute("class","editInfoHandle");f.style.display="none";g.appendChild(f)};
 +// 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/
 +*/
- 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 [...]
++gui.KeyboardHandler=function(){function g(f,g){g||(g=l.None);return f+":"+g}var l=gui.KeyboardHandler.Modifier,f=null,p={};this.setDefault=function(g){f=g};this.bind=function(f,l,h){f=g(f,l);runtime.assert(!1===p.hasOwnProperty(f),"tried to overwrite the callback handler of key combo: "+f);p[f]=h};this.unbind=function(f,l){var h=g(f,l);delete p[h]};this.reset=function(){f=null;p={}};this.handleEvent=function(r){var n=r.keyCode,h=l.None;r.metaKey&&(h|=l.Meta);r.ctrlKey&&(h|=l.Ctrl);r.alt [...]
++r.shiftKey&&(h|=l.Shift);n=g(n,h);n=p[n];h=!1;n?h=n():null!==f&&(h=f(r));h&&(r.preventDefault?r.preventDefault():r.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/
 +*/
 +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;
++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",metans:"urn:oasis:names:tc:opendocument:xmlns:meta:1.0",numberns:"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0",officens:"urn:oasis:names:tc:opendoc [...]
++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"};
++(function(){var g=odf.Namespaces.namespaceMap,l=odf.Namespaces.prefixMap,f;for(f in g)g.hasOwnProperty(f)&&(l[g[f]]=f)})();odf.Namespaces.forEachPrefix=function(g){var l=odf.Namespaces.namespaceMap,f;for(f in l)l.hasOwnProperty(f)&&g(f,l[f])};odf.Namespaces.lookupNamespaceURI=function(g){var l=null;odf.Namespaces.namespaceMap.hasOwnProperty(g)&&(l=odf.Namespaces.namespaceMap[g]);return l};odf.Namespaces.lookupPrefix=function(g){var l=odf.Namespaces.prefixMap;return l.hasOwnProperty(g)?l [...]
++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 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}};
++odf.OdfUtils=function(){function g(a){return"image"===(a&&a.localName)&&a.namespaceURI===y}function l(a){return null!==a&&a.nodeType===Node.ELEMENT_NODE&&"frame"===a.localName&&a.namespaceURI===y&&"as-char"===a.getAttributeNS(H,"anchor-type")}function f(a){var b;(b="annotation"===(a&&a.localName)&&a.namespaceURI===odf.Namespaces.officens)||(b="div"===(a&&a.localName)&&"annotationWrapper"===a.className);return b}function p(a){var b=a&&a.localName;return("p"===b||"h"===b)&&a.namespaceURI= [...]
++!p(a);)a=a.parentNode;return a}function n(a){return/^[ \t\r\n]+$/.test(a)}function h(a){if(null===a||a.nodeType!==Node.ELEMENT_NODE)return!1;var b=a.localName;return/^(span|p|h|a|meta)$/.test(b)&&a.namespaceURI===H||"span"===b&&"annotationHighlight"===a.className}function d(a){var b=a&&a.localName,c=!1;b&&(a=a.namespaceURI,a===H&&(c="s"===b||"tab"===b||"line-break"===b));return c}function m(a){return d(a)||l(a)||f(a)}function c(a){var b=a&&a.localName,c=!1;b&&(a=a.namespaceURI,a===H&&(c [...]
++return c}function e(a){for(;null!==a.firstChild&&h(a);)a=a.firstChild;return a}function a(a){for(;null!==a.lastChild&&h(a);)a=a.lastChild;return a}function b(b){for(;!p(b)&&null===b.previousSibling;)b=b.parentNode;return p(b)?null:a(b.previousSibling)}function q(a){for(;!p(a)&&null===a.nextSibling;)a=a.parentNode;return p(a)?null:e(a.nextSibling)}function k(a){for(var e=!1;a;)if(a.nodeType===Node.TEXT_NODE)if(0===a.length)a=b(a);else return!n(a.data.substr(a.length-1,1));else m(a)?(e=!1 [...]
++null):a=b(a);return e}function t(a){var b=!1,c;for(a=a&&e(a);a;){c=a.nodeType===Node.TEXT_NODE?a.length:0;if(0<c&&!n(a.data)){b=!0;break}if(m(a)){b=!0;break}a=q(a)}return b}function A(a,b){return n(a.data.substr(b))?!t(q(a)):!1}function w(a,c){var e=a.data,d;if(!n(e[c])||m(a.parentNode))return!1;0<c?n(e[c-1])||(d=!0):k(b(a))&&(d=!0);return!0===d?A(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 [...]
++{value:parseFloat(a[1]),unit:a[3]}:null}function v(a){return(a=x(a))&&(0>a.value||"%"===a.unit)?null:a}function u(a){return(a=x(a))&&"%"!==a.unit?null:a}function s(a){switch(a.namespaceURI){case odf.Namespaces.drawns:case odf.Namespaces.svgns:case odf.Namespaces.dr3dns:return!1;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! [...]
++var H=odf.Namespaces.textns,y=odf.Namespaces.drawns,B=/^\s*$/,L=new core.DomUtils;this.isImage=g;this.isCharacterFrame=l;this.isInlineRoot=f;this.isTextSpan=function(a){return"span"===(a&&a.localName)&&a.namespaceURI===H};this.isParagraph=p;this.getParagraphElement=r;this.isWithinTrackedChanges=function(a,b){for(;a&&a!==b;){if(a.namespaceURI===H&&"tracked-changes"===a.localName)return!0;a=a.parentNode}return!1};this.isListItem=function(a){return"list-item"===(a&&a.localName)&&a.namespac [...]
++this.isLineBreak=function(a){return"line-break"===(a&&a.localName)&&a.namespaceURI===H};this.isODFWhitespace=n;this.isGroupingElement=h;this.isCharacterElement=d;this.isAnchoredAsCharacterElement=m;this.isSpaceElement=c;this.firstChild=e;this.lastChild=a;this.previousNode=b;this.nextNode=q;this.scanLeftForNonSpace=k;this.lookLeftForCharacter=function(a){var c,e=c=0;a.nodeType===Node.TEXT_NODE&&(e=a.length);0<e?(c=a.data,c=n(c.substr(e-1,1))?1===e?k(b(a))?2:0:n(c.substr(e-2,1))?0:2:1):m( [...]
++return c};this.lookRightForCharacter=function(a){var b=!1,c=0;a&&a.nodeType===Node.TEXT_NODE&&(c=a.length);0<c?b=!n(a.data.substr(0,1)):m(a)&&(b=!0);return b};this.scanLeftForAnyCharacter=function(c){var e=!1,d;for(c=c&&a(c);c;){d=c.nodeType===Node.TEXT_NODE?c.length:0;if(0<d&&!n(c.data)){e=!0;break}if(m(c)){e=!0;break}c=b(c)}return e};this.scanRightForAnyCharacter=t;this.isTrailingWhitespace=A;this.isSignificantWhitespace=w;this.isDowngradableSpaceElement=function(a){return a.namespace [...]
++a.localName?k(b(a))&&t(q(a)):!1};this.getFirstNonWhitespaceChild=function(a){for(a=a&&a.firstChild;a&&a.nodeType===Node.TEXT_NODE&&B.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||u(a)};this.parseFoLineHeight=function(a){return v(a)||u(a)};this.getImpactedParagraphs=function(a){var b,c,e;b=a.commonAncestorContainer;var d=[],f=[];for(b.nodeType===N [...]
++(d=L.getElementsByTagNameNS(b,H,"p").concat(L.getElementsByTagNameNS(b,H,"h")));b&&!p(b);)b=b.parentNode;b&&d.push(b);c=d.length;for(b=0;b<c;b+=1)e=d[b],L.rangeIntersectsNode(a,e)&&f.push(e);return f};this.getTextNodes=function(a,b){var c=a.startContainer.ownerDocument.createRange(),e;e=L.getNodesInRange(a,function(e){c.selectNodeContents(e);if(e.nodeType===Node.TEXT_NODE){if(b&&L.rangesIntersect(a,c)||L.containsRange(a,c))return Boolean(r(e)&&(!n(e.textContent)||w(e,0)))?NodeFilter.FIL [...]
++NodeFilter.FILTER_REJECT}else if(L.rangesIntersect(a,c)&&s(e))return NodeFilter.FILTER_SKIP;return NodeFilter.FILTER_REJECT});c.detach();return e};this.getTextElements=function(a,b,c){var e=a.startContainer.ownerDocument.createRange(),f;f=L.getNodesInRange(a,function(f){e.selectNodeContents(f);if(d(f.parentNode))return NodeFilter.FILTER_REJECT;if(f.nodeType===Node.TEXT_NODE){if(b&&L.rangesIntersect(a,e)||L.containsRange(a,e))if(c||Boolean(r(f)&&(!n(f.textContent)||w(f,0))))return NodeFi [...]
++L.rangesIntersect(a,e)||L.containsRange(a,e))return NodeFilter.FILTER_ACCEPT}else if(s(f)||h(f))return NodeFilter.FILTER_SKIP;return NodeFilter.FILTER_REJECT});e.detach();return f};this.getParagraphElements=function(a){var b=a.startContainer.ownerDocument.createRange(),c;c=L.getNodesInRange(a,function(c){b.selectNodeContents(c);if(p(c)){if(L.rangesIntersect(a,b))return NodeFilter.FILTER_ACCEPT}else if(s(c)||h(c))return NodeFilter.FILTER_SKIP;return NodeFilter.FILTER_REJECT});b.detach(); [...]
++this.getImageElements=function(a){var b=a.startContainer.ownerDocument.createRange(),c;c=L.getNodesInRange(a,function(c){b.selectNodeContents(c);return g(c)&&L.containsRange(a,b)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP});b.detach();return c}};
 +// 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/
 +*/
- 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){};
++ops.Server=function(){};ops.Server.prototype.connect=function(g,l){};ops.Server.prototype.networkStatus=function(){};ops.Server.prototype.login=function(g,l,f,p){};ops.Server.prototype.joinSession=function(g,l,f,p){};ops.Server.prototype.leaveSession=function(g,l,f,p){};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();
++function createXPathSingleton(){function g(c,a,b){return-1!==c&&(c<a||-1===a)&&(c<b||-1===b)}function l(e){for(var a=[],b=0,d=e.length,f;b<d;){var h=e,m=d,l=a,n="",p=[],r=h.indexOf("[",b),s=h.indexOf("/",b),H=h.indexOf("=",b);g(s,r,H)?(n=h.substring(b,s),b=s+1):g(r,s,H)?(n=h.substring(b,r),b=c(h,r,p)):g(H,s,r)?(n=h.substring(b,H),b=H):(n=h.substring(b,m),b=m);l.push({location:n,predicates:p});if(b<d&&"="===e[b]){f=e.substring(b+1,d);if(2<f.length&&("'"===f[0]||'"'===f[0]))f=f.slice(1,f. [...]
++else try{f=parseInt(f,10)}catch(y){}b=d}}return{steps:a,value:f}}function f(){var c=null,a=!1;this.setNode=function(a){c=a};this.reset=function(){a=!1};this.next=function(){var b=a?null:c;a=!0;return b}}function p(c,a,b){this.reset=function(){c.reset()};this.next=function(){for(var d=c.next();d;){d.nodeType===Node.ELEMENT_NODE&&(d=d.getAttributeNodeNS(a,b));if(d)break;d=c.next()}return d}}function r(c,a){var b=c.next(),d=null;this.reset=function(){c.reset();b=c.next();d=null};this.next= [...]
++d.firstChild)d=d.firstChild;else{for(;!d.nextSibling&&d!==b;)d=d.parentNode;d===b?b=c.next():d=d.nextSibling}else{do(d=b.firstChild)||(b=c.next());while(b&&!d)}if(d&&d.nodeType===Node.ELEMENT_NODE)return d}return null}}function n(c,a){this.reset=function(){c.reset()};this.next=function(){for(var b=c.next();b&&!a(b);)b=c.next();return b}}function h(c,a,b){a=a.split(":",2);var d=b(a[0]),f=a[1];return new n(c,function(a){return a.localName===f&&a.namespaceURI===d})}function d(c,a,b){var d= [...]
++a,b),h=a.value;return void 0===h?new n(c,function(a){d.setNode(a);k.reset();return null!==k.next()}):new n(c,function(a){d.setNode(a);k.reset();return(a=k.next())?a.nodeValue===h:!1})}var m,c;c=function(c,a,b){for(var d=a,f=c.length,h=0;d<f;)"]"===c[d]?(h-=1,0>=h&&b.push(l(c.substring(a,d)))):"["===c[d]&&(0>=h&&(a=d+1),h+=1),d+=1;return d};m=function(c,a,b){var f,k,g,m;for(f=0;f<a.steps.length;f+=1){g=a.steps[f];k=g.location;if(""===k)c=new r(c,!1);else if("@"===k[0]){k=k.substr(1).spli [...]
++b(k[0]);if(!m)throw"No namespace associated with the prefix "+k[0];c=new p(c,m,k[1])}else"."!==k&&(c=new r(c,!1),-1!==k.indexOf(":")&&(c=h(c,k,b)));for(k=0;k<g.predicates.length;k+=1)m=g.predicates[k],c=d(c,m,b)}return c};return{getODFElementsWithXPath:function(c,a,b){var d=c.ownerDocument,k=[],h=null;if(d&&"function"===typeof d.evaluate)for(b=d.evaluate(a,c,b,XPathResult.UNORDERED_NODE_ITERATOR_TYPE,null),h=b.iterateNext();null!==h;)h.nodeType===Node.ELEMENT_NODE&&k.push(h),h=b.iterate [...]
++new f;k.setNode(c);c=l(a);k=m(k,c,b);c=[];for(b=k.next();b;)c.push(b),b=k.next();k=c}return k}}}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)};
++core.Cursor=function(g,l){function f(a){a.parentNode&&(d.push(a.previousSibling),d.push(a.nextSibling),a.parentNode.removeChild(a))}function p(a,b,c){if(b.nodeType===Node.TEXT_NODE){runtime.assert(Boolean(b),"putCursorIntoTextNode: invalid container");var e=b.parentNode;runtime.assert(Boolean(e),"putCursorIntoTextNode: container without parent");runtime.assert(0<=c&&c<=b.length,"putCursorIntoTextNode: offset is out of bounds");0===c?e.insertBefore(a,b):(c!==b.length&&b.splitText(c),e.in [...]
++b.nextSibling))}else b.nodeType===Node.ELEMENT_NODE&&b.insertBefore(a,b.childNodes.item(c));d.push(a.previousSibling);d.push(a.nextSibling)}var r=g.createElementNS("urn:webodf:names:cursor","cursor"),n=g.createElementNS("urn:webodf:names:cursor","anchor"),h,d=[],m=g.createRange(),c,e=new core.DomUtils;this.getNode=function(){return r};this.getAnchorNode=function(){return n.parentNode?n:r};this.getSelectedRange=function(){c?(m.setStartBefore(r),m.collapse(!0)):(m.setStartAfter(h?n:r),m.s [...]
++r:n));return m};this.setSelectedRange=function(a,b){m&&m!==a&&m.detach();m=a;h=!1!==b;(c=a.collapsed)?(f(n),f(r),p(r,a.startContainer,a.startOffset)):(f(n),f(r),p(h?r:n,a.endContainer,a.endOffset),p(h?n:r,a.startContainer,a.startOffset));d.forEach(e.normalizeTextNodes);d.length=0};this.hasForwardSelection=function(){return h};this.remove=function(){f(r);d.forEach(e.normalizeTextNodes);d.length=0};r.setAttributeNS("urn:webodf:names:cursor","memberId",l);n.setAttributeNS("urn:webodf:names [...]
++l)};
 +// 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]}};
++runtime.loadClass("core.PositionFilter");core.PositionFilterChain=function(){var g={},l=core.PositionFilter.FilterResult.FILTER_ACCEPT,f=core.PositionFilter.FilterResult.FILTER_REJECT;this.acceptPosition=function(p){for(var r in g)if(g.hasOwnProperty(r)&&g[r].acceptPosition(p)===f)return f;return l};this.addFilter=function(f,l){g[f]=l};this.removeFilter=function(f){delete g[f]}};
 +// 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/
 +*/
 +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)}}};
++gui.AnnotationViewManager=function(g,l,f){function p(a){var b=a.node,d=a.end;a=m.createRange();d&&(a.setStart(b,b.childNodes.length),a.setEnd(d,0),d=c.getTextNodes(a,!1),d.forEach(function(a){var c=m.createElement("span"),d=b.getAttributeNS(odf.Namespaces.officens,"name");c.className="annotationHighlight";c.setAttribute("annotation",d);a.parentNode.insertBefore(c,a);c.appendChild(a)}));a.detach()}function r(a){var b=g.getSizer();a?(f.style.display="inline-block",b.style.paddingRight=e.g [...]
++(f.style.display="none",b.style.paddingRight=0);g.refreshSize()}function n(){d.sort(function(a,b){return a.node.compareDocumentPosition(b.node)===Node.DOCUMENT_POSITION_FOLLOWING?-1:1})}function h(){var a;for(a=0;a<d.length;a+=1){var b=d[a],c=b.node.parentElement,e=c.nextElementSibling,h=e.nextElementSibling,m=c.parentElement,l=0,l=d[d.indexOf(b)-1],n=void 0,b=g.getZoomLevel();c.style.left=(f.getBoundingClientRect().left-m.getBoundingClientRect().left)/b+"px";c.style.width=f.getBounding [...]
++b+"px";e.style.width=parseFloat(c.style.left)-30+"px";l&&(n=l.node.parentElement.getBoundingClientRect(),20>=(m.getBoundingClientRect().top-n.bottom)/b?c.style.top=Math.abs(m.getBoundingClientRect().top-n.bottom)/b+20+"px":c.style.top="0px");h.style.left=e.getBoundingClientRect().width/b+"px";var e=h.style,m=h.getBoundingClientRect().left/b,l=h.getBoundingClientRect().top/b,n=c.getBoundingClientRect().left/b,r=c.getBoundingClientRect().top/b,p=0,s=0,p=n-m,p=p*p,s=r-l,s=s*s,m=Math.sqrt(p [...]
++m+"px";l=Math.asin((c.getBoundingClientRect().top-h.getBoundingClientRect().top)/(b*parseFloat(h.style.width)));h.style.transform="rotate("+l+"rad)";h.style.MozTransform="rotate("+l+"rad)";h.style.WebkitTransform="rotate("+l+"rad)";h.style.msTransform="rotate("+l+"rad)"}}var d=[],m=l.ownerDocument,c=new odf.OdfUtils,e=runtime.getWindow();runtime.assert(Boolean(e),"Expected to be run in an environment which has a global window, like a browser.");this.rerenderAnnotations=h;this.addAnnotat [...]
++d.push({node:a.node,end:a.end});n();var b=m.createElement("div"),c=m.createElement("div"),e=m.createElement("div"),f=m.createElement("div"),g=m.createElement("div"),l=a.node;b.className="annotationWrapper";l.parentNode.insertBefore(b,l);c.className="annotationNote";c.appendChild(l);g.className="annotationRemoveButton";c.appendChild(g);e.className="annotationConnector horizontal";f.className="annotationConnector angular";b.appendChild(c);b.appendChild(e);b.appendChild(f);a.end&&p(a);h()} [...]
++function(){for(;d.length;){var a=d[0],b=d.indexOf(a),c=a.node,e=c.parentNode.parentNode;"div"===e.localName&&(e.parentNode.insertBefore(c,e),e.parentNode.removeChild(e));a=a.node.getAttributeNS(odf.Namespaces.officens,"name");a=m.querySelectorAll('span.annotationHighlight[annotation="'+a+'"]');e=c=void 0;for(c=0;c<a.length;c+=1){for(e=a.item(c);e.firstChild;)e.parentNode.insertBefore(e.firstChild,e);e.parentNode.removeChild(e)}-1!==b&&d.splice(b,1);0===d.length&&r(!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("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})();
++gui.SelectionMover=function(g,l){function f(){w.setUnfilteredPosition(g.getNode(),0);return w}function p(a,b){var c,d=null;a&&0<a.length&&(c=b?a.item(a.length-1):a.item(0));c&&(d={top:c.top,left:b?c.right:c.left,bottom:c.bottom});return d}function r(a,b,c,d){var e=a.nodeType;c.setStart(a,b);c.collapse(!d);d=p(c.getClientRects(),!0===d);!d&&0<b&&(c.setStart(a,b-1),c.setEnd(a,b),d=p(c.getClientRects(),!0));d||(e===Node.ELEMENT_NODE&&0<b&&a.childNodes.length>=b?d=r(a,b-1,c,!0):a.nodeType== [...]
++0<b?d=r(a,b-1,c,!0):a.previousSibling?d=r(a.previousSibling,a.previousSibling.nodeType===Node.TEXT_NODE?a.previousSibling.textContent.length:a.previousSibling.childNodes.length,c,!0):a.parentNode&&a.parentNode!==l?d=r(a.parentNode,0,c,!1):(c.selectNode(l),d=p(c.getClientRects(),!1)));runtime.assert(Boolean(d),"No visible rectangle found");return d}function n(a,b,c){var d=a,e=f(),h,k=l.ownerDocument.createRange(),q=g.getSelectedRange().cloneRange(),m;for(h=r(e.container(),e.unfilteredDom [...]
++d&&c();)d-=1;b?(b=e.container(),e=e.unfilteredDomOffset(),-1===A.comparePoints(q.startContainer,q.startOffset,b,e)?(q.setStart(b,e),m=!1):q.setEnd(b,e)):(q.setStart(e.container(),e.unfilteredDomOffset()),q.collapse(!0));g.setSelectedRange(q,m);e=f();q=r(e.container(),e.unfilteredDomOffset(),k);if(q.top===h.top||void 0===x)x=q.left;runtime.clearTimeout(v);v=runtime.setTimeout(function(){x=void 0},2E3);k.detach();return a-d}function h(a){var b=f();return a.acceptPosition(b)===u&&(b.setUnf [...]
++0),a.acceptPosition(b)===u)?!0:!1}function d(a,b,c){for(var d=new core.LoopWatchDog(1E4),e=0,f=0,h=0<=b?1:-1,k=0<=b?a.nextPosition:a.previousPosition;0!==b&&k();)d.check(),f+=h,c.acceptPosition(a)===u&&(b-=h,e+=f,f=0);return e}function m(a,b,c){for(var d=f(),e=new core.LoopWatchDog(1E4),h=0,k=0;0<a&&d.nextPosition();)e.check(),c.acceptPosition(d)===u&&(h+=1,b.acceptPosition(d)===u&&(k+=h,h=0,a-=1));return k}function c(a,b,c){for(var d=f(),e=new core.LoopWatchDog(1E4),h=0,k=0;0<a&&d.prev [...]
++c.acceptPosition(d)===u&&(h+=1,b.acceptPosition(d)===u&&(k+=h,h=0,a-=1));return k}function e(a,b){var c=f();return d(c,a,b)}function a(a,b,c){var e=f(),h=t.getParagraphElement(e.getCurrentNode()),k=0;e.setUnfilteredPosition(a,b);c.acceptPosition(e)!==u&&(k=d(e,-1,c),0===k||h&&h!==t.getParagraphElement(e.getCurrentNode()))&&(e.setUnfilteredPosition(a,b),k=d(e,1,c));return k}function b(a,b){var c=f(),d=0,e=0,h=0>a?-1:1;for(a=Math.abs(a);0<a;){for(var k=b,q=h,g=c,m=g.container(),n=0,p=null [...]
++t=10,w=void 0,A=0,F=void 0,C=void 0,Y=void 0,w=void 0,U=l.ownerDocument.createRange(),R=new core.LoopWatchDog(1E4),w=r(m,g.unfilteredDomOffset(),U),F=w.top,C=void 0===x?w.left:x,Y=F;!0===(0>q?g.previousPosition():g.nextPosition());)if(R.check(),k.acceptPosition(g)===u&&(n+=1,m=g.container(),w=r(m,g.unfilteredDomOffset(),U),w.top!==F)){if(w.top!==Y&&Y!==F)break;Y=w.top;w=Math.abs(C-w.left);if(null===p||w<t)p=m,v=g.unfilteredDomOffset(),t=w,A=n}null!==p?(g.setUnfilteredPosition(p,v),n=A): [...]
++d+=n;if(0===d)break;e+=d;a-=1}return e*h}function q(a,b){var c,d,e,h,k=f(),q=t.getParagraphElement(k.getCurrentNode()),g=0,m=l.ownerDocument.createRange();0>a?(c=k.previousPosition,d=-1):(c=k.nextPosition,d=1);for(e=r(k.container(),k.unfilteredDomOffset(),m);c.call(k);)if(b.acceptPosition(k)===u){if(t.getParagraphElement(k.getCurrentNode())!==q)break;h=r(k.container(),k.unfilteredDomOffset(),m);if(h.bottom!==e.bottom&&(e=h.top>=e.top&&h.bottom<e.bottom||h.top<=e.top&&h.bottom>e.bottom,! [...]
++d;e=h}m.detach();return g}function k(a,b,c){runtime.assert(null!==a,"SelectionMover.countStepsToPosition called with element===null");var d=f(),e=d.container(),h=d.unfilteredDomOffset(),k=0,q=new core.LoopWatchDog(1E4);for(d.setUnfilteredPosition(a,b);c.acceptPosition(d)!==u&&d.previousPosition();)q.check();a=d.container();runtime.assert(Boolean(a),"SelectionMover.countStepsToPosition: positionIterator.container() returned null");b=d.unfilteredDomOffset();for(d.setUnfilteredPosition(e,h [...]
++u&&d.previousPosition();)q.check();e=A.comparePoints(a,b,d.container(),d.unfilteredDomOffset());if(0>e)for(;d.nextPosition()&&(q.check(),c.acceptPosition(d)===u&&(k+=1),d.container()!==a||d.unfilteredDomOffset()!==b););else if(0<e)for(;d.previousPosition()&&(q.check(),c.acceptPosition(d)!==u||(k-=1,d.container()!==a||d.unfilteredDomOffset()!==b)););return k}var t=new odf.OdfUtils,A=new core.DomUtils,w,x,v,u=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.movePointForward=function(a, [...]
++b||!1,w.nextPosition)};this.movePointBackward=function(a,b){return n(a,b||!1,w.previousPosition)};this.getStepCounter=function(){return{countSteps:e,convertForwardStepsBetweenFilters:m,convertBackwardStepsBetweenFilters:c,countLinesSteps:b,countStepsToLineBoundary:q,countStepsToPosition:k,isPositionWalkable:h,countPositionsToNearestStep:a}};(function(){w=gui.SelectionMover.createPositionIterator(l);var a=l.ownerDocument.createRange();a.setStart(w.container(),w.unfilteredDomOffset());a.c [...]
++g.setSelectedRange(a)})()};gui.SelectionMover.createPositionIterator=function(g){var l=new function(){this.acceptNode=function(f){return f&&"urn:webodf:names:cursor"!==f.namespaceURI&&"urn:webodf:names:editinfo"!==f.namespaceURI?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT}};return new core.PositionIterator(g,5,l,!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 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) 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 31
++// Input 30
 +/*
 +
 + 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(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 [...]
++odf.Style2CSS=function(){function g(a){var b,c,d,e={};if(!a)return e;for(a=a.firstElementChild;a;){if(c=a.namespaceURI!==k||"style"!==a.localName&&"default-style"!==a.localName?a.namespaceURI===w&&"list-style"===a.localName?"list":a.namespaceURI!==k||"page-layout"!==a.localName&&"default-page-layout"!==a.localName?void 0:"page":a.getAttributeNS(k,"family"))(b=a.getAttributeNS(k,"name"))||(b=""),e.hasOwnProperty(c)?d=e[c]:e[c]=d={},d[b]=a;a=a.nextElementSibling}return e}function l(a,b){i [...]
++var c,d=null;for(c in a)if(a.hasOwnProperty(c)&&(d=l(a[c].derivedStyles,b)))break;return d}function f(a,b,c){var d,e,h;if(!b.hasOwnProperty(a))return null;d=new odf.StyleTreeNode(b[a]);e=d.element.getAttributeNS(k,"parent-style-name");h=null;e&&(h=l(c,e)||f(e,b,c));h?h.derivedStyles[a]=d:c[a]=d;delete b[a];return d}function p(a,b){for(var c in a)a.hasOwnProperty(c)&&f(c,a,b)}function r(a,b,c){var d=[];c=c.derivedStyles;var e;var f=u[a],h;void 0===f?b=null:(h=b?"["+f+'|style-name="'+b+'" [...]
++f&&(f="draw",h=b?'[presentation|style-name="'+b+'"]':""),b=f+"|"+s[a].join(h+","+f+"|")+h);null!==b&&d.push(b);for(e in c)c.hasOwnProperty(e)&&(b=r(a,e,c[e]),d=d.concat(b));return d}function n(a,b,c){for(a=a&&a.firstElementChild;a&&(a.namespaceURI!==b||a.localName!==c);)a=a.nextElementSibling;return a}function h(a,b){var c="",d,e,f;for(d=0;d<b.length;d+=1)if(e=b[d],f=a.getAttributeNS(e[0],e[1])){f=f.trim();if(G.hasOwnProperty(e[1])){var h=f.indexOf(" "),k=void 0,q=void 0;-1!==h?(k=f.sub [...]
++q=f.substring(h)):(k=f,q="");(k=O.parseLength(k))&&"pt"===k.unit&&0.75>k.value&&(f="0.75pt"+q)}e[2]&&(c+=e[2]+":"+f+";")}return c}function d(a){return(a=n(a,k,"text-properties"))?O.parseFoFontSize(a.getAttributeNS(b,"font-size")):null}function m(a,b,c,d){return b+b+c+c+d+d}function c(a,c,d,e){c='text|list[text|style-name="'+c+'"]';var f=d.getAttributeNS(w,"level");d=n(d,k,"list-level-properties");d=n(d,k,"list-level-label-alignment");var h,q;d&&(h=d.getAttributeNS(b,"text-indent"),q=d.g [...]
++"margin-left"));h||(h="-0.6cm");d="-"===h.charAt(0)?h.substring(1):"-"+h;for(f=f&&parseInt(f,10);1<f;)c+=" > text|list-item > text|list",f-=1;if(q){f=c+" > text|list-item > *:not(text|list):first-child";f+="{";f=f+("margin-left:"+q+";")+"}";try{a.insertRule(f,a.cssRules.length)}catch(g){runtime.log("cannot load rule: "+f)}}e=c+" > text|list-item > *:not(text|list):first-child:before{"+e+";";e=e+"counter-increment:list;"+("margin-left:"+h+";");e+="width:"+d+";";e+="display:inline-block}" [...]
++a.cssRules.length)}catch(m){runtime.log("cannot load rule: "+e)}}function e(f,g,l,p){if("list"===g)for(var s=p.element.firstChild,t,u;s;){if(s.namespaceURI===w)if(t=s,"list-level-style-number"===s.localName){var G=t;u=G.getAttributeNS(k,"num-format");var T=G.getAttributeNS(k,"num-suffix")||"",G=G.getAttributeNS(k,"num-prefix")||"",$={1:"decimal",a:"lower-latin",A:"upper-latin",i:"lower-roman",I:"upper-roman"},X="";G&&(X+=' "'+G+'"');X=$.hasOwnProperty(u)?X+(" counter(list, "+$[u]+")"):u [...]
++'"'):X+" ''";u="content:"+X+' "'+T+'"';c(f,l,t,u)}else"list-level-style-image"===s.localName?(u="content: none;",c(f,l,t,u)):"list-level-style-bullet"===s.localName&&(u="content: '"+t.getAttributeNS(w,"bullet-char")+"';",c(f,l,t,u));s=s.nextSibling}else if("page"===g){if(u=p.element,G=T=l="",s=n(u,k,"page-layout-properties"))if(t=u.getAttributeNS(k,"name"),l+=h(s,ja),(T=n(s,k,"background-image"))&&(G=T.getAttributeNS(x,"href"))&&(l=l+("background-image: url('odfkit:"+G+"');")+h(T,y)),"p [...]
++aa)for(u=(u=n(u.parentNode.parentElement,q,"master-styles"))&&u.firstElementChild;u;){if(u.namespaceURI===k&&"master-page"===u.localName&&u.getAttributeNS(k,"page-layout-name")===t){G=u.getAttributeNS(k,"name");T="draw|page[draw|master-page-name="+G+"] {"+l+"}";G="office|body, draw|page[draw|master-page-name="+G+"] {"+h(s,ka)+" }";try{f.insertRule(T,f.cssRules.length),f.insertRule(G,f.cssRules.length)}catch(da){throw da;}}u=u.nextElementSibling}else if("text"===aa){T="office|text {"+l+" [...]
++s.getAttributeNS(b,"page-width")+";}";try{f.insertRule(T,f.cssRules.length),f.insertRule(G,f.cssRules.length)}catch(S){throw S;}}}else{l=r(g,l,p).join(",");s="";if(t=n(p.element,k,"text-properties")){G=t;u=X="";T=1;t=""+h(G,H);$=G.getAttributeNS(k,"text-underline-style");"solid"===$&&(X+=" underline");$=G.getAttributeNS(k,"text-line-through-style");"solid"===$&&(X+=" line-through");X.length&&(t+="text-decoration:"+X+";");if(X=G.getAttributeNS(k,"font-name")||G.getAttributeNS(b,"font-fam [...]
++t+="font-family: "+($||X)+";";$=G.parentElement;if(G=d($)){for(;$;){if(G=d($)){if("%"!==G.unit){u="font-size: "+G.value*T+G.unit+";";break}T*=G.value/100}G=$;X=$="";$=null;"default-style"===G.localName?$=null:($=G.getAttributeNS(k,"parent-style-name"),X=G.getAttributeNS(k,"family"),$=C.getODFElementsWithXPath(J,$?"//style:*[@style:name='"+$+"'][@style:family='"+X+"']":"//style:default-style[@style:family='"+X+"']",odf.Namespaces.lookupNamespaceURI)[0])}u||(u="font-size: "+parseFloat(F)* [...]
++";");t+=u}s+=t}if(t=n(p.element,k,"paragraph-properties"))u=t,t=""+h(u,B),(T=n(u,k,"background-image"))&&(G=T.getAttributeNS(x,"href"))&&(t=t+("background-image: url('odfkit:"+G+"');")+h(T,y)),(u=u.getAttributeNS(b,"line-height"))&&"normal"!==u&&(u=O.parseFoLineHeight(u),t="%"!==u.unit?t+("line-height: "+u.value+u.unit+";"):t+("line-height: "+u.value/100+";")),s+=t;if(t=n(p.element,k,"graphic-properties"))G=t,t=""+h(G,L),u=G.getAttributeNS(a,"opacity"),T=G.getAttributeNS(a,"fill"),G=G.g [...]
++"fill-color"),"solid"===T||"hatch"===T?G&&"none"!==G?(u=isNaN(parseFloat(u))?1:parseFloat(u)/100,T=G.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i,m),(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)&&(t+="background-color: rgba("+G.r+","+G.g+","+G.b+","+u+");")):t+="background: none;":"none"===T&&(t+="background: none;"),s+=t;if(t=n(p.element,k,"drawing-page-properties"))u=""+h(t,L),"true"===t.getAttributeNS(v,"b [...]
++(u+="background: none;"),s+=u;if(t=n(p.element,k,"table-cell-properties"))t=""+h(t,I),s+=t;if(t=n(p.element,k,"table-row-properties"))t=""+h(t,Q),s+=t;if(t=n(p.element,k,"table-column-properties"))t=""+h(t,W),s+=t;if(t=n(p.element,k,"table-properties"))u=t,t=""+h(u,z),u=u.getAttributeNS(A,"border-model"),"collapsing"===u?t+="border-collapse:collapse;":"separating"===u&&(t+="border-collapse:separate;"),s+=t;if(0!==s.length)try{f.insertRule(l+"{"+s+"}",f.cssRules.length)}catch(ga){throw g [...]
++e(f,g,E,p.derivedStyles[E])}var a=odf.Namespaces.drawns,b=odf.Namespaces.fons,q=odf.Namespaces.officens,k=odf.Namespaces.stylens,t=odf.Namespaces.svgns,A=odf.Namespaces.tablens,w=odf.Namespaces.textns,x=odf.Namespaces.xlinkns,v=odf.Namespaces.presentationns,u={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
++list:["list-item"]},H=[[b,"color","color"],[b,"background-color","background-color"],[b,"font-weight","font-weight"],[b,"font-style","font-style"]],y=[[k,"repeat","background-repeat"]],B=[[b,"background-color","background-color"],[b,"text-align","text-align"],[b,"text-indent","text-indent"],[b,"padding","padding"],[b,"padding-left","padding-left"],[b,"padding-right","padding-right"],[b,"padding-top","padding-top"],[b,"padding-bottom","padding-bottom"],[b,"border-left","border-left"],[b, [...]
++"border-right"],[b,"border-top","border-top"],[b,"border-bottom","border-bottom"],[b,"margin","margin"],[b,"margin-left","margin-left"],[b,"margin-right","margin-right"],[b,"margin-top","margin-top"],[b,"margin-bottom","margin-bottom"],[b,"border","border"]],L=[[b,"background-color","background-color"],[b,"min-height","min-height"],[a,"stroke","border"],[t,"stroke-color","border-color"],[t,"stroke-width","border-width"],[b,"border","border"],[b,"border-left","border-left"],[b,"border-ri [...]
++[b,"border-top","border-top"],[b,"border-bottom","border-bottom"]],I=[[b,"background-color","background-color"],[b,"border-left","border-left"],[b,"border-right","border-right"],[b,"border-top","border-top"],[b,"border-bottom","border-bottom"],[b,"border","border"]],W=[[k,"column-width","width"]],Q=[[k,"row-height","height"],[b,"keep-together",null]],z=[[k,"width","width"],[b,"margin-left","margin-left"],[b,"margin-right","margin-right"],[b,"margin-top","margin-top"],[b,"margin-bottom", [...]
++ja=[[b,"background-color","background-color"],[b,"padding","padding"],[b,"padding-left","padding-left"],[b,"padding-right","padding-right"],[b,"padding-top","padding-top"],[b,"padding-bottom","padding-bottom"],[b,"border","border"],[b,"border-left","border-left"],[b,"border-right","border-right"],[b,"border-top","border-top"],[b,"border-bottom","border-bottom"],[b,"margin","margin"],[b,"margin-left","margin-left"],[b,"margin-right","margin-right"],[b,"margin-top","margin-top"],[b,"margi [...]
++"margin-bottom"]],ka=[[b,"page-width","width"],[b,"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,aa,J,F,C=xmldom.XPath,Y=new core.CSSUnits;this.style2css=function(a,b,c,d,f){for(var h,k,q,m;b.cssRules.length;)b.deleteRule(b.cssRules.length-1);h=null;d&&(h=d.ownerDocument,J=d.parentNode);f&&(h=f.ownerDocument,J=f.parentNode);if(h)for(m in odf.Namespaces.forEachPrefix(function(a,c){k="@ [...]
++a+" url("+c+");";try{b.insertRule(k,b.cssRules.length)}catch(d){}}),Z=c,aa=a,F=runtime.getWindow().getComputedStyle(document.body,null).getPropertyValue("font-size")||"12pt",a=g(d),d=g(f),f={},u)if(u.hasOwnProperty(m))for(q in c=f[m]={},p(a[m],c),p(d[m],c),c)c.hasOwnProperty(q)&&e(b,m,q,c[q])}};
++// 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("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 [...]
++odf.StyleInfo=function(){function g(a,b){var c,d,e,f,h,k=0;if(c=B[a.localName])if(e=c[a.namespaceURI])k=e.length;for(c=0;c<k;c+=1)d=e[c],f=d.ns,h=d.localname,(d=a.getAttributeNS(f,h))&&a.setAttributeNS(f,H[f]+h,b+d);for(e=a.firstElementChild;e;)g(e,b),e=e.nextElementSibling}function l(a,b){var c,d,e,f,h,k=0;if(c=B[a.localName])if(e=c[a.namespaceURI])k=e.length;for(c=0;c<k;c+=1)if(d=e[c],f=d.ns,h=d.localname,d=a.getAttributeNS(f,h))d=d.replace(b,""),a.setAttributeNS(f,H[f]+h,d);for(e=a.f [...]
++b),e=e.nextElementSibling}function f(a,b){var c,d,e,f,h,k=0;if(c=B[a.localName])if(e=c[a.namespaceURI])k=e.length;for(c=0;c<k;c+=1)if(f=e[c],d=f.ns,h=f.localname,d=a.getAttributeNS(d,h))b=b||{},f=f.keyname,b.hasOwnProperty(f)?b[f][d]=1:(h={},h[d]=1,b[f]=h);return b}function p(a,b){var c,d;f(a,b);for(c=a.firstChild;c;)c.nodeType===Node.ELEMENT_NODE&&(d=c,p(d,b)),c=c.nextSibling}function r(a,b,c){this.key=a;this.name=b;this.family=c;this.requires={}}function n(a,b,c){var d=a+'"'+b,e=c[d]; [...]
++new r(d,a,b));return e}function h(a,b,c){var d,e,f,k,q,g=0;d=a.getAttributeNS(v,"name");k=a.getAttributeNS(v,"family");d&&k&&(b=n(d,k,c));if(b){if(d=B[a.localName])if(f=d[a.namespaceURI])g=f.length;for(d=0;d<g;d+=1)if(k=f[d],e=k.ns,q=k.localname,e=a.getAttributeNS(e,q))k=k.keyname,k=n(e,k,c),b.requires[k.key]=k}for(a=a.firstElementChild;a;)h(a,b,c),a=a.nextElementSibling;return c}function d(a,b){var c=b[a.family];c||(c=b[a.family]={});c[a.name]=1;Object.keys(a.requires).forEach(function [...]
++b)})}function m(a,b){var c=h(a,null,{});Object.keys(c).forEach(function(a){a=c[a];var e=b[a.family];e&&e.hasOwnProperty(a.name)&&d(a,b)})}function c(a,b){function d(b){(b=h.getAttributeNS(v,b))&&(a[b]=!0)}var e=["font-name","font-name-asian","font-name-complex"],f,h;for(f=b&&b.firstElementChild;f;)h=f,e.forEach(d),c(a,h),f=f.nextElementSibling}function e(a,b){function c(a){var d=h.getAttributeNS(v,a);d&&b.hasOwnProperty(d)&&h.setAttributeNS(v,"style:"+a,b[d])}var d=["font-name","font-na [...]
++"font-name-complex"],f,h;for(f=a&&a.firstElementChild;f;)h=f,d.forEach(c),e(h,b),f=f.nextElementSibling}var a=odf.Namespaces.chartns,b=odf.Namespaces.dbns,q=odf.Namespaces.dr3dns,k=odf.Namespaces.drawns,t=odf.Namespaces.formns,A=odf.Namespaces.numberns,w=odf.Namespaces.officens,x=odf.Namespaces.presentationns,v=odf.Namespaces.stylens,u=odf.Namespaces.tablens,s=odf.Namespaces.textns,H={"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: [...]
++"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:"},y={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-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:k,en:"caption",ans:k,a:"text-style- [...]
++en:"circle",ans:k,a:"text-style-name"},{ens:k,en:"connector",ans:k,a:"text-style-name"},{ens:k,en:"control",ans:k,a:"text-style-name"},{ens:k,en:"custom-shape",ans:k,a:"text-style-name"},{ens:k,en:"ellipse",ans:k,a:"text-style-name"},{ens:k,en:"frame",ans:k,a:"text-style-name"},{ens:k,en:"line",ans:k,a:"text-style-name"},{ens:k,en:"measure",ans:k,a:"text-style-name"},{ens:k,en:"path",ans:k,a:"text-style-name"},{ens:k,en:"polygon",ans:k,a:"text-style-name"},{ens:k,en:"polyline",ans:k,a:" [...]
++{ens:k,en:"rect",ans:k,a:"text-style-name"},{ens:k,en:"regular-polygon",ans:k,a:"text-style-name"},{ens:w,en:"annotation",ans:k,a:"text-style-name"},{ens:t,en:"column",ans:t,a:"text-style-name"},{ens:v,en:"style",ans:v,a:"next-style-name"},{ens:u,en:"body",ans:u,a:"paragraph-style-name"},{ens:u,en:"even-columns",ans:u,a:"paragraph-style-name"},{ens:u,en:"even-rows",ans:u,a:"paragraph-style-name"},{ens:u,en:"first-column",ans:u,a:"paragraph-style-name"},{ens:u,en:"first-row",ans:u,a:"par [...]
++{ens:u,en:"last-column",ans:u,a:"paragraph-style-name"},{ens:u,en:"last-row",ans:u,a:"paragraph-style-name"},{ens:u,en:"odd-columns",ans:u,a:"paragraph-style-name"},{ens:u,en:"odd-rows",ans:u,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 [...]
++{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:b,en:"query",ans:b,a:"style-name"},{ens:b,en:"table-representation",ans:b,a:"style-name"},{ens:u,en:"background",ans:u,a:"style-name"},{ens:u,en:"table",an [...]
++"table-column":[{ens:b,en:"column",ans:b,a:"style-name"},{ens:u,en:"table-column",ans:u,a:"style-name"}],"table-row":[{ens:b,en:"query",ans:b,a:"default-row-style-name"},{ens:b,en:"table-representation",ans:b,a:"default-row-style-name"},{ens:u,en:"table-row",ans:u,a:"style-name"}],"table-cell":[{ens:b,en:"column",ans:b,a:"default-cell-style-name"},{ens:u,en:"table-column",ans:u,a:"default-cell-style-name"},{ens:u,en:"table-row",ans:u,a:"default-cell-style-name"},{ens:u,en:"body",ans:u,a [...]
++{ens:u,en:"covered-table-cell",ans:u,a:"style-name"},{ens:u,en:"even-columns",ans:u,a:"style-name"},{ens:u,en:"covered-table-cell",ans:u,a:"style-name"},{ens:u,en:"even-columns",ans:u,a:"style-name"},{ens:u,en:"even-rows",ans:u,a:"style-name"},{ens:u,en:"first-column",ans:u,a:"style-name"},{ens:u,en:"first-row",ans:u,a:"style-name"},{ens:u,en:"last-column",ans:u,a:"style-name"},{ens:u,en:"last-row",ans:u,a:"style-name"},{ens:u,en:"odd-columns",ans:u,a:"style-name"},{ens:u,en:"odd-rows", [...]
++{ens:u,en:"table-cell",ans:u,a:"style-name"}],graphic:[{ens:q,en:"cube",ans:k,a:"style-name"},{ens:q,en:"extrude",ans:k,a:"style-name"},{ens:q,en:"rotate",ans:k,a:"style-name"},{ens:q,en:"scene",ans:k,a:"style-name"},{ens:q,en:"sphere",ans:k,a:"style-name"},{ens:k,en:"caption",ans:k,a:"style-name"},{ens:k,en:"circle",ans:k,a:"style-name"},{ens:k,en:"connector",ans:k,a:"style-name"},{ens:k,en:"control",ans:k,a:"style-name"},{ens:k,en:"custom-shape",ans:k,a:"style-name"},{ens:k,en:"ellips [...]
++{ens:k,en:"frame",ans:k,a:"style-name"},{ens:k,en:"g",ans:k,a:"style-name"},{ens:k,en:"line",ans:k,a:"style-name"},{ens:k,en:"measure",ans:k,a:"style-name"},{ens:k,en:"page-thumbnail",ans:k,a:"style-name"},{ens:k,en:"path",ans:k,a:"style-name"},{ens:k,en:"polygon",ans:k,a:"style-name"},{ens:k,en:"polyline",ans:k,a:"style-name"},{ens:k,en:"rect",ans:k,a:"style-name"},{ens:k,en:"regular-polygon",ans:k,a:"style-name"},{ens:w,en:"annotation",ans:k,a:"style-name"}],presentation:[{ens:q,en:"c [...]
++a:"style-name"},{ens:q,en:"extrude",ans:x,a:"style-name"},{ens:q,en:"rotate",ans:x,a:"style-name"},{ens:q,en:"scene",ans:x,a:"style-name"},{ens:q,en:"sphere",ans:x,a:"style-name"},{ens:k,en:"caption",ans:x,a:"style-name"},{ens:k,en:"circle",ans:x,a:"style-name"},{ens:k,en:"connector",ans:x,a:"style-name"},{ens:k,en:"control",ans:x,a:"style-name"},{ens:k,en:"custom-shape",ans:x,a:"style-name"},{ens:k,en:"ellipse",ans:x,a:"style-name"},{ens:k,en:"frame",ans:x,a:"style-name"},{ens:k,en:"g" [...]
++{ens:k,en:"line",ans:x,a:"style-name"},{ens:k,en:"measure",ans:x,a:"style-name"},{ens:k,en:"page-thumbnail",ans:x,a:"style-name"},{ens:k,en:"path",ans:x,a:"style-name"},{ens:k,en:"polygon",ans:x,a:"style-name"},{ens:k,en:"polyline",ans:x,a:"style-name"},{ens:k,en:"rect",ans:x,a:"style-name"},{ens:k,en:"regular-polygon",ans:x,a:"style-name"},{ens:w,en:"annotation",ans:x,a:"style-name"}],"drawing-page":[{ens:k,en:"page",ans:k,a:"style-name"},{ens:x,en:"notes",ans:k,a:"style-name"},{ens:v, [...]
++ans:k,a:"style-name"},{ens:v,en:"master-page",ans:k,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:x,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
++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:x,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"}]},B,L=xmldom.XPath;this.collectUsedFontFaces=c;this.changeFontFaceNames=e;this.UsedStyleList=function(a,b){var c={};this.uses=function(a){var b=a.localName,d=a.getAttributeNS(k,"name")||a.getAttributeNS(v,"name");a="style"===b?a.getAttributeNS(v,"family"):a.namespaceURI===A?"data":b;return(a=c[a])?0<a[d]:!1};p(a,c);b&&m(b,c)};this.hasDerivedStyles=function(a,b,c){var d=c.getAttributeNS(v,"name");c=c.getAttributeNS [...]
++return L.getODFElementsWithXPath(a,"//style:*[@style:parent-style-name='"+d+"'][@style:family='"+c+"']",b).length?!0:!1};this.prefixStyleNames=function(a,b,c){var d;if(a){for(d=a.firstChild;d;){if(d.nodeType===Node.ELEMENT_NODE){var e=d,f=b,h=e.getAttributeNS(k,"name"),q=void 0;h?q=k:(h=e.getAttributeNS(v,"name"))&&(q=v);q&&e.setAttributeNS(q,H[q]+"name",f+h)}d=d.nextSibling}g(a,b);c&&g(c,b)}};this.removePrefixFromStyleNames=function(a,b,c){var d=RegExp("^"+b);if(a){for(b=a.firstChild;b [...]
++Node.ELEMENT_NODE){var e=b,f=d,h=e.getAttributeNS(k,"name"),q=void 0;h?q=k:(h=e.getAttributeNS(v,"name"))&&(q=v);q&&(h=h.replace(f,""),e.setAttributeNS(q,H[q]+"name",h))}b=b.nextSibling}l(a,d);c&&l(c,d)}};this.determineStylesForNode=f;B=function(){var a,b,c,d,e,f={},h,k,q,g;for(c in y)if(y.hasOwnProperty(c))for(d=y[c],b=d.length,a=0;a<b;a+=1)e=d[a],q=e.en,g=e.ens,f.hasOwnProperty(q)?h=f[q]:f[q]=h={},h.hasOwnProperty(g)?k=h[g]:h[g]=k=[],k.push({ns:e.ans,localname:e.a,keyname:c});return f}()};
++// Input 32
 +/*
 +
 + 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(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
++odf.TextSerializer=function(){function g(p){var r="",n=l.filter?l.filter.acceptNode(p):NodeFilter.FILTER_ACCEPT,h=p.nodeType,d;if(n===NodeFilter.FILTER_ACCEPT||n===NodeFilter.FILTER_SKIP)for(d=p.firstChild;d;)r+=g(d),d=d.nextSibling;n===NodeFilter.FILTER_ACCEPT&&(h===Node.ELEMENT_NODE&&f.isParagraph(p)?r+="\n":h===Node.TEXT_NODE&&p.textContent&&(r+=p.textContent));return r}var l=this,f=new odf.OdfUtils;this.filter=null;this.writeToString=function(f){if(!f)return"";f=g(f);"\n"===f[f.leng [...]
++f.substr(0,f.length-1));return f}};
++// Input 33
 +/*
 +
 + 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 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}};
++ops.TextPositionFilter=function(g){function l(d,g,c){var e,a;if(g){if(f.isInlineRoot(g)&&f.isGroupingElement(c))return h;e=f.lookLeftForCharacter(g);if(1===e||2===e&&(f.scanRightForAnyCharacter(c)||f.scanRightForAnyCharacter(f.nextNode(d))))return n}e=null===g&&f.isParagraph(d);a=f.lookRightForCharacter(c);if(e)return a?n:f.scanRightForAnyCharacter(c)?h:n;if(!a)return h;g=g||f.previousNode(d);return f.scanLeftForAnyCharacter(g)?h:n}var f=new odf.OdfUtils,p=Node.ELEMENT_NODE,r=Node.TEXT_ [...]
++h=core.PositionFilter.FilterResult.FILTER_REJECT;this.acceptPosition=function(d){var m=d.container(),c=m.nodeType,e,a,b;if(c!==p&&c!==r)return h;if(c===r){if(!f.isGroupingElement(m.parentNode)||f.isWithinTrackedChanges(m.parentNode,g()))return h;c=d.unfilteredDomOffset();e=m.data;runtime.assert(c!==e.length,"Unexpected offset.");if(0<c){d=e[c-1];if(!f.isODFWhitespace(d))return n;if(1<c)if(d=e[c-2],!f.isODFWhitespace(d))a=n;else{if(!f.isODFWhitespace(e.substr(0,c)))return h}else b=f.prev [...]
++f.scanLeftForNonSpace(b)&&(a=n);if(a===n)return f.isTrailingWhitespace(m,c)?h:n;a=e[c];return f.isODFWhitespace(a)?h:f.scanLeftForAnyCharacter(f.previousNode(m))?h:n}b=d.leftNode();a=m;m=m.parentNode;a=l(m,b,a)}else!f.isGroupingElement(m)||f.isWithinTrackedChanges(m,g())?a=h:(b=d.leftNode(),a=d.rightNode(),a=l(m,b,a));return a}};
++// Input 34
++"function"!==typeof Object.create&&(Object.create=function(g){var l=function(){};l.prototype=g;return new l});
++xmldom.LSSerializer=function(){function g(f){var g=f||{},h=function(c){var a={},b;for(b in c)c.hasOwnProperty(b)&&(a[c[b]]=b);return a}(f),d=[g],m=[h],c=0;this.push=function(){c+=1;g=d[c]=Object.create(g);h=m[c]=Object.create(h)};this.pop=function(){d.pop();m.pop();c-=1;g=d[c];h=m[c]};this.getLocalNamespaceDefinitions=function(){return h};this.getQName=function(c){var a=c.namespaceURI,b=0,d;if(!a)return c.localName;if(d=h[a])return d+":"+c.localName;do{d||!c.prefix?(d="ns"+b,b+=1):d=c.p [...]
++a)break;if(!g[d]){g[d]=a;h[a]=d;break}d=null}while(null===d);return d+":"+c.localName}}function l(f){return f.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/'/g,"'").replace(/"/g,""")}function f(g,n){var h="",d=p.filter?p.filter.acceptNode(n):NodeFilter.FILTER_ACCEPT,m;if(d===NodeFilter.FILTER_ACCEPT&&n.nodeType===Node.ELEMENT_NODE){g.push();m=g.getQName(n);var c,e=n.attributes,a,b,q,k="",t;c="<"+m;a=e.length;for(b=0;b<a;b+=1)q=e.item(b),"http://www.w [...]
++q.namespaceURI&&(t=p.filter?p.filter.acceptNode(q):NodeFilter.FILTER_ACCEPT,t===NodeFilter.FILTER_ACCEPT&&(t=g.getQName(q),q="string"===typeof q.value?l(q.value):q.value,k+=" "+(t+'="'+q+'"')));a=g.getLocalNamespaceDefinitions();for(b in a)a.hasOwnProperty(b)&&((e=a[b])?"xmlns"!==e&&(c+=" xmlns:"+a[b]+'="'+b+'"'):c+=' xmlns="'+b+'"');h+=c+(k+">")}if(d===NodeFilter.FILTER_ACCEPT||d===NodeFilter.FILTER_SKIP){for(d=n.firstChild;d;)h+=f(g,d),d=d.nextSibling;n.nodeValue&&(h+=l(n.nodeValue))} [...]
++m+">",g.pop());return h}var p=this;this.filter=null;this.writeToString=function(l,n){if(!l)return"";var h=new g(n);return f(h,l)}};
 +// 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/
 +*/
 +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
++gui.Clipboard=function(){var g,l,f;this.setDataFromRange=function(f,r){var n=!0,h,d=f.clipboardData;h=runtime.getWindow();var m=r.startContainer.ownerDocument;!d&&h&&(d=h.clipboardData);d?(m=m.createElement("span"),m.appendChild(r.cloneContents()),h=d.setData("text/plain",l.writeToString(m)),n=n&&h,h=d.setData("text/html",g.writeToString(m,odf.Namespaces.namespaceMap)),n=n&&h,f.preventDefault()):n=!1;return n};g=new xmldom.LSSerializer;l=new odf.TextSerializer;f=new odf.OdfNodeFilter;g. [...]
++f};
++// Input 36
 +/*
 +
 + 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");
- (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
++runtime.loadClass("core.Base64");runtime.loadClass("core.Zip");runtime.loadClass("core.DomUtils");runtime.loadClass("xmldom.LSSerializer");runtime.loadClass("odf.StyleInfo");runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.OdfNodeFilter");
++(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=m.length;for(b=0;b<c;b+=1)if("urn:oasis:names:tc:opendocument:xmlns:office:1.0"===a.namespaceURI&&a.localName===m[b])return b;return-1}function f(a,b){var c=new n.UsedStyleList(a,b),d=new odf.OdfNodeFilter;this.acceptNode=function(a){var e=d.acceptNode(a);e===NodeFilter.FILTER_ACCEPT&&a.parentNode===b&&a.nodeType===Node.ELEMENT_NOD [...]
++NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT);return e}}function p(a,b){var c=new f(a,b);this.acceptNode=function(a){var b=c.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 r(a,b){if(b){var c=l(b),d,e=a.firstChild;if(-1!==c){for(;e;){d=l(e);if(-1!==d&&d>c)break;e=e.nextSibling}a.insertBefore(b,e)}}}var n=new odf. [...]
++h=new core.DomUtils,d=odf.Namespaces.stylens,m="meta settings scripts font-face-decls styles automatic-styles master-styles body".split(" "),c=(new Date).getTime()+"_webodf_",e=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.ODFDocument [...]
++null;odf.ODFDocumentElement.namespaceURI="urn:oasis:names:tc:opendocument:xmlns:office:1.0";odf.ODFDocumentElement.localName="document";odf.OdfPart=function(a,b,c,d){var e=this;this.size=0;this.type=null;this.name=a;this.container=c;this.url=null;this.mimetype=b;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=b,d.loadAsDataURL(a,b,function(a,b){a&&runtime.log(a);e.url=b;if [...]
++if(e.onstatereadychange)e.onstatereadychange(e)}))}};odf.OdfPart.prototype.load=function(){};odf.OdfPart.prototype.getUrl=function(){return this.data?"data:;base64,"+e.toBase64(this.data):null};odf.OdfContainer=function b(q,k){function m(b){for(var c=b.firstChild,d;c;)d=c.nextSibling,c.nodeType===Node.ELEMENT_NODE?m(c):c.nodeType===Node.PROCESSING_INSTRUCTION_NODE&&b.removeChild(c),c=d}function l(b,c){for(var d=b&&b.firstChild;d;)d.nodeType===Node.ELEMENT_NODE&&d.setAttributeNS("urn:web [...]
++"scope",c),d=d.nextSibling}function w(b){var c={},e;for(b=b.firstChild;b;)b.nodeType===Node.ELEMENT_NODE&&b.namespaceURI===d&&"font-face"===b.localName&&(e=b.getAttributeNS(d,"name"),c[e]=b),b=b.nextSibling;return c}function x(b,c){var d=null,e,f,h;if(b)for(d=b.cloneNode(!0),e=d.firstElementChild;e;)f=e.nextElementSibling,(h=e.getAttributeNS("urn:webodf:names:scope","scope"))&&h!==c&&d.removeChild(e),e=f;return d}function v(b,c){var e,f,h,k=null,g={};if(b)for(c.forEach(function(b){n.col [...]
++b)}),k=b.cloneNode(!0),e=k.firstElementChild;e;)f=e.nextElementSibling,h=e.getAttributeNS(d,"name"),g[h]||k.removeChild(e),e=f;return k}function u(b){var c=R.rootElement.ownerDocument,d;if(b){m(b.documentElement);try{d=c.importNode(b.documentElement,!0)}catch(e){}}return d}function s(b){R.state=b;if(R.onchange)R.onchange(R);if(R.onstatereadychange)R.onstatereadychange(R)}function H(b){ba=null;R.rootElement=b;b.fontFaceDecls=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-fa [...]
++b.styles=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles");b.automaticStyles=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles");b.masterStyles=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles");b.body=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","body");b.meta=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta")}function y(d){var e=u(d),f=R.rootElement,h;e&&"document-styles"===e.localName&&"urn:oasis:names:t [...]
++e.namespaceURI?(f.fontFaceDecls=g(e,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls"),r(f,f.fontFaceDecls),h=g(e,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles"),f.styles=h||d.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles"),r(f,f.styles),h=g(e,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles"),f.automaticStyles=h||d.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles"),l(f.a [...]
++"document-styles"),r(f,f.automaticStyles),e=g(e,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles"),f.masterStyles=e||d.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles"),r(f,f.masterStyles),n.prefixStyleNames(f.automaticStyles,c,f.masterStyles)):s(b.INVALID)}function B(c){c=u(c);var e,f,h,k;if(c&&"document-content"===c.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===c.namespaceURI){e=R.rootElement;h=g(c,"urn:oasis:names:t [...]
++"font-face-decls");if(e.fontFaceDecls&&h){k=e.fontFaceDecls;var q,m,p,t,v={};f=w(k);t=w(h);for(h=h.firstElementChild;h;){q=h.nextElementSibling;if(h.namespaceURI===d&&"font-face"===h.localName)if(m=h.getAttributeNS(d,"name"),f.hasOwnProperty(m)){if(!h.isEqualNode(f[m])){p=m;for(var y=f,I=t,z=0,B=void 0,B=p=p.replace(/\d+$/,"");y.hasOwnProperty(B)||I.hasOwnProperty(B);)z+=1,B=p+z;p=B;h.setAttributeNS(d,"style:name",p);k.appendChild(h);f[p]=h;delete t[m];v[m]=p}}else k.appendChild(h),f[m] [...]
++h=q}k=v}else h&&(e.fontFaceDecls=h,r(e,h));f=g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles");l(f,"document-content");k&&n.changeFontFaceNames(f,k);if(e.automaticStyles&&f)for(k=f.firstChild;k;)e.automaticStyles.appendChild(k),k=f.firstChild;else f&&(e.automaticStyles=f,r(e,f));c=g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","body");if(null===c)throw"<office:body/> tag is mising.";e.body=c;r(e,e.body)}else s(b.INVALID)}function L(b){b=u(b);var c;b&&"do [...]
++b.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===b.namespaceURI&&(c=R.rootElement,c.meta=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta"),r(c,c.meta))}function I(b){b=u(b);var c;b&&"document-settings"===b.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===b.namespaceURI&&(c=R.rootElement,c.settings=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","settings"),r(c,c.settings))}function W(b){b=u(b);var c;if(b&&"manifest"===b.localName&&"urn [...]
++b.namespaceURI)for(c=R.rootElement,c.manifest=b,b=c.manifest.firstElementChild;b;)"file-entry"===b.localName&&"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"===b.namespaceURI&&(M[b.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","full-path")]=b.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","media-type")),b=b.nextElementSibling}function Q(c){var d=c.shift();d?P.loadAsDOM(d.path,function(e,f){d.handler(f);e||R.state===b.INVALID||Q(c)}):s(b.DO [...]
++"";odf.Namespaces.forEachPrefix(function(b,d){c+=" xmlns:"+b+'="'+d+'"'});return'<?xml version="1.0" encoding="UTF-8"?><office:'+b+" "+c+' office:version="1.2">'}function ja(){var b=new xmldom.LSSerializer,c=z("document-meta");b.filter=new odf.OdfNodeFilter;c+=b.writeToString(R.rootElement.meta,odf.Namespaces.namespaceMap);return c+"</office:document-meta>"}function ka(b,c){var d=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest:file-entry");d.setAt [...]
++"manifest:full-path",b);d.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest:media-type",c);return d}function G(){var b=runtime.parseXML('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2"></manifest:manifest>'),c=g(b,"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest"),d=new xmldom.LSSerializer,e;for(e in M)M.hasOwnProperty(e)&&c.appendChild(ka(e,M[e]));d.filter=new odf.OdfNodeFilter;retur [...]
++d.writeToString(b,odf.Namespaces.namespaceMap)}function Z(){var b=new xmldom.LSSerializer,c=z("document-settings");b.filter=new odf.OdfNodeFilter;c+=b.writeToString(R.rootElement.settings,odf.Namespaces.namespaceMap);return c+"</office:document-settings>"}function O(){var b,d,e,h=odf.Namespaces.namespaceMap,k=new xmldom.LSSerializer,g=z("document-styles");d=x(R.rootElement.automaticStyles,"document-styles");e=R.rootElement.masterStyles.cloneNode(!0);b=v(R.rootElement.fontFaceDecls,[e,R. [...]
++d]);n.removePrefixFromStyleNames(d,c,e);k.filter=new f(e,d);g+=k.writeToString(b,h);g+=k.writeToString(R.rootElement.styles,h);g+=k.writeToString(d,h);g+=k.writeToString(e,h);return g+"</office:document-styles>"}function aa(){var b,c,d=odf.Namespaces.namespaceMap,e=new xmldom.LSSerializer,f=z("document-content");c=x(R.rootElement.automaticStyles,"document-content");b=v(R.rootElement.fontFaceDecls,[c]);e.filter=new p(R.rootElement.body,c);f+=e.writeToString(b,d);f+=e.writeToString(c,d);f [...]
++d);return f+"</office:document-content>"}function J(c,d){runtime.loadXML(c,function(c,e){if(c)d(c);else{var f=u(e);f&&"document"===f.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===f.namespaceURI?(H(f),s(b.DONE)):s(b.INVALID)}})}function F(b,c){var d;d=R.rootElement;var e=d.meta;e||(d.meta=e=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta"),r(d,e));d=e;b&&h.mapKeyValObjOntoNode(d,b,odf.Namespaces.lookupNamespaceURI);c&&h.removeKeyElement [...]
++c,odf.Namespaces.lookupNamespaceURI)}function C(){function c(b,d){var e;d||(d=b);e=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0",d);f[b]=e;f.appendChild(e)}var d=new core.Zip("",null),e=runtime.byteArrayFromString("application/vnd.oasis.opendocument.text","utf8"),f=R.rootElement,h=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","text");d.save("mimetype",e,!1,new Date);c("meta");c("settings");c("scripts");c("fontFaceDecls","font-f [...]
++c("styles");c("automaticStyles","automatic-styles");c("masterStyles","master-styles");c("body");f.body.appendChild(h);s(b.DONE);return d}function Y(){var b,c=new Date,d=runtime.getWindow();b="WebODF/"+("undefined"!==String(typeof webodf_version)?webodf_version:"FromSource");d&&(b=b+" "+d.navigator.userAgent);F({"meta:generator":b},null);b=runtime.byteArrayFromString(Z(),"utf8");P.save("settings.xml",b,!0,c);b=runtime.byteArrayFromString(ja(),"utf8");P.save("meta.xml",b,!0,c);b=runtime.b [...]
++"utf8");P.save("styles.xml",b,!0,c);b=runtime.byteArrayFromString(aa(),"utf8");P.save("content.xml",b,!0,c);b=runtime.byteArrayFromString(G(),"utf8");P.save("META-INF/manifest.xml",b,!0,c)}function U(b,c){Y();P.writeAs(b,function(b){c(b)})}var R=this,P,M={},ba;this.onstatereadychange=k;this.state=this.onchange=null;this.setRootElement=H;this.getContentElement=function(){var b;ba||(b=R.rootElement.body,ba=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","text")||g(b,"urn:oasis:name [...]
++"presentation")||g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","spreadsheet"));if(!ba)throw"Could not find content element in <office:body/>.";return ba};this.getDocumentType=function(){var b=R.getContentElement();return b&&b.localName};this.getPart=function(b){return new odf.OdfPart(b,M[b],R,P)};this.getPartData=function(b,c){P.load(b,c)};this.setMetadata=F;this.incrementEditingCycles=function(){var b;for(b=(b=R.rootElement.meta)&&b.firstChild;b&&(b.namespaceURI!==odf.Namespac [...]
++"editing-cycles"!==b.localName);)b=b.nextSibling;for(b=b&&b.firstChild;b&&b.nodeType!==Node.TEXT_NODE;)b=b.nextSibling;b=b?b.data:null;b=b?parseInt(b,10):0;isNaN(b)&&(b=0);F({"meta:editing-cycles":b+1},null)};this.createByteArray=function(b,c){Y();P.createByteArray(b,c)};this.saveAs=U;this.save=function(b){U(q,b)};this.getUrl=function(){return q};this.setBlob=function(b,c,d){d=e.convertBase64ToByteArray(d);P.save(b,d,!1,new Date);M.hasOwnProperty(b)&&runtime.log(b+" has been overwritten [...]
++this.removeBlob=function(b){var c=P.remove(b);runtime.assert(c,"file is not found: "+b);delete M[b]};this.state=b.LOADING;this.rootElement=function(b){var c=document.createElementNS(b.namespaceURI,b.localName),d;b=new b.Type;for(d in b)b.hasOwnProperty(d)&&(c[d]=b[d]);return c}({Type:odf.ODFDocumentElement,namespaceURI:odf.ODFDocumentElement.namespaceURI,localName:odf.ODFDocumentElement.localName});P=q?new core.Zip(q,function(c,d){P=d;c?J(q,function(d){c&&(P.error=c+"\n"+d,s(b.INVALID)) [...]
++handler:y},{path:"content.xml",handler:B},{path:"meta.xml",handler:L},{path:"settings.xml",handler:I},{path:"META-INF/manifest.xml",handler:W}])}):C()};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(b){return new odf.OdfContainer(b,null)};return odf.OdfContainer})();
++// 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/
 +*/
 +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
++(function(){function g(l,r,n,h,d){var m,c=0,e;for(e in l)if(l.hasOwnProperty(e)){if(c===n){m=e;break}c+=1}m?r.getPartData(l[m].href,function(a,b){if(a)runtime.log(a);else if(b){var c="@font-face { font-family: '"+(l[m].family||m)+"'; src: url(data:application/x-font-ttf;charset=binary;base64,"+f.convertUTF8ArrayToBase64(b)+') format("truetype"); }';try{h.insertRule(c,h.cssRules.length)}catch(e){runtime.log("Problem inserting rule in CSS: "+runtime.toJson(e)+"\nRule: "+c)}}else runtime.l [...]
++l[m].href);g(l,r,n+1,h,d)}):d&&d()}var l=xmldom.XPath,f=new core.Base64;odf.FontLoader=function(){this.loadFonts=function(f,r){for(var n=f.rootElement.fontFaceDecls;r.cssRules.length;)r.deleteRule(r.cssRules.length-1);if(n){var h={},d,m,c,e;if(n)for(n=l.getODFElementsWithXPath(n,"style:font-face[svg:font-face-src]",odf.Namespaces.lookupNamespaceURI),d=0;d<n.length;d+=1)m=n[d],c=m.getAttributeNS(odf.Namespaces.stylens,"name"),e=m.getAttributeNS(odf.Namespaces.svgns,"font-family"),m=l.get [...]
++"svg:font-face-src/svg:font-face-uri",odf.Namespaces.lookupNamespaceURI),0<m.length&&(m=m[0].getAttributeNS(odf.Namespaces.xlinkns,"href"),h[c]={href:m,family:e});g(h,f,0,r)}}};return odf.FontLoader})();
++// 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/
 +*/
 +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
++odf.ObjectNameGenerator=function(g,l){function f(a,b){var c={};this.generateName=function(){var d=b(),e=0,f;do f=a+e,e+=1;while(c[f]||d[f]);c[f]=!0;return f}}function p(){var a={};[g.rootElement.automaticStyles,g.rootElement.styles].forEach(function(b){for(b=b.firstElementChild;b;)b.namespaceURI===r&&"style"===b.localName&&(a[b.getAttributeNS(r,"name")]=!0),b=b.nextElementSibling});return a}var r=odf.Namespaces.stylens,n=odf.Namespaces.drawns,h=odf.Namespaces.xlinkns,d=new core.DomUtils [...]
++c=null,e=null,a=null,b={},q={};this.generateStyleName=function(){null===c&&(c=new f("auto"+m+"_",function(){return p()}));return c.generateName()};this.generateFrameName=function(){null===e&&(d.getElementsByTagNameNS(g.rootElement.body,n,"frame").forEach(function(a){b[a.getAttributeNS(n,"name")]=!0}),e=new f("fr"+m+"_",function(){return b}));return e.generateName()};this.generateImageName=function(){null===a&&(d.getElementsByTagNameNS(g.rootElement.body,n,"image").forEach(function(a){a= [...]
++"href");a=a.substring(9,a.lastIndexOf("."));q[a]=!0}),a=new f("img"+m+"_",function(){return q}));return a.generateName()}};
++// 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("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
++runtime.loadClass("core.Utils");runtime.loadClass("odf.ObjectNameGenerator");runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.OdfContainer");runtime.loadClass("odf.StyleInfo");runtime.loadClass("odf.OdfUtils");
++odf.Formatting=function(){function g(a){return(a=u[a])?v.mergeObjects({},a):{}}function l(a,b,c){for(a=a&&a.firstElementChild;a&&(a.namespaceURI!==b||a.localName!==c);)a=a.nextElementSibling;return a}function f(){for(var a=e.rootElement.fontFaceDecls,c={},d,f,a=a&&a.firstElementChild;a;){if(d=a.getAttributeNS(q,"name"))if((f=a.getAttributeNS(b,"font-family"))||0<a.getElementsByTagNameNS(b,"font-face-uri").length)c[d]=f;a=a.nextElementSibling}return c}function p(a){for(var b=e.rootElemen [...]
++q&&"default-style"===b.localName&&b.getAttributeNS(q,"family")===a)return b;b=b.nextElementSibling}return null}function r(a,b,c){var d,f,h;c=c||[e.rootElement.automaticStyles,e.rootElement.styles];for(h=0;h<c.length;h+=1)for(d=c[h],d=d.firstElementChild;d;){f=d.getAttributeNS(q,"name");if(d.namespaceURI===q&&"style"===d.localName&&d.getAttributeNS(q,"family")===b&&f===a||"list-style"===b&&d.namespaceURI===k&&"list-style"===d.localName&&f===a||"data"===b&&d.namespaceURI===t&&f===a)return [...]
++function n(a){for(var b,c,d,e,f={},h=a.firstElementChild;h;){if(h.namespaceURI===q)for(d=f[h.nodeName]={},c=h.attributes,b=0;b<c.length;b+=1)e=c.item(b),d[e.name]=e.value;h=h.nextElementSibling}c=a.attributes;for(b=0;b<c.length;b+=1)e=c.item(b),f[e.name]=e.value;return f}function h(a,b){for(var c=e.rootElement.styles,d,f={},h=a.getAttributeNS(q,"family"),k=a;k;)d=n(k),f=v.mergeObjects(d,f),k=(d=k.getAttributeNS(q,"parent-style-name"))?r(d,h,[c]):null;if(k=p(h))d=n(k),f=v.mergeObjects(d, [...]
++(f=v.mergeObjects(d,f));return f}function d(b,c){function d(a){Object.keys(a).forEach(function(b){Object.keys(a[b]).forEach(function(a){k+="|"+b+":"+a+"|"})})}for(var e=b.nodeType===Node.TEXT_NODE?b.parentNode:b,f,h=[],k="",g=!1;e;)!g&&w.isGroupingElement(e)&&(g=!0),(f=a.determineStylesForNode(e))&&h.push(f),e=e.parentElement;g&&(h.forEach(d),c&&(c[k]=h));return g?h:void 0}function m(a){var b={orderedStyles:[]};a.forEach(function(a){Object.keys(a).forEach(function(c){var d=Object.keys(a [...]
++f;(e=r(d,c))?(f=h(e),b=v.mergeObjects(f,b),f=e.getAttributeNS(q,"display-name")):runtime.log("No style element found for '"+d+"' of family '"+c+"'");b.orderedStyles.push({name:d,family:c,displayName:f})})});return b}function c(a,b){var c=w.parseLength(a),d=b;if(c)switch(c.unit){case "cm":d=c.value;break;case "mm":d=0.1*c.value;break;case "in":d=2.54*c.value;break;case "pt":d=0.035277778*c.value;break;case "pc":case "px":case "em":break;default:runtime.log("Unit identifier: "+c.unit+" is [...]
++var e,a=new odf.StyleInfo,b=odf.Namespaces.svgns,q=odf.Namespaces.stylens,k=odf.Namespaces.textns,t=odf.Namespaces.numberns,A=odf.Namespaces.fons,w=new odf.OdfUtils,x=new core.DomUtils,v=new core.Utils,u={paragraph:{"style:paragraph-properties":{"fo:text-align":"left"}}};this.getSystemDefaultStyleAttributes=g;this.setOdfContainer=function(a){e=a};this.getFontMap=f;this.getAvailableParagraphStyles=function(){for(var a=e.rootElement.styles,b,c,d=[],a=a&&a.firstElementChild;a;)"style"===a. [...]
++a.namespaceURI===q&&(b=a.getAttributeNS(q,"family"),"paragraph"===b&&(b=a.getAttributeNS(q,"name"),c=a.getAttributeNS(q,"display-name")||b,b&&c&&d.push({name:b,displayName:c}))),a=a.nextElementSibling;return d};this.isStyleUsed=function(b){var c,d=e.rootElement;c=a.hasDerivedStyles(d,odf.Namespaces.lookupNamespaceURI,b);b=(new a.UsedStyleList(d.styles)).uses(b)||(new a.UsedStyleList(d.automaticStyles)).uses(b)||(new a.UsedStyleList(d.body)).uses(b);return c||b};this.getDefaultStyleEleme [...]
++r;this.getStyleAttributes=n;this.getInheritedStyleAttributes=h;this.getFirstCommonParentStyleNameOrSelf=function(a){var b=e.rootElement.automaticStyles,c=e.rootElement.styles,d;for(d=r(a,"paragraph",[b]);d;)a=d.getAttributeNS(q,"parent-style-name"),d=r(a,"paragraph",[b]);return(d=r(a,"paragraph",[c]))?a:null};this.hasParagraphStyle=function(a){return Boolean(r(a,"paragraph"))};this.getAppliedStyles=function(a){var b={},c=[];a.forEach(function(a){d(a,b)});Object.keys(b).forEach(function( [...]
++return c};this.getAppliedStylesForElement=function(a){return(a=d(a))?m(a):void 0};this.updateStyle=function(a,c){var d,h;x.mapObjOntoNode(a,c,odf.Namespaces.lookupNamespaceURI);(d=c["style:text-properties"]&&c["style:text-properties"]["style:font-name"])&&!f().hasOwnProperty(d)&&(h=a.ownerDocument.createElementNS(q,"style:font-face"),h.setAttributeNS(q,"style:name",d),h.setAttributeNS(b,"svg:font-family",d),e.rootElement.fontFaceDecls.appendChild(h))};this.createDerivedStyleObject=funct [...]
++r(a,b);runtime.assert(Boolean(d),"No style element found for '"+a+"' of family '"+b+"'");a=d.parentNode===e.rootElement.automaticStyles?n(d):{"style:parent-style-name":a};a["style:family"]=b;v.mergeObjects(a,c);return a};this.getDefaultTabStopDistance=function(){for(var a=p("paragraph"),a=a&&a.firstElementChild,b;a;)a.namespaceURI===q&&"paragraph-properties"===a.localName&&(b=a.getAttributeNS(q,"tab-stop-distance")),a=a.nextElementSibling;b||(b="1.25cm");return w.parseNonNegativeLength( [...]
++function(a,b){var d,f,h,k,g,m,n,p,t,v,u;a:{var w,aa,J;d=r(a,b);runtime.assert("paragraph"===b||"table"===b,"styleFamily has to be either paragraph or table");if(d){w=d.getAttributeNS(q,"master-page-name")||"Standard";for(d=e.rootElement.masterStyles.lastElementChild;d&&d.getAttributeNS(q,"name")!==w;)d=d.previousElementSibling;w=d.getAttributeNS(q,"page-layout-name");aa=x.getElementsByTagNameNS(e.rootElement.automaticStyles,q,"page-layout");for(J=0;J<aa.length;J+=1)if(d=aa[J],d.getAttri [...]
++w)break a}d=null}d||(d=l(e.rootElement.styles,q,"default-page-layout"));if(d=l(d,q,"page-layout-properties"))f=d.getAttributeNS(q,"print-orientation")||"portrait","portrait"===f?(f=21.001,h=29.7):(f=29.7,h=21.001),f=c(d.getAttributeNS(A,"page-width"),f),h=c(d.getAttributeNS(A,"page-height"),h),k=c(d.getAttributeNS(A,"margin"),null),null===k?(k=c(d.getAttributeNS(A,"margin-left"),2),g=c(d.getAttributeNS(A,"margin-right"),2),m=c(d.getAttributeNS(A,"margin-top"),2),n=c(d.getAttributeNS(A," [...]
++2)):k=g=m=n=k,p=c(d.getAttributeNS(A,"padding"),null),null===p?(p=c(d.getAttributeNS(A,"padding-left"),0),t=c(d.getAttributeNS(A,"padding-right"),0),v=c(d.getAttributeNS(A,"padding-top"),0),u=c(d.getAttributeNS(A,"padding-bottom"),0)):p=t=v=u=p;return{width:f-k-g-p-t,height:h-m-n-v-u}}};
++// 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("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
++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){c=!0;runtime.setTimeout(function(){try{d()}catch(e){runtime.log(String(e))}c=!1;0<b.length&&a(b.pop())},10)}var b=[],c=!1;this.clearQueue=function(){b.length=0};this.addToQueue=function(d){if(0===b.length&&!c)return a(d);b.push(d)}}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("#shadowContent [...]
++d+") {display:block;}",2);c.insertRule("office|presentation draw|page:nth-of-type("+d+") {display:block;}",3)}var c=a.sheet,d=1;this.showFirstPage=function(){d=1;b()};this.showNextPage=function(){d+=1;b()};this.showPreviousPage=function(){1<d&&(d-=1,b())};this.showPage=function(a){0<a&&(d=a,b())};this.css=a;this.destroy=function(b){a.parentNode.removeChild(a);b()}}function f(a){for(;a.firstChild;)a.removeChild(a.firstChild)}function p(a,b,c){(new odf.Style2CSS).style2css(a.getDocumentTy [...]
++b.getFontMap(),a.rootElement.styles,a.rootElement.automaticStyles)}function r(a,b,c){var d=null;a=a.rootElement.body.getElementsByTagNameNS(L,c+"-decl");c=b.getAttributeNS(L,"use-"+c+"-name");var e;if(c&&0<a.length)for(b=0;b<a.length;b+=1)if(e=a[b],e.getAttributeNS(L,"name")===c){d=e.textContent;break}return d}function n(a,b,c,d){var e=a.ownerDocument;b=a.getElementsByTagNameNS(b,c);for(a=0;a<b.length;a+=1)f(b[a]),d&&(c=b[a],c.appendChild(e.createTextNode(d)))}function h(a,b,c){b.setAtt [...]
++"styleid",a);var d,e=b.getAttributeNS(H,"anchor-type"),f=b.getAttributeNS(u,"x"),h=b.getAttributeNS(u,"y"),k=b.getAttributeNS(u,"width"),g=b.getAttributeNS(u,"height"),q=b.getAttributeNS(w,"min-height"),m=b.getAttributeNS(w,"min-width");if("as-char"===e)d="display: inline-block;";else if(e||f||h)d="position: absolute;";else if(k||g||q||m)d="display: block;";f&&(d+="left: "+f+";");h&&(d+="top: "+h+";");k&&(d+="width: "+k+";");g&&(d+="height: "+g+";");q&&(d+="min-height: "+q+";");m&&(d+=" [...]
++m+";");d&&(d="draw|"+b.localName+'[webodfhelper|styleid="'+a+'"] {'+d+"}",c.insertRule(d,c.cssRules.length))}function d(a){for(a=a.firstChild;a;){if(a.namespaceURI===x&&"binary-data"===a.localName)return"data:image/png;base64,"+a.textContent.replace(/[\r\n\s]/g,"");a=a.nextSibling}return""}function m(a,b,c,e){function f(b){b&&(b='draw|image[webodfhelper|styleid="'+a+'"] {'+("background-image: url("+b+");")+"}",e.insertRule(b,e.cssRules.length))}function h(a){f(a.url)}c.setAttributeNS("u [...]
++"styleid",a);var k=c.getAttributeNS(y,"href"),g;if(k)try{g=b.getPart(k),g.onchange=h,g.load()}catch(q){runtime.log("slight problem: "+String(q))}else k=d(c),f(k)}function c(a){function b(c){var d,e;c.hasAttributeNS(y,"href")&&(d=c.getAttributeNS(y,"href"),"#"===d[0]?(d=d.substring(1),e=function(){var b=W.getODFElementsWithXPath(a,"//text:bookmark-start[@text:name='"+d+"']",odf.Namespaces.lookupNamespaceURI);0===b.length&&(b=W.getODFElementsWithXPath(a,"//text:bookmark[@text:name='"+d+"' [...]
++0<b.length&&b[0].scrollIntoView(!0);return!1}):e=function(){I.open(d)},c.onclick=e)}var c,d,e;d=a.getElementsByTagNameNS(H,"a");for(c=0;c<d.length;c+=1)e=d.item(c),b(e)}function e(a){var b=a.ownerDocument;z.getElementsByTagNameNS(a,H,"line-break").forEach(function(a){a.hasChildNodes()||a.appendChild(b.createElement("br"))})}function a(a){var b=a.ownerDocument;z.getElementsByTagNameNS(a,H,"s").forEach(function(a){for(var c,d;a.firstChild;)a.removeChild(a.firstChild);a.appendChild(b.creat [...]
++d=parseInt(a.getAttributeNS(H,"c"),10);if(1<d)for(a.removeAttributeNS(H,"c"),c=1;c<d;c+=1)a.parentNode.insertBefore(a.cloneNode(!0),a)})}function b(a){z.getElementsByTagNameNS(a,H,"tab").forEach(function(a){a.textContent="\t"})}function q(a,b){function c(a,d){var e=g.documentElement.namespaceURI;"video/"===d.substr(0,6)?(f=g.createElementNS(e,"video"),f.setAttribute("controls","controls"),h=g.createElementNS(e,"source"),a&&h.setAttribute("src",a),h.setAttribute("type",d),f.appendChild(h [...]
++b.innerHtml="Unrecognised Plugin"}function e(a){c(a.url,a.mimetype)}var f,h,k,g=b.ownerDocument,q;if(k=b.getAttributeNS(y,"href"))try{q=a.getPart(k),q.onchange=e,q.load()}catch(m){runtime.log("slight problem: "+String(m))}else runtime.log("using MP4 data fallback"),k=d(b),c(k,"video/mp4")}function k(a){var b=a.getElementsByTagName("head")[0],c;"undefined"!==String(typeof webodf_css)?(c=a.createElementNS(b.namespaceURI,"style"),c.setAttribute("media","screen, print, handheld, projection" [...]
++(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 t(a){var b=a.getElementsByTagName("head")[0],c=a.createElementNS(b.namespaceURI,"style"),d="";c.setAttribute("type","text/css");c.setAttribute("media","screen, print, handheld, projection");odf.Namespaces.forEachPrefix(function(a,b){d+= [...]
++a+" url("+b+");\n"});d+="@namespace webodfhelper url(urn:webodf:names:helper);\n";c.appendChild(a.createTextNode(d));b.appendChild(c);return c}var A=odf.Namespaces.drawns,w=odf.Namespaces.fons,x=odf.Namespaces.officens,v=odf.Namespaces.stylens,u=odf.Namespaces.svgns,s=odf.Namespaces.tablens,H=odf.Namespaces.textns,y=odf.Namespaces.xlinkns,B=odf.Namespaces.xmlns,L=odf.Namespaces.presentationns,I=runtime.getWindow(),W=xmldom.XPath,Q=new odf.OdfUtils,z=new core.DomUtils;odf.OdfCanvas=funct [...]
++b,c){function d(a,b,c,e){E.addToQueue(function(){m(a,b,c,e)})}var e,f;e=b.getElementsByTagNameNS(A,"image");for(b=0;b<e.length;b+=1)f=e.item(b),d("image"+String(b),a,f,c)}function w(a,b){function c(a,b){E.addToQueue(function(){q(a,b)})}var d,e,f;e=b.getElementsByTagNameNS(A,"plugin");for(d=0;d<e.length;d+=1)f=e.item(d),c(a,f)}function y(){M.firstChild&&(1<S?(M.style.MozTransformOrigin="center top",M.style.WebkitTransformOrigin="center top",M.style.OTransformOrigin="center top",M.style.m [...]
++"center top"):(M.style.MozTransformOrigin="left top",M.style.WebkitTransformOrigin="left top",M.style.OTransformOrigin="left top",M.style.msTransformOrigin="left top"),M.style.WebkitTransform="scale("+S+")",M.style.MozTransform="scale("+S+")",M.style.OTransform="scale("+S+")",M.style.msTransform="scale("+S+")",d.style.width=Math.round(S*M.offsetWidth)+"px",d.style.height=Math.round(S*M.offsetHeight)+"px")}function O(a){function b(a){return d===a.getAttributeNS(x,"name")}var c=z.getEleme [...]
++x,"annotation");a=z.getElementsByTagNameNS(a,x,"annotation-end");var d,e;for(e=0;e<c.length;e+=1)d=c[e].getAttributeNS(x,"name"),ca.addAnnotation({node:c[e],end:a.filter(b)[0]||null});ca.rerenderAnnotations()}function aa(a){la?(ba.parentNode||(M.appendChild(ba),y()),ca&&ca.forgetAnnotations(),ca=new gui.AnnotationViewManager(C,a.body,ba),O(a.body)):ba.parentNode&&(M.removeChild(ba),ca.forgetAnnotations(),y())}function J(k){function g(){f(d);d.style.display="inline-block";var q=U.rootEle [...]
++!0);R.setOdfContainer(U);var m=U,l=T;(new odf.FontLoader).loadFonts(m,l.sheet);p(U,R,$);l=U;m=X.sheet;f(d);M=Y.createElementNS(d.namespaceURI,"div");M.style.display="inline-block";M.style.background="white";M.appendChild(q);d.appendChild(M);ba=Y.createElementNS(d.namespaceURI,"div");ba.id="annotationsPane";da=Y.createElementNS(d.namespaceURI,"div");da.id="shadowContent";da.style.position="absolute";da.style.top=0;da.style.left=0;l.getContentElement().appendChild(da);var t=q.body,z,D=[], [...]
++z!==t;)if(z.namespaceURI===A&&(D[D.length]=z),z.firstElementChild)z=z.firstElementChild;else{for(;z&&z!==t&&!z.nextElementSibling;)z=z.parentElement;z&&z.nextElementSibling&&(z=z.nextElementSibling)}for(C=0;C<D.length;C+=1)z=D[C],h("frame"+String(C),z,m);D=W.getODFElementsWithXPath(t,".//*[*[@text:anchor-type='paragraph']]",odf.Namespaces.lookupNamespaceURI);for(z=0;z<D.length;z+=1)t=D[z],t.setAttributeNS&&t.setAttributeNS("urn:webodf:names:helper","containsparagraphanchor",!0);var t=da [...]
++var J,P,D=l.rootElement.ownerDocument;if((z=q.body.firstElementChild)&&z.namespaceURI===x&&("presentation"===z.localName||"drawing"===z.localName))for(z=z.firstElementChild;z;){C=z.getAttributeNS(A,"master-page-name");if(C){for(O=l.rootElement.masterStyles.firstElementChild;O&&(O.getAttributeNS(v,"name")!==C||"master-page"!==O.localName||O.namespaceURI!==v););C=O}else C=null;if(C){O=z.getAttributeNS("urn:webodf:names:helper","styleid");E=D.createElementNS(A,"draw:page");P=C.firstElement [...]
++0;P;)"true"!==P.getAttributeNS(L,"placeholder")&&(F=P.cloneNode(!0),E.appendChild(F),h(O+"_"+J,F,m)),P=P.nextElementSibling,J+=1;P=J=F=void 0;var V=E.getElementsByTagNameNS(A,"frame");for(F=0;F<V.length;F+=1)J=V[F],(P=J.getAttributeNS(L,"class"))&&!/^(date-time|footer|header|page-number')$/.test(P)&&J.parentNode.removeChild(J);t.appendChild(E);F=String(t.getElementsByTagNameNS(A,"page").length);n(E,H,"page-number",F);n(E,L,"header",r(l,z,"header"));n(E,L,"footer",r(l,z,"footer"));h(O,E, [...]
++"draw:master-page-name",C.getAttributeNS(v,"name"))}z=z.nextElementSibling}t=d.namespaceURI;D=q.body.getElementsByTagNameNS(s,"table-cell");for(z=0;z<D.length;z+=1)C=D.item(z),C.hasAttributeNS(s,"number-columns-spanned")&&C.setAttributeNS(t,"colspan",C.getAttributeNS(s,"number-columns-spanned")),C.hasAttributeNS(s,"number-rows-spanned")&&C.setAttributeNS(t,"rowspan",C.getAttributeNS(s,"number-rows-spanned"));c(q.body);e(q.body);a(q.body);b(q.body);u(l,q.body,m);w(l,q.body);C=q.body;l=d. [...]
++z={};var D={},K;O=I.document.getElementsByTagNameNS(H,"list-style");for(t=0;t<O.length;t+=1)J=O.item(t),(P=J.getAttributeNS(v,"name"))&&(D[P]=J);C=C.getElementsByTagNameNS(H,"list");for(t=0;t<C.length;t+=1)if(J=C.item(t),O=J.getAttributeNS(B,"id")){E=J.getAttributeNS(H,"continue-list");J.setAttributeNS(l,"id",O);F="text|list#"+O+" > text|list-item > *:first-child:before {";if(P=J.getAttributeNS(H,"style-name")){J=D[P];K=Q.getFirstNonWhitespaceChild(J);J=void 0;if(K)if("list-level-style- [...]
++K.localName){J=K.getAttributeNS(v,"num-format");P=K.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=K.getAttributeNS(v,"num-prefix")||"",S=V.hasOwnProperty(J)?S+(" counter(list, "+V[J]+")"):J?S+("'"+J+"';"):S+" ''";P&&(S+=" '"+P+"'");J=V="content: "+S+";"}else"list-level-style-image"===K.localName?J="content: none;":"list-level-style-bullet"===K.localName&&(J="content: '"+K.getAttributeNS(H,"bullet-ch [...]
++K=J}if(E){for(J=z[E];J;)J=z[J];F+="counter-increment:"+E+";";K?(K=K.replace("list",E),F+=K):F+="content:counter("+E+");"}else E="",K?(K=K.replace("list",O),F+=K):F+="content: counter("+O+");",F+="counter-increment:"+O+";",m.insertRule("text|list#"+O+" {counter-reset:"+O+"}",m.cssRules.length);F+="}";z[O]=E;F&&m.insertRule(F,m.cssRules.length)}M.insertBefore(da,M.firstChild);y();aa(q);if(!k&&(q=[U],ga.hasOwnProperty("statereadychange")))for(m=ga.statereadychange,K=0;K<m.length;K+=1)m[K]. [...]
++q)}U.state===odf.OdfContainer.DONE?g():(runtime.log("WARNING: refreshOdf called but ODF was not DONE."),runtime.setTimeout(function ha(){U.state===odf.OdfContainer.DONE?g():(runtime.log("will be back later..."),runtime.setTimeout(ha,500))},100))}function F(a){E.clearQueue();d.innerHTML=runtime.tr("Loading")+" "+a+"...";d.removeAttribute("style");U=new odf.OdfContainer(a,function(a){U=a;J(!1)})}runtime.assert(null!==d&&void 0!==d,"odf.OdfCanvas constructor needs DOM element");runtime.ass [...]
++d.ownerDocument&&void 0!==d.ownerDocument,"odf.OdfCanvas constructor needs DOM");var C=this,Y=d.ownerDocument,U,R=new odf.Formatting,P,M=null,ba=null,la=!1,ca=null,ma,T,$,X,da,S=1,ga={},E=new g;this.refreshCSS=function(){p(U,R,$);y()};this.refreshSize=function(){y()};this.odfContainer=function(){return U};this.setOdfContainer=function(a,b){U=a;J(!0===b)};this.load=this.load=F;this.save=function(a){U.save(a)};this.addListener=function(a,b){switch(a){case "click":var c=d,e=a;c.addEventLis [...]
++b,!1):c.attachEvent?c.attachEvent("on"+e,b):c["on"+e]=b;break;default:c=ga.hasOwnProperty(a)?ga[a]:ga[a]=[],b&&-1===c.indexOf(b)&&c.push(b)}};this.getFormatting=function(){return R};this.getAnnotationViewManager=function(){return ca};this.refreshAnnotations=function(){aa(U.rootElement)};this.rerenderAnnotations=function(){ca&&ca.rerenderAnnotations()};this.getSizer=function(){return M};this.enableAnnotations=function(a){a!==la&&(la=a,U&&aa(U.rootElement))};this.addAnnotation=function(a) [...]
++this.forgetAnnotations=function(){ca&&ca.forgetAnnotations()};this.setZoomLevel=function(a){S=a;y()};this.getZoomLevel=function(){return S};this.fitToContainingElement=function(a,b){var c=d.offsetHeight/S;S=a/(d.offsetWidth/S);b/c<S&&(S=b/c);y()};this.fitToWidth=function(a){S=a/(d.offsetWidth/S);y()};this.fitSmart=function(a,b){var c,e;c=d.offsetWidth/S;e=d.offsetHeight/S;c=a/c;void 0!==b&&b/e<c&&(c=b/e);S=Math.min(1,c);y()};this.fitToHeight=function(a){S=a/(d.offsetHeight/S);y()};this. [...]
++function(){P.showFirstPage()};this.showNextPage=function(){P.showNextPage()};this.showPreviousPage=function(){P.showPreviousPage()};this.showPage=function(a){P.showPage(a);y()};this.getElement=function(){return d};this.addCssForFrameWithImage=function(a){var b=a.getAttributeNS(A,"name"),c=a.firstElementChild;h(b,a,X.sheet);c&&m(b+"img",U,c,X.sheet)};this.destroy=function(a){var b=Y.getElementsByTagName("head")[0];ba&&ba.parentNode&&ba.parentNode.removeChild(ba);M&&(d.removeChild(M),M=nu [...]
++b.removeChild(T);b.removeChild($);b.removeChild(X);P.destroy(a)};ma=k(Y);P=new l(t(Y));T=t(Y);$=t(Y);X=t(Y)}})();
++// 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/
 +*/
- 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
++runtime.loadClass("core.DomUtils");runtime.loadClass("core.LoopWatchDog");runtime.loadClass("odf.Namespaces");
++odf.TextStyleApplicator=function(g,l,f){function p(c){function d(a,b){return"object"===typeof a&&"object"===typeof b?Object.keys(a).every(function(c){return d(a[c],b[c])}):a===b}this.isStyleApplied=function(a){a=l.getAppliedStylesForElement(a);return d(c,a)}}function r(c){var e={};this.applyStyleToContainer=function(a){var b;b=a.getAttributeNS(d,"style-name");var h=a.ownerDocument;b=b||"";if(!e.hasOwnProperty(b)){var k=b,n;n=b?l.createDerivedStyleObject(b,"text",c):c;h=h.createElementNS [...]
++l.updateStyle(h,n);h.setAttributeNS(m,"style:name",g.generateStyleName());h.setAttributeNS(m,"style:family","text");h.setAttributeNS("urn:webodf:names:scope","scope","document-content");f.appendChild(h);e[k]=h}b=e[b].getAttributeNS(m,"name");a.setAttributeNS(d,"text:style-name",b)}}function n(c,e){var a=c.ownerDocument,b=c.parentNode,f,k,g=new core.LoopWatchDog(1E4);k=[];"span"!==b.localName||b.namespaceURI!==d?(f=a.createElementNS(d,"text:span"),b.insertBefore(f,c),b=!1):(c.previousSib [...]
++b.firstChild)?(f=b.cloneNode(!1),b.parentNode.insertBefore(f,b.nextSibling)):f=b,b=!0);k.push(c);for(a=c.nextSibling;a&&h.rangeContainsNode(e,a);)g.check(),k.push(a),a=a.nextSibling;k.forEach(function(a){a.parentNode!==f&&f.appendChild(a)});if(a&&b)for(k=f.cloneNode(!1),f.parentNode.insertBefore(k,f.nextSibling);a;)g.check(),b=a.nextSibling,k.appendChild(a),a=b;return f}var h=new core.DomUtils,d=odf.Namespaces.textns,m=odf.Namespaces.stylens;this.applyStyle=function(c,d,a){var b={},f,h, [...]
++a.hasOwnProperty("style:text-properties"),"applyStyle without any text properties");b["style:text-properties"]=a["style:text-properties"];g=new r(b);m=new p(b);c.forEach(function(a){f=m.isStyleApplied(a);!1===f&&(h=n(a,d),g.applyStyleToContainer(h))})}};
++// 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/
 +*/
- 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"])}};
++runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.OdfUtils");
++gui.StyleHelper=function(g){function l(f,h,d){var g=!0,c;for(c=0;c<f.length&&!(g=f[c]["style:text-properties"],g=!g||g[h]!==d);c+=1);return!g}function f(f,h,d){function m(){b=!0;(e=g.getDefaultStyleElement("paragraph"))||(e=null)}var c,e;f=p.getParagraphElements(f);for(var a={},b=!1;0<f.length;){(c=f[0].getAttributeNS(r,"style-name"))?a[c]||(e=g.getStyleElement(c,"paragraph"),a[c]=!0,e||b||m()):b?e=void 0:m();if(void 0!==e&&(c=null===e?g.getSystemDefaultStyleAttributes("paragraph"):g.ge [...]
++!0),(c=c["style:paragraph-properties"])&&-1===d.indexOf(c[h])))return!1;f.pop()}return!0}var p=new odf.OdfUtils,r=odf.Namespaces.textns;this.getAppliedStyles=function(f){var h;f.collapsed?(h=f.startContainer,h.hasChildNodes()&&f.startOffset<h.childNodes.length&&(h=h.childNodes.item(f.startOffset)),f=[h]):f=p.getTextNodes(f,!0);return g.getAppliedStyles(f)};this.isBold=function(f){return l(f,"fo:font-weight","bold")};this.isItalic=function(f){return l(f,"fo:font-style","italic")};this.ha [...]
++function(f){return l(f,"style:text-underline-style","solid")};this.hasStrikeThrough=function(f){return l(f,"style:text-line-through-style","solid")};this.isAlignedLeft=function(g){return f(g,"fo:text-align",["left","start"])};this.isAlignedCenter=function(g){return f(g,"fo:text-align",["center"])};this.isAlignedRight=function(g){return f(g,"fo:text-align",["right","end"])};this.isAlignedJustified=function(g){return f(g,"fo:text-align",["justify"])}};
++// Input 43
++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 f(a,b,c,d){this.good_length=a;this.max_lazy=b;this.nice_length=c;this.max_chain=d}function p(){this.next=null;this.len=0;this.ptr=[];this.ptr.length=r;this.off=0}var r=8192,n,h,d,m,c=null,e,a,b,q,k,t,A,w,x,v,u,s,H,y,B,L,I,W,Q,z,ja,ka,G,Z,O,aa,J,F,C,Y,U,R,P,M,ba,la,ca,ma,T,$,X,da,S,ga,E,fa,D,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],sa=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],xa=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],ra;ra=[new f(0,0,0,0),new f(4,4,8,4),new f(4,5,16,8),new f(4,6,32,32),new f(4,4,16,16),new f(8,16,32,32),new f(8,16,128,128),new f(8,32,128,256),new f(32,128,258,1024),new f(32,258,258,4096)];var Aa=function(b){c[a+e++]=b;if(a+e===r){var f;if(0!==e){null!==n?(b=n,n=n. [...]
++b.next=null;b.len=b.off=0;null===h?h=d=b:d=d.next=b;b.len=e-a;for(f=0;f<b.len;f++)b.ptr[f]=c[a+f];e=a=0}}},ta=function(b){b&=65535;a+e<r-2?(c[a+e++]=b&255,c[a+e++]=b>>>8):(Aa(b&255),Aa(b>>>8))},Ba=function(){u=(u<<5^q[I+3-1]&255)&8191;s=A[32768+u];A[I&32767]=s;A[32768+u]=I},V=function(a,b){x>16-b?(w|=a<<x,ta(w),w=a>>16-x,x+=b-16):(w|=a<<x,x+=b)},K=function(a,b){V(b[a].fc,b[a].dl)},ua=function(a,b,c){return a[b].fc<a[c].fc||a[b].fc===a[c].fc&&ca[b]<=ca[c]},na=function(a,b,c){var d;for(d= [...]
++ia.length;d++)a[b+d]=ia.charCodeAt(Da++)&255;return d},ea=function(){var a,b,c=65536-z-I;if(-1===c)c--;else if(65274<=I){for(a=0;32768>a;a++)q[a]=q[a+32768];W-=32768;I-=32768;v-=32768;for(a=0;8192>a;a++)b=A[32768+a],A[32768+a]=32768<=b?b-32768:0;for(a=0;32768>a;a++)b=A[a],A[a]=32768<=b?b-32768:0;c+=32768}Q||(a=na(q,I+z,c),0>=a?Q=!0:z+=a)},oa=function(a){var b=ja,c=I,d,e=L,f=32506<I?I-32506:0,h=I+258,k=q[c+e-1],g=q[c+e];L>=Z&&(b>>=2);do if(d=a,q[d+e]===g&&q[d+e-1]===k&&q[d]===q[c]&&q[++d [...]
++2;d++;do++c;while(q[c]===q[++d]&&q[++c]===q[++d]&&q[++c]===q[++d]&&q[++c]===q[++d]&&q[++c]===q[++d]&&q[++c]===q[++d]&&q[++c]===q[++d]&&q[++c]===q[++d]&&c<h);d=258-(h-c);c=h-258;if(d>e){W=a;e=d;if(258<=d)break;k=q[c+e-1];g=q[c+e]}a=A[a&32767]}while(a>f&&0!==--b);return e},Ca=function(a,b){t[S++]=b;0===a?O[b].fc++:(a--,O[ma[b]+256+1].fc++,aa[(256>a?T[a]:T[256+(a>>7)])&255].fc++,k[ga++]=a,fa|=D);D<<=1;0===(S&7)&&(da[E++]=fa,fa=0,D=1);if(2<G&&0===(S&4095)){var c=8*S,d=I-v,e;for(e=0;30>e;e++ [...]
++(5+qa[e]);c>>=3;if(ga<parseInt(S/2,10)&&c<parseInt(d/2,10))return!0}return 8191===S||8192===ga},ya=function(a,b){for(var c=M[b],d=b<<1;d<=ba;){d<ba&&ua(a,M[d+1],M[d])&&d++;if(ua(a,c,M[d]))break;M[b]=M[d];b=d;d<<=1}M[b]=c},Ea=function(a,b){var c=0;do c|=a&1,a>>=1,c<<=1;while(0<--b);return c>>1},za=function(a,b){var c=[];c.length=16;var d=0,e;for(e=1;15>=e;e++)d=d+P[e-1]<<1,c[e]=d;for(d=0;d<=b;d++)e=a[d].dl,0!==e&&(a[d].fc=Ea(c[e]++,e))},va=function(a){var b=a.dyn_tree,c=a.static_tree,d=a [...]
++-1,h=d;ba=0;la=573;for(e=0;e<d;e++)0!==b[e].fc?(M[++ba]=f=e,ca[e]=0):b[e].dl=0;for(;2>ba;)e=M[++ba]=2>f?++f:0,b[e].fc=1,ca[e]=0,pa--,null!==c&&(ha-=c[e].dl);a.max_code=f;for(e=ba>>1;1<=e;e--)ya(b,e);do e=M[1],M[1]=M[ba--],ya(b,1),c=M[1],M[--la]=e,M[--la]=c,b[h].fc=b[e].fc+b[c].fc,ca[h]=ca[e]>ca[c]+1?ca[e]:ca[c]+1,b[e].dl=b[c].dl=h,M[1]=h++,ya(b,1);while(2<=ba);M[--la]=M[1];h=a.dyn_tree;e=a.extra_bits;var d=a.extra_base,c=a.max_code,k=a.max_length,g=a.static_tree,q,m,l,p,n=0;for(m=0;15>= [...]
++0;h[M[la]].dl=0;for(a=la+1;573>a;a++)q=M[a],m=h[h[q].dl].dl+1,m>k&&(m=k,n++),h[q].dl=m,q>c||(P[m]++,l=0,q>=d&&(l=e[q-d]),p=h[q].fc,pa+=p*(m+l),null!==g&&(ha+=p*(g[q].dl+l)));if(0!==n){do{for(m=k-1;0===P[m];)m--;P[m]--;P[m+1]+=2;P[k]--;n-=2}while(0<n);for(m=k;0!==m;m--)for(q=P[m];0!==q;)e=M[--a],e>c||(h[e].dl!==m&&(pa+=(m-h[e].dl)*h[e].fc,h[e].fc=m),q--)}za(b,f)},Fa=function(a,b){var c,d=-1,e,f=a[0].dl,h=0,k=7,g=4;0===f&&(k=138,g=3);a[b+1].dl=65535;for(c=0;c<=b;c++)e=f,f=a[c+1].dl,++h<k& [...]
++g?C[e].fc+=h:0!==e?(e!==d&&C[e].fc++,C[16].fc++):10>=h?C[17].fc++:C[18].fc++,h=0,d=e,0===f?(k=138,g=3):e===f?(k=6,g=3):(k=7,g=4))},wa=function(){8<x?ta(w):0<x&&Aa(w);x=w=0},Ha=function(a,b){var c,d=0,e=0,f=0,h=0,g,q;if(0!==S){do 0===(d&7)&&(h=da[f++]),c=t[d++]&255,0===(h&1)?K(c,a):(g=ma[c],K(g+256+1,a),q=N[g],0!==q&&(c-=$[g],V(c,q)),c=k[e++],g=(256>c?T[c]:T[256+(c>>7)])&255,K(g,b),q=qa[g],0!==q&&(c-=X[g],V(c,q))),h>>=1;while(d<S)}K(256,a)},Ia=function(a,b){var c,d=-1,e,f=a[0].dl,h=0,k=7 [...]
++(k=138,g=3);for(c=0;c<=b;c++)if(e=f,f=a[c+1].dl,!(++h<k&&e===f)){if(h<g){do K(e,C);while(0!==--h)}else 0!==e?(e!==d&&(K(e,C),h--),K(16,C),V(h-3,2)):10>=h?(K(17,C),V(h-3,3)):(K(18,C),V(h-11,7));h=0;d=e;0===f?(k=138,g=3):e===f?(k=6,g=3):(k=7,g=4)}},Ja=function(){var a;for(a=0;286>a;a++)O[a].fc=0;for(a=0;30>a;a++)aa[a].fc=0;for(a=0;19>a;a++)C[a].fc=0;O[256].fc=1;fa=S=ga=E=pa=ha=0;D=1},Ga=function(a){var b,c,d,e;e=I-v;da[E]=fa;va(Y);va(U);Fa(O,Y.max_code);Fa(aa,U.max_code);va(R);for(d=18;3< [...]
++pa+=3*(d+1)+14;b=pa+3+7>>3;c=ha+3+7>>3;c<=b&&(b=c);if(e+4<=b&&0<=v)for(V(0+a,3),wa(),ta(e),ta(~e),d=0;d<e;d++)Aa(q[v+d]);else if(c===b)V(2+a,3),Ha(J,F);else{V(4+a,3);e=Y.max_code+1;b=U.max_code+1;d+=1;V(e-257,5);V(b-1,5);V(d-4,4);for(c=0;c<d;c++)V(C[xa[c]].dl,3);Ia(O,e-1);Ia(aa,b-1);Ha(O,aa)}Ja();0!==a&&wa()},Ka=function(b,d,f){var k,g,q;for(k=0;null!==h&&k<f;){g=f-k;g>h.len&&(g=h.len);for(q=0;q<g;q++)b[d+k+q]=h.ptr[h.off+q];h.off+=g;h.len-=g;k+=g;0===h.len&&(g=h,h=h.next,g.next=n,n=g)} [...]
++if(a<e){g=f-k;g>e-a&&(g=e-a);for(q=0;q<g;q++)b[d+k+q]=c[a+q];a+=g;k+=g;e===a&&(e=a=0)}return k},La=function(c,d,f){var k;if(!m){if(!Q){x=w=0;var g,l;if(0===F[0].dl){Y.dyn_tree=O;Y.static_tree=J;Y.extra_bits=N;Y.extra_base=257;Y.elems=286;Y.max_length=15;Y.max_code=0;U.dyn_tree=aa;U.static_tree=F;U.extra_bits=qa;U.extra_base=0;U.elems=30;U.max_length=15;U.max_code=0;R.dyn_tree=C;R.static_tree=null;R.extra_bits=sa;R.extra_base=0;R.elems=19;R.max_length=7;for(l=g=R.max_code=0;28>l;l++)for( [...]
++1<<N[l];k++)ma[g++]=l;ma[g-1]=l;for(l=g=0;16>l;l++)for(X[l]=g,k=0;k<1<<qa[l];k++)T[g++]=l;for(g>>=7;30>l;l++)for(X[l]=g<<7,k=0;k<1<<qa[l]-7;k++)T[256+g++]=l;for(k=0;15>=k;k++)P[k]=0;for(k=0;143>=k;)J[k++].dl=8,P[8]++;for(;255>=k;)J[k++].dl=9,P[9]++;for(;279>=k;)J[k++].dl=7,P[7]++;for(;287>=k;)J[k++].dl=8,P[8]++;za(J,287);for(k=0;30>k;k++)F[k].dl=5,F[k].fc=Ea(k,5);Ja()}for(k=0;8192>k;k++)A[32768+k]=0;ka=ra[G].max_lazy;Z=ra[G].good_length;ja=ra[G].max_chain;v=I=0;z=na(q,0,65536);if(0>=z)Q [...]
++!1;262>z&&!Q;)ea();for(k=u=0;2>k;k++)u=(u<<5^q[k]&255)&8191}h=null;a=e=0;3>=G?(L=2,B=0):(B=2,y=0);b=!1}m=!0;if(0===z)return b=!0,0}k=Ka(c,d,f);if(k===f)return f;if(b)return k;if(3>=G)for(;0!==z&&null===h;){Ba();0!==s&&32506>=I-s&&(B=oa(s),B>z&&(B=z));if(3<=B)if(l=Ca(I-W,B-3),z-=B,B<=ka){B--;do I++,Ba();while(0!==--B);I++}else I+=B,B=0,u=q[I]&255,u=(u<<5^q[I+1]&255)&8191;else l=Ca(0,q[I]&255),z--,I++;l&&(Ga(0),v=I);for(;262>z&&!Q;)ea()}else for(;0!==z&&null===h;){Ba();L=B;H=W;B=2;0!==s&& [...]
++I-s&&(B=oa(s),B>z&&(B=z),3===B&&4096<I-W&&B--);if(3<=L&&B<=L){l=Ca(I-1-H,L-3);z-=L-1;L-=2;do I++,Ba();while(0!==--L);y=0;B=2;I++;l&&(Ga(0),v=I)}else 0!==y?Ca(0,q[I-1]&255)&&(Ga(0),v=I):y=1,I++,z--;for(;262>z&&!Q;)ea()}0===z&&(0!==y&&Ca(0,q[I-1]&255),Ga(1),b=!0);return k+Ka(c,k+d,f-k)};this.deflate=function(a,b){var e,f;ia=a;Da=0;"undefined"===String(typeof b)&&(b=6);(e=b)?1>e?e=1:9<e&&(e=9):e=6;G=e;Q=m=!1;if(null===c){n=h=d=null;c=[];c.length=r;q=[];q.length=65536;k=[];k.length=8192;t=[ [...]
++32832;A=[];A.length=65536;O=[];O.length=573;for(e=0;573>e;e++)O[e]=new g;aa=[];aa.length=61;for(e=0;61>e;e++)aa[e]=new g;J=[];J.length=288;for(e=0;288>e;e++)J[e]=new g;F=[];F.length=30;for(e=0;30>e;e++)F[e]=new g;C=[];C.length=39;for(e=0;39>e;e++)C[e]=new g;Y=new l;U=new l;R=new l;P=[];P.length=16;M=[];M.length=573;ca=[];ca.length=573;ma=[];ma.length=256;T=[];T.length=512;$=[];$.length=29;X=[];X.length=30;da=[];da.length=1024}var p=Array(1024),v=[],s=[];for(e=La(p,0,p.length);0<e;){s.le [...]
++0;f<e;f++)s[f]=String.fromCharCode(p[f]);v[v.length]=s.join("");e=La(p,0,p.length)}ia="";return v.join("")}};
 +// 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
++gui.ImageSelector=function(g){function l(){var f=g.getSizer(),d,m;d=r.createElement("div");d.id="imageSelector";d.style.borderWidth="1px";f.appendChild(d);p.forEach(function(c){m=r.createElement("div");m.className=c;d.appendChild(m)});return d}var f=odf.Namespaces.svgns,p="topLeft topRight bottomRight bottomLeft topMiddle rightMiddle bottomMiddle leftMiddle".split(" "),r=g.getElement().ownerDocument,n=!1;this.select=function(h){var d,m,c=r.getElementById("imageSelector");c||(c=l());n=!0 [...]
++m=h.getBoundingClientRect();var e=d.getBoundingClientRect(),a=g.getZoomLevel();d=(m.left-e.left)/a-1;m=(m.top-e.top)/a-1;c.style.display="block";c.style.left=d+"px";c.style.top=m+"px";c.style.width=h.getAttributeNS(f,"width");c.style.height=h.getAttributeNS(f,"height")};this.clearSelection=function(){var f;n&&(f=r.getElementById("imageSelector"))&&(f.style.display="none");n=!1};this.isSelectorElement=function(f){var d=r.getElementById("imageSelector");return d?f===d||f.parentNode===d:!1}};
++// Input 45
 +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
++odf.CommandLineTools=function(){this.roundTrip=function(g,l,f){return new odf.OdfContainer(g,function(p){if(p.state===odf.OdfContainer.INVALID)return f("Document "+g+" is invalid.");p.state===odf.OdfContainer.DONE?p.saveAs(l,function(g){f(g)}):f("Document was not completely loaded.")})};this.render=function(g,l,f){for(l=l.getElementsByTagName("body")[0];l.firstChild;)l.removeChild(l.firstChild);l=new odf.OdfCanvas(l);l.addListener("statereadychange",function(g){f(g)});l.load(g)}};
++// Input 46
 +/*
 +
 + 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
++ops.Member=function(g,l){var f={};this.getMemberId=function(){return g};this.getProperties=function(){return f};this.setProperties=function(g){Object.keys(g).forEach(function(l){f[l]=g[l]})};this.removeProperties=function(g){delete g.fullName;delete g.color;delete g.imageUrl;Object.keys(g).forEach(function(g){f.hasOwnProperty(g)&&delete f[g]})};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");f=l};
++// Input 47
 +/*
 +
 + 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(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
++(function(){function g(f,g,r){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)===t)break;while(a.nextPosition())}}function h(a){return a.nodeType===Node.ELEMENT_NODE&&a.getAttributeNS(c,"nodeId")}function d(a){var b=l;a.setAttributeNS(c,"nodeId",b.toString());l+=1;return b}function m(b,d){var e,k=null;for(b=b. [...]
++b;!k&&b&&b!==f;)(e=h(b))&&(k=a[e])&&k.node!==b&&(runtime.log("Cloned node detected. Creating new bookmark"),k=null,b.removeAttributeNS(c,"nodeId")),b=b.parentNode;return k}var c="urn:webodf:names:steps",e={},a={},b=new odf.OdfUtils,q=new core.DomUtils,k,t=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.updateCache=function(c,f,k,g){var q;0===k&&b.isParagraph(f)?(q=!0,g||(c+=1)):f.hasChildNodes()&&f.childNodes[k]&&(f=f.childNodes[k],(q=b.isParagraph(f))&&(c+=1));q&&(k=h(f)||d(f),(g=a [...]
++f?g.steps=c:(runtime.log("Cloned node detected. Creating new bookmark"),k=d(f),g=a[k]=new n(c,f)):g=a[k]=new n(c,f),k=g,c=Math.ceil(k.steps/r)*r,f=e[c],!f||k.steps>f.steps)&&(e[c]=k)};this.setToClosestStep=function(a,b){for(var c=Math.floor(a/r)*r,d;!d&&0!==c;)d=e[c],c-=r;d=d||k;d.setIteratorPosition(b);return d.steps};this.setToClosestDomPoint=function(a,b,c){var d;if(a===f&&0===b)d=k;else if(a===f&&b===f.childNodes.length)d=Object.keys(e).map(function(a){return e[a]}).reduce(function( [...]
++a.steps?b:a},k);else if(d=m(a,b),!d)for(c.setUnfilteredPosition(a,b);!d&&c.previousNode();)d=m(c.container(),c.unfilteredDomOffset());d=d||k;d.setIteratorPosition(c);return d.steps};this.updateCacheAtPoint=function(b,c){var d={};Object.keys(a).map(function(b){return a[b]}).filter(function(a){return a.steps>b}).forEach(function(b){var k=Math.ceil(b.steps/r)*r,g,m;if(q.containsNode(f,b.node)){if(c(b),g=Math.ceil(b.steps/r)*r,m=d[g],!m||b.steps>m.steps)d[g]=b}else delete a[h(b.node)];e[k]= [...]
++Object.keys(d).forEach(function(a){e[a]=d[a]})};k=new function(a,b){this.steps=a;this.node=b;this.setIteratorPosition=function(a){a.setUnfilteredPosition(b,0);do if(g.acceptPosition(a)===t)break;while(a.nextPosition())}}(0,f)}var l=0;ops.StepsTranslator=function(f,l,r,n){function h(){var b=f();b!==m&&(runtime.log("Undo detected. Resetting steps cache"),m=b,c=new g(m,r,n),a=l(m))}function d(a,c){if(!c||r.acceptPosition(a)===b)return!0;for(;a.previousPosition();)if(r.acceptPosition(a)===b [...]
++a.unfilteredDomOffset()))return!0;break}for(;a.nextPosition();)if(r.acceptPosition(a)===b){if(c(1,a.container(),a.unfilteredDomOffset()))return!0;break}return!1}var m=f(),c=new g(m,r,n),e=new core.DomUtils,a=l(f()),b=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.convertStepsToDomPoint=function(d){var e,f;0>d&&(runtime.log("warn","Requested steps were negative ("+d+")"),d=0);h();for(e=c.setToClosestStep(d,a);e<d&&a.nextPosition();)(f=r.acceptPosition(a)===b)&&(e+=1),c.updateCache(e [...]
++a.unfilteredDomOffset(),f);e!==d&&runtime.log("warn","Requested "+d+" steps but only "+e+" are available");return{node:a.container(),offset:a.unfilteredDomOffset()}};this.convertDomPointToSteps=function(f,k,g){var l;h();e.containsNode(m,f)||(k=0>e.comparePoints(m,0,f,k),f=m,k=k?0:m.childNodes.length);a.setUnfilteredPosition(f,k);d(a,g)||a.setUnfilteredPosition(f,k);g=a.container();k=a.unfilteredDomOffset();f=c.setToClosestDomPoint(g,k,a);if(0>e.comparePoints(a.container(),a.unfilteredDo [...]
++g,k))return 0<f?f-1:f;for(;(a.container()!==g||a.unfilteredDomOffset()!==k)&&a.nextPosition();)(l=r.acceptPosition(a)===b)&&(f+=1),c.updateCache(f,a.container(),a.unfilteredDomOffset(),l);return f+0};this.prime=function(){var d,e;h();for(d=c.setToClosestStep(0,a);a.nextPosition();)(e=r.acceptPosition(a)===b)&&(d+=1),c.updateCache(d,a.container(),a.unfilteredDomOffset(),e)};this.handleStepsInserted=function(a){h();c.updateCacheAtPoint(a.position,function(b){b.steps+=a.length})};this.hand [...]
++function(a){h();c.updateCacheAtPoint(a.position,function(b){b.steps-=a.length;0>b.steps&&(b.steps=0)})}};ops.StepsTranslator.PREVIOUS_STEP=0;ops.StepsTranslator.NEXT_STEP=1;return ops.StepsTranslator})();
++// Input 48
 +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
++xmldom.RelaxNGParser=function(){function g(c,d){this.message=function(){d&&(c+=1===d.nodeType?" Element ":" Node ",c+=d.nodeName,d.nodeValue&&(c+=" with value '"+d.nodeValue+"'"),c+=".");return c}}function l(c){if(2>=c.e.length)return c;var d={name:c.name,e:c.e.slice(0,2)};return l({name:c.name,e:[d].concat(c.e.slice(2))})}function f(c){c=c.split(":",2);var e="",a;1===c.length?c=["",c[0]]:e=c[0];for(a in d)d[a]===e&&(c[0]=a);return c}function p(c,d){for(var a=0,b,h,k=c.name;c.e&&a<c.e.l [...]
++"ref"===b.name){h=d[b.a.name];if(!h)throw b.a.name+" was not defined.";b=c.e.slice(a+1);c.e=c.e.slice(0,a);c.e=c.e.concat(h.e);c.e=c.e.concat(b)}else a+=1,p(b,d);b=c.e;"choice"!==k||b&&b[1]&&"empty"!==b[1].name||(b&&b[0]&&"empty"!==b[0].name?(b[1]=b[0],b[0]={name:"empty"}):(delete c.e,c.name="empty"));if("group"===k||"interleave"===k)"empty"===b[0].name?"empty"===b[1].name?(delete c.e,c.name="empty"):(k=c.name=b[1].name,c.names=b[1].names,b=c.e=b[1].e):"empty"===b[1].name&&(k=c.name=b[0 [...]
++b[0].names,b=c.e=b[0].e);"oneOrMore"===k&&"empty"===b[0].name&&(delete c.e,c.name="empty");if("attribute"===k){h=c.names?c.names.length:0;for(var g,m=[],l=[],a=0;a<h;a+=1)g=f(c.names[a]),l[a]=g[0],m[a]=g[1];c.localnames=m;c.namespaces=l}"interleave"===k&&("interleave"===b[0].name?c.e="interleave"===b[1].name?b[0].e.concat(b[1].e):[b[1]].concat(b[0].e):"interleave"===b[1].name&&(c.e=[b[0]].concat(b[1].e)))}function r(c,d){for(var a=0,b;c.e&&a<c.e.length;)b=c.e[a],"elementref"===b.name?(b [...]
++0,c.e[a]=d[b.id]):"element"!==b.name&&r(b,d),a+=1}var n=this,h,d={"http://www.w3.org/XML/1998/namespace":"xml"},m;m=function(c,e,a){var b=[],h,g,n=c.localName,p=[];h=c.attributes;var r=n,x=p,v={},u,s;for(u=0;h&&u<h.length;u+=1)if(s=h.item(u),s.namespaceURI)"http://www.w3.org/2000/xmlns/"===s.namespaceURI&&(d[s.value]=s.localName);else{"name"!==s.localName||"element"!==r&&"attribute"!==r||x.push(s.value);if("name"===s.localName||"combine"===s.localName||"type"===s.localName){var H=s,y;y= [...]
++y.replace(/^\s\s*/,"");for(var B=/\s/,L=y.length-1;B.test(y.charAt(L));)L-=1;y=y.slice(0,L+1);H.value=y}v[s.localName]=s.value}h=v;h.combine=h.combine||void 0;c=c.firstChild;r=b;x=p;for(v="";c;){if(c.nodeType===Node.ELEMENT_NODE&&"http://relaxng.org/ns/structure/1.0"===c.namespaceURI){if(u=m(c,e,r))"name"===u.name?x.push(d[u.a.ns]+":"+u.text):"choice"===u.name&&u.names&&u.names.length&&(x=x.concat(u.names),delete u.names),r.push(u)}else c.nodeType===Node.TEXT_NODE&&(v+=c.nodeValue);c=c. [...]
++v;"value"!==n&&"param"!==n&&(c=/^\s*([\s\S]*\S)?\s*$/.exec(c)[1]);"value"===n&&void 0===h.type&&(h.type="token",h.datatypeLibrary="");"attribute"!==n&&"element"!==n||void 0===h.name||(g=f(h.name),b=[{name:"name",text:g[1],a:{ns:g[0]}}].concat(b),delete h.name);"name"===n||"nsName"===n||"value"===n?void 0===h.ns&&(h.ns=""):delete h.ns;"name"===n&&(g=f(c),h.ns=g[0],c=g[1]);1<b.length&&("define"===n||"oneOrMore"===n||"zeroOrMore"===n||"optional"===n||"list"===n||"mixed"===n)&&(b=[{name:"gr [...]
++e:b}).e}]);2<b.length&&"element"===n&&(b=[b[0]].concat({name:"group",e:l({name:"group",e:b.slice(1)}).e}));1===b.length&&"attribute"===n&&b.push({name:"text",text:c});1!==b.length||"choice"!==n&&"group"!==n&&"interleave"!==n?2<b.length&&("choice"===n||"group"===n||"interleave"===n)&&(b=l({name:n,e:b}).e):(n=b[0].name,p=b[0].names,h=b[0].a,c=b[0].text,b=b[0].e);"mixed"===n&&(n="interleave",b=[b[0],{name:"text"}]);"optional"===n&&(n="choice",b=[b[0],{name:"empty"}]);"zeroOrMore"===n&&(n=" [...]
++[{name:"oneOrMore",e:[b[0]]},{name:"empty"}]);if("define"===n&&h.combine){a:{r=h.combine;x=h.name;v=b;for(u=0;a&&u<a.length;u+=1)if(s=a[u],"define"===s.name&&s.a&&s.a.name===x){s.e=[{name:r,e:s.e.concat(v)}];a=s;break a}a=null}if(a)return null}a={name:n};b&&0<b.length&&(a.e=b);for(g in h)if(h.hasOwnProperty(g)){a.a=h;break}void 0!==c&&(a.text=c);p&&0<p.length&&(a.names=p);"element"===n&&(a.id=e.length,e.push(a),a={name:"elementref",id:a.id});return a};this.parseRelaxNGDOM=function(c,e){ [...]
++m(c&&c.documentElement,a,void 0),f,k,l={};for(f=0;f<b.e.length;f+=1)k=b.e[f],"define"===k.name?l[k.a.name]=k:"start"===k.name&&(h=k);if(!h)return[new g("No Relax NG start element was found.")];p(h,l);for(f in l)l.hasOwnProperty(f)&&p(l[f],l);for(f=0;f<a.length;f+=1)p(a[f],l);e&&(n.rootPattern=e(h.e[0],a));r(h,a);for(f=0;f<a.length;f+=1)r(a[f],a);n.start=h;n.elements=a;n.nsmap=d;return null}};
++// Input 49
 +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
++ops.OdtCursor=function(g,l){var f=this,p={},r,n,h;this.removeFromOdtDocument=function(){h.remove()};this.move=function(d,h){var c=0;0<d?c=n.movePointForward(d,h):0>=d&&(c=-n.movePointBackward(-d,h));f.handleUpdate();return c};this.handleUpdate=function(){};this.getStepCounter=function(){return n.getStepCounter()};this.getMemberId=function(){return g};this.getNode=function(){return h.getNode()};this.getAnchorNode=function(){return h.getAnchorNode()};this.getSelectedRange=function(){retur [...]
++this.setSelectedRange=function(d,g){h.setSelectedRange(d,g);f.handleUpdate()};this.hasForwardSelection=function(){return h.hasForwardSelection()};this.getOdtDocument=function(){return l};this.getSelectionType=function(){return r};this.setSelectionType=function(d){p.hasOwnProperty(d)?r=d:runtime.log("Invalid selection type: "+d)};this.resetSelectionType=function(){f.setSelectionType(ops.OdtCursor.RangeSelection)};h=new core.Cursor(l.getDOM(),g);n=new gui.SelectionMover(h,l.getRootNode()) [...]
++!0;p[ops.OdtCursor.RegionSelection]=!0;f.resetSelectionType()};ops.OdtCursor.RangeSelection="Range";ops.OdtCursor.RegionSelection="Region";(function(){return ops.OdtCursor})();
++// Input 50
 +/*
 +
 + 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 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
++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 f(){return l().ownerDocument}function p(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 r(b){this.acceptPosition=function(c){c=c.container();var d;d="str [...]
++a[b].getNode():b;return p(c)===p(d)?k:t}}function n(a){var b=gui.SelectionMover.createPositionIterator(l());a=w.convertStepsToDomPoint(a);b.setUnfilteredPosition(a.node,a.offset);return b}function h(a,b){return g.getFormatting().getStyleElement(a,b)}function d(a){return h(a,"paragraph")}var m=this,c,e,a={},b={},q=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]),k=core.PositionFilter.FilterResult.FILTER_ACCEPT,t=core.PositionFilter.FilterResult.FILTER_REJECT,A,w,x;th [...]
++f;this.getRootElement=p;this.getIteratorAtPosition=n;this.convertDomPointToCursorStep=function(a,b,c){return w.convertDomPointToSteps(a,b,c)};this.convertDomToCursorRange=function(a,b){var c,d;c=b(a.anchorNode,a.anchorOffset);c=w.convertDomPointToSteps(a.anchorNode,a.anchorOffset,c);b||a.anchorNode!==a.focusNode||a.anchorOffset!==a.focusOffset?(d=b(a.focusNode,a.focusOffset),d=w.convertDomPointToSteps(a.focusNode,a.focusOffset,d)):d=c;return{position:c,length:d-c}};this.convertCursorToD [...]
++b){var c=f().createRange(),d,e;d=w.convertStepsToDomPoint(a);b?(e=w.convertStepsToDomPoint(a+b),0<b?(c.setStart(d.node,d.offset),c.setEnd(e.node,e.offset)):(c.setStart(e.node,e.offset),c.setEnd(d.node,d.offset))):c.setStart(d.node,d.offset);return c};this.getStyleElement=h;this.upgradeWhitespacesAtPosition=function(a){a=n(a);var b,d,e;a.previousPosition();a.previousPosition();for(e=-1;1>=e;e+=1){b=a.container();d=a.unfilteredDomOffset();if(b.nodeType===Node.TEXT_NODE&&" "===b.data[d]&&c [...]
++d)){runtime.assert(" "===b.data[d],"upgradeWhitespaceToElement: textNode.data[offset] should be a literal space");var f=b.ownerDocument.createElementNS(odf.Namespaces.textns,"text:s");f.appendChild(b.ownerDocument.createTextNode(" "));b.deleteData(d,1);0<d&&(b=b.splitText(d));b.parentNode.insertBefore(f,b);b=f;a.moveToEndOfNode(b)}a.nextPosition()}};this.downgradeWhitespacesAtPosition=function(a){var b=n(a),d;a=b.container();for(b=b.unfilteredDomOffset();!c.isSpaceElement(a)&&a.childNod [...]
++b=0;a.nodeType===Node.TEXT_NODE&&(a=a.parentNode);c.isDowngradableSpaceElement(a)&&(b=a.firstChild,d=a.lastChild,e.mergeIntoParent(a),d!==b&&e.normalizeTextNodes(d),e.normalizeTextNodes(b))};this.getParagraphStyleElement=d;this.getParagraphElement=function(a){return c.getParagraphElement(a)};this.getParagraphStyleAttributes=function(a){return(a=d(a))?g.getFormatting().getInheritedStyleAttributes(a):null};this.getTextNodeAtStep=function(b,c){var d=n(b),e=d.container(),h,g=0,k=null;e.node [...]
++(h=e,g=d.unfilteredDomOffset(),0<h.length&&(0<g&&(h=h.splitText(g)),h.parentNode.insertBefore(f().createTextNode(""),h),h=h.previousSibling,g=0)):(h=f().createTextNode(""),g=0,e.insertBefore(h,d.rightNode()));if(c){if(a[c]&&m.getCursorPosition(c)===b){for(k=a[c].getNode();k.nextSibling&&"cursor"===k.nextSibling.localName;)k.parentNode.insertBefore(k.nextSibling,k);0<h.length&&h.nextSibling!==k&&(h=f().createTextNode(""),g=0);k.parentNode.insertBefore(h,k)}}else for(;h.nextSibling&&"curs [...]
++h);for(;h.previousSibling&&h.previousSibling.nodeType===Node.TEXT_NODE;)h.previousSibling.appendData(h.data),g=h.previousSibling.length,h=h.previousSibling,h.parentNode.removeChild(h.nextSibling);for(;h.nextSibling&&h.nextSibling.nodeType===Node.TEXT_NODE;)h.appendData(h.nextSibling.data),h.parentNode.removeChild(h.nextSibling);return{textNode:h,offset:g}};this.fixCursorPositions=function(){var b=new core.PositionFilterChain;b.addFilter("BaseFilter",A);Object.keys(a).forEach(function(c) [...]
++e=d.getStepCounter(),f,h,g=!1;b.addFilter("RootFilter",m.createRootFilter(c));c=e.countStepsToPosition(d.getAnchorNode(),0,b);e.isPositionWalkable(b)?0===c&&(g=!0,d.move(0)):(g=!0,f=e.countPositionsToNearestStep(d.getNode(),0,b),h=e.countPositionsToNearestStep(d.getAnchorNode(),0,b),d.move(f),0!==c&&(0<h&&(c+=1),0<f&&(c-=1),e=e.countSteps(c,b),d.move(e),d.move(-e,!0)));g&&m.emit(ops.OdtDocument.signalCursorMoved,d);b.removeFilter("RootFilter")})};this.getDistanceFromCursor=function(b,c, [...]
++var e,f;runtime.assert(null!==c&&void 0!==c,"OdtDocument.getDistanceFromCursor called without node");b&&(e=w.convertDomPointToSteps(b.getNode(),0),f=w.convertDomPointToSteps(c,d));return f-e};this.getCursorPosition=function(b){return(b=a[b])?w.convertDomPointToSteps(b.getNode(),0):0};this.getCursorSelection=function(b){b=a[b];var c=0,d=0;b&&(c=w.convertDomPointToSteps(b.getNode(),0),d=w.convertDomPointToSteps(b.getAnchorNode(),0));return{position:d,length:c-d}};this.getPositionFilter=fu [...]
++this.getOdfCanvas=function(){return g};this.getRootNode=l;this.addMember=function(a){runtime.assert(void 0===b[a.getMemberId()],"This member already exists");b[a.getMemberId()]=a};this.getMember=function(a){return b.hasOwnProperty(a)?b[a]:null};this.removeMember=function(a){delete b[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,A),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],m.emit(ops.OdtDocument.signalCursorRemoved,b),!0):!1};this.moveCursor=function(b,c,d,e){b=a[b];c=m.convertCursorToDomRange(c,d);b&&c&&(b.setSel [...]
++0<=d),b.setSelectionType(e||ops.OdtCursor.RangeSelection))};this.getFormatting=function(){return g.getFormatting()};this.emit=function(a,b){q.emit(a,b)};this.subscribe=function(a,b){q.subscribe(a,b)};this.unsubscribe=function(a,b){q.unsubscribe(a,b)};this.createRootFilter=function(a){return new r(a)};this.close=function(a){a()};this.destroy=function(a){a()};A=new ops.TextPositionFilter(l);c=new odf.OdfUtils;e=new core.DomUtils;w=new ops.StepsTranslator(l,gui.SelectionMover.createPositio [...]
++A,500);q.subscribe(ops.OdtDocument.signalStepsInserted,w.handleStepsInserted);q.subscribe(ops.OdtDocument.signalStepsRemoved,w.handleStepsRemoved);q.subscribe(ops.OdtDocument.signalOperationExecuted,function(a){var b=a.spec(),c=b.memberid,b=(new Date(b.timestamp)).toISOString(),d=g.odfContainer();a.isEdit&&(c=m.getMember(c).getProperties().fullName,d.setMetadata({"dc:creator":c,"dc:date":b},null),x||(d.incrementEditingCycles(),d.setMetadata(null,["meta:editing-duration","meta:document-s [...]
++x=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 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.Operation=function(){};ops.Operation.prototype.init=function(g){};ops.Operation.prototype.execute=function(g){};ops.Operation.prototype.spec=function(){};
++// Input 52
++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 c={},d=0;return function(e){var f=e.hash||e.toString();if(c.hasOwnProperty(f))return c[f];c[f]=e=b(e);e.hash=a+d.toString();d+=1;return e}}()}function f(a){return function(){var b={};return function(c){var d,e;if(b.hasOwnProperty(c.localName)){if(e=b[c.localName],d=e[c.namespaceURI],void 0!==d)return d}else b[c.localName]=e={};return e[ [...]
++d=a(c)}}()}function p(a,b,c){return function(){var d={},e=0;return function(f,h){var g=b&&b(f,h),k;if(void 0!==g)return g;k=f.hash||f.toString();g=h.hash||h.toString();if(d.hasOwnProperty(k)){if(k=d[k],k.hasOwnProperty(g))return k[g]}else d[k]=k={};k[g]=g=c(f,h);g.hash=a+e.toString();e+=1;return g}}()}function r(a,b){"choice"===b.p1.type?r(a,b.p1):a[b.p1.hash]=b.p1;"choice"===b.p2.type?r(a,b.p2):a[b.p2.hash]=b.p2}function n(a,b){return{type:"element",nc:a,nullable:!1,textDeriv:function( [...]
++startTagOpenDeriv:function(c){return a.contains(c)?q(b,B):y},attDeriv:function(){return y},startTagCloseDeriv:function(){return this}}}function h(){return{type:"list",nullable:!1,hash:"list",textDeriv:function(){return B}}}function d(a,b,e,f){if(b===y)return y;if(f>=e.length)return b;0===f&&(f=0);for(var h=e.item(f);h.namespaceURI===c;){f+=1;if(f>=e.length)return b;h=e.item(f)}return h=d(a,b.attDeriv(a,e.item(f)),e,f+1)}function m(a,b,c){c.e[0].a?(a.push(c.e[0].text),b.push(c.e[0].a.ns) [...]
++c.e[1].a?(a.push(c.e[1].text),b.push(c.e[1].a.ns)):m(a,b,c.e[1])}var c="http://www.w3.org/2000/xmlns/",e,a,b,q,k,t,A,w,x,v,u,s,H,y={type:"notAllowed",nullable:!1,hash:"notAllowed",nc:void 0,p:void 0,p1:void 0,p2:void 0,textDeriv:function(){return y},startTagOpenDeriv:function(){return y},attDeriv:function(){return y},startTagCloseDeriv:function(){return y},endTagDeriv:function(){return y}},B={type:"empty",nullable:!0,hash:"empty",nc:void 0,p:void 0,p1:void 0,p2:void 0,textDeriv:function [...]
++startTagOpenDeriv:function(){return y},attDeriv:function(){return y},startTagCloseDeriv:function(){return B},endTagDeriv:function(){return y}},L={type:"text",nullable:!0,hash:"text",nc:void 0,p:void 0,p1:void 0,p2:void 0,textDeriv:function(){return L},startTagOpenDeriv:function(){return y},attDeriv:function(){return y},startTagCloseDeriv:function(){return L},endTagDeriv:function(){return y}};e=p("choice",function(a,b){if(a===y)return b;if(b===y||a===b)return a},function(a,b){var c={},d; [...]
++p2:b});b=a=void 0;for(d in c)c.hasOwnProperty(d)&&(void 0===a?a=c[d]:b=void 0===b?c[d]:e(b,c[d]));return function(a,b){return{type:"choice",nullable:a.nullable||b.nullable,hash:void 0,nc:void 0,p:void 0,p1:a,p2:b,textDeriv:function(c,d){return e(a.textDeriv(c,d),b.textDeriv(c,d))},startTagOpenDeriv:f(function(c){return e(a.startTagOpenDeriv(c),b.startTagOpenDeriv(c))}),attDeriv:function(c,d){return e(a.attDeriv(c,d),b.attDeriv(c,d))},startTagCloseDeriv:g(function(){return e(a.startTagCl [...]
++b.startTagCloseDeriv())}),endTagDeriv:g(function(){return e(a.endTagDeriv(),b.endTagDeriv())})}}(a,b)});a=function(a,b,c){return function(){var d={},e=0;return function(f,h){var g=b&&b(f,h),k,m;if(void 0!==g)return g;k=f.hash||f.toString();g=h.hash||h.toString();k<g&&(m=k,k=g,g=m,m=f,f=h,h=m);if(d.hasOwnProperty(k)){if(k=d[k],k.hasOwnProperty(g))return k[g]}else d[k]=k={};k[g]=g=c(f,h);g.hash=a+e.toString();e+=1;return g}}()}("interleave",function(a,b){if(a===y||b===y)return y;if(a===B) [...]
++B)return a},function(b,c){return{type:"interleave",nullable:b.nullable&&c.nullable,hash:void 0,p1:b,p2:c,textDeriv:function(d,f){return e(a(b.textDeriv(d,f),c),a(b,c.textDeriv(d,f)))},startTagOpenDeriv:f(function(d){return e(u(function(b){return a(b,c)},b.startTagOpenDeriv(d)),u(function(c){return a(b,c)},c.startTagOpenDeriv(d)))}),attDeriv:function(d,f){return e(a(b.attDeriv(d,f),c),a(b,c.attDeriv(d,f)))},startTagCloseDeriv:g(function(){return a(b.startTagCloseDeriv(),c.startTagCloseDe [...]
++b=p("group",function(a,b){if(a===y||b===y)return y;if(a===B)return b;if(b===B)return a},function(a,c){return{type:"group",p1:a,p2:c,nullable:a.nullable&&c.nullable,textDeriv:function(d,f){var h=b(a.textDeriv(d,f),c);return a.nullable?e(h,c.textDeriv(d,f)):h},startTagOpenDeriv:function(d){var f=u(function(a){return b(a,c)},a.startTagOpenDeriv(d));return a.nullable?e(f,c.startTagOpenDeriv(d)):f},attDeriv:function(d,f){return e(b(a.attDeriv(d,f),c),b(a,c.attDeriv(d,f)))},startTagCloseDeriv [...]
++c.startTagCloseDeriv())})}});q=p("after",function(a,b){if(a===y||b===y)return y},function(a,b){return{type:"after",p1:a,p2:b,nullable:!1,textDeriv:function(c,d){return q(a.textDeriv(c,d),b)},startTagOpenDeriv:f(function(c){return u(function(a){return q(a,b)},a.startTagOpenDeriv(c))}),attDeriv:function(c,d){return q(a.attDeriv(c,d),b)},startTagCloseDeriv:g(function(){return q(a.startTagCloseDeriv(),b)}),endTagDeriv:g(function(){return a.nullable?b:y})}});k=l("oneormore",function(a){retur [...]
++{type:"oneOrMore",p:a,nullable:a.nullable,textDeriv:function(c,d){return b(a.textDeriv(c,d),e(this,B))},startTagOpenDeriv:function(c){var d=this;return u(function(a){return b(a,e(d,B))},a.startTagOpenDeriv(c))},attDeriv:function(c,d){return b(a.attDeriv(c,d),e(this,B))},startTagCloseDeriv:g(function(){return k(a.startTagCloseDeriv())})}});A=p("attribute",void 0,function(a,b){return{type:"attribute",nullable:!1,hash:void 0,nc:a,p:b,p1:void 0,p2:void 0,textDeriv:void 0,startTagOpenDeriv:v [...]
++d){return a.contains(d)&&(b.nullable&&/^\s+$/.test(d.nodeValue)||b.textDeriv(c,d.nodeValue).nullable)?B:y},startTagCloseDeriv:function(){return y},endTagDeriv:void 0}});t=l("value",function(a){return{type:"value",nullable:!1,value:a,textDeriv:function(b,c){return c===a?B:y},attDeriv:function(){return y},startTagCloseDeriv:function(){return this}}});x=l("data",function(a){return{type:"data",nullable:!1,dataType:a,textDeriv:function(){return B},attDeriv:function(){return y},startTagCloseD [...]
++u=function W(a,b){return"after"===b.type?q(b.p1,a(b.p2)):"choice"===b.type?e(W(a,b.p1),W(a,b.p2)):b};s=function(a,b,c){var f=c.currentNode;b=b.startTagOpenDeriv(f);b=d(a,b,f.attributes,0);var h=b=b.startTagCloseDeriv(),f=c.currentNode;b=c.firstChild();for(var g=[],k;b;)b.nodeType===Node.ELEMENT_NODE?g.push(b):b.nodeType!==Node.TEXT_NODE||/^\s*$/.test(b.nodeValue)||g.push(b.nodeValue),b=c.nextSibling();0===g.length&&(g=[""]);k=h;for(h=0;k!==y&&h<g.length;h+=1)b=g[h],"string"===typeof b?k [...]
++e(k,k.textDeriv(a,b)):k.textDeriv(a,b):(c.currentNode=b,k=s(a,k,c));c.currentNode=f;return b=k.endTagDeriv()};w=function(a){var b,c,d;if("name"===a.name)b=a.text,c=a.a.ns,a={name:b,ns:c,hash:"{"+c+"}"+b,contains:function(a){return a.namespaceURI===c&&a.localName===b}};else if("choice"===a.name){b=[];c=[];m(b,c,a);a="";for(d=0;d<b.length;d+=1)a+="{"+c[d]+"}"+b[d]+",";a={hash:a,contains:function(a){var d;for(d=0;d<b.length;d+=1)if(b[d]===a.localName&&c[d]===a.namespaceURI)return!0;return! [...]
++{hash:"anyName",contains:function(){return!0}};return a};v=function Q(c,d){var f,g;if("elementref"===c.name){f=c.id||0;c=d[f];if(void 0!==c.name){var m=c;f=d[m.id]={hash:"element"+m.id.toString()};m=n(w(m.e[0]),v(m.e[1],d));for(g in m)m.hasOwnProperty(g)&&(f[g]=m[g]);return f}return c}switch(c.name){case "empty":return B;case "notAllowed":return y;case "text":return L;case "choice":return e(Q(c.e[0],d),Q(c.e[1],d));case "interleave":f=Q(c.e[0],d);for(g=1;g<c.e.length;g+=1)f=a(f,Q(c.e[g] [...]
++case "group":return b(Q(c.e[0],d),Q(c.e[1],d));case "oneOrMore":return k(Q(c.e[0],d));case "attribute":return A(w(c.e[0]),Q(c.e[1],d));case "value":return t(c.text);case "data":return f=c.a&&c.a.type,void 0===f&&(f=""),x(f);case "list":return h()}throw"No support for "+c.name;};this.makePattern=function(a,b){var c={},d;for(d in b)b.hasOwnProperty(d)&&(c[d]=b[d]);return d=v(a,c)};this.validate=function(a,b){var c;a.currentNode=a.root;c=s(null,H,a);c.nullable?b(null):(runtime.log("Error i [...]
++c),b(["Error in Relax NG validation: "+c]))};this.init=function(a){H=a}};
 +// 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}};
++xmldom.RelaxNG2=function(){function g(f,d){this.message=function(){d&&(f+=d.nodeType===Node.ELEMENT_NODE?" Element ":" Node ",f+=d.nodeName,d.nodeValue&&(f+=" with value '"+d.nodeValue+"'"),f+=".");return f}}function l(f,d,g,c){return"empty"===f.name?null:r(f,d,g,c)}function f(f,d){if(2!==f.e.length)throw"Element with wrong # of elements: "+f.e.length;for(var m=d.currentNode,c=m?m.nodeType:0,e=null;c>Node.ELEMENT_NODE;){if(c!==Node.COMMENT_NODE&&(c!==Node.TEXT_NODE||!/^\s+$/.test(d.curr [...]
++c+".")];c=(m=d.nextSibling())?m.nodeType:0}if(!m)return[new g("Missing element "+f.names)];if(f.names&&-1===f.names.indexOf(n[m.namespaceURI]+":"+m.localName))return[new g("Found "+m.nodeName+" instead of "+f.names+".",m)];if(d.firstChild()){for(e=l(f.e[1],d,m);d.nextSibling();)if(c=d.currentNode.nodeType,!(d.currentNode&&d.currentNode.nodeType===Node.TEXT_NODE&&/^\s+$/.test(d.currentNode.nodeValue)||c===Node.COMMENT_NODE))return[new g("Spurious content.",d.currentNode)];if(d.parentNode [...]
++l(f.e[1],d,m);d.nextSibling();return e}var p,r,n;r=function(h,d,m,c){var e=h.name,a=null;if("text"===e)a:{for(var b=(h=d.currentNode)?h.nodeType:0;h!==m&&3!==b;){if(1===b){a=[new g("Element not allowed here.",h)];break a}b=(h=d.nextSibling())?h.nodeType:0}d.nextSibling();a=null}else if("data"===e)a=null;else if("value"===e)c!==h.text&&(a=[new g("Wrong value, should be '"+h.text+"', not '"+c+"'",m)]);else if("list"===e)a=null;else if("attribute"===e)a:{if(2!==h.e.length)throw"Attribute w [...]
++h.e.length;e=h.localnames.length;for(a=0;a<e;a+=1){c=m.getAttributeNS(h.namespaces[a],h.localnames[a]);""!==c||m.hasAttributeNS(h.namespaces[a],h.localnames[a])||(c=void 0);if(void 0!==b&&void 0!==c){a=[new g("Attribute defined too often.",m)];break a}b=c}a=void 0===b?[new g("Attribute not found: "+h.names,m)]:l(h.e[1],d,m,b)}else if("element"===e)a=f(h,d);else if("oneOrMore"===e){c=0;do b=d.currentNode,e=r(h.e[0],d,m),c+=1;while(!e&&b!==d.currentNode);1<c?(d.currentNode=b,a=null):a=e}e [...]
++e){if(2!==h.e.length)throw"Choice with wrong # of options: "+h.e.length;b=d.currentNode;if("empty"===h.e[0].name){if(e=r(h.e[1],d,m,c))d.currentNode=b;a=null}else{if(e=l(h.e[0],d,m,c))d.currentNode=b,e=r(h.e[1],d,m,c);a=e}}else if("group"===e){if(2!==h.e.length)throw"Group with wrong # of members: "+h.e.length;a=r(h.e[0],d,m)||r(h.e[1],d,m)}else if("interleave"===e)a:{b=h.e.length;c=[b];for(var q=b,k,n,p,w;0<q;){k=0;n=d.currentNode;for(a=0;a<b;a+=1)p=d.currentNode,!0!==c[a]&&c[a]!==p&&( [...]
++r(w,d,m))?(d.currentNode=p,void 0===c[a]&&(c[a]=!1)):p===d.currentNode||"oneOrMore"===w.name||"choice"===w.name&&("oneOrMore"===w.e[0].name||"oneOrMore"===w.e[1].name)?(k+=1,c[a]=p):(k+=1,c[a]=!0));if(n===d.currentNode&&k===q){a=null;break a}if(0===k){for(a=0;a<b;a+=1)if(!1===c[a]){a=[new g("Interleave does not match.",m)];break a}a=null;break a}for(a=q=0;a<b;a+=1)!0!==c[a]&&(q+=1)}a=null}else throw e+" not allowed in nonEmptyPattern.";return a};this.validate=function(f,d){f.currentNode [...]
++l(p.e[0],f,f.root);d(g)};this.init=function(f,d){p=f;n=d}};
 +// 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()})()};
++gui.Caret=function(g,l,f){function p(c){e&&m.parentNode&&(!a||c)&&(c&&void 0!==b&&runtime.clearTimeout(b),a=!0,h.style.opacity=c||"0"===h.style.opacity?"1":"0",b=runtime.setTimeout(function(){a=!1;p(!1)},500))}function r(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 b=g.getNode(),d,e=null;b.previousSibling&&(d=b.previousSibling.nodeType===Node.TEXT_NODE?b.pr [...]
++b.previousSibling.childNodes.length,a.setStart(b.previousSibling,0<d?d-1:0),a.setEnd(b.previousSibling,d),(d=a.getBoundingClientRect())&&d.height&&(e=d));b.nextSibling&&(a.setStart(b.nextSibling,0),a.setEnd(b.nextSibling,0<(b.nextSibling.nodeType===Node.TEXT_NODE?b.nextSibling.textContent.length:b.nextSibling.childNodes.length)?1:0),(d=a.getBoundingClientRect())&&d.height&&(!e||r(b,d)>r(b,e))&&(e=d));a=e;b=g.getOdtDocument().getOdfCanvas().getZoomLevel();c&&g.getSelectionType()===ops.Od [...]
++h.style.visibility="visible":h.style.visibility="hidden";a?(h.style.top="0",e=q.getBoundingClientRect(h),8>a.height&&(a={top:a.top-(8-a.height)/2,height:8}),h.style.height=q.adaptRangeDifferenceToZoomLevel(a.height,b)+"px",h.style.top=q.adaptRangeDifferenceToZoomLevel(a.top-e.top,b)+"px"):(h.style.height="1em",h.style.top="5%")}var h,d,m,c=!0,e=!1,a=!1,b,q=new core.DomUtils;this.handleUpdate=n;this.refreshCursorBlinking=function(){f||g.getSelectedRange().collapsed?(e=!0,p(!0)):(e=!1,h.s [...]
++"0")};this.setFocus=function(){e=!0;d.markAsFocussed(!0);p(!0)};this.removeFocus=function(){e=!1;d.markAsFocussed(!1);h.style.opacity="1"};this.show=function(){c=!0;n();d.markAsFocussed(!0)};this.hide=function(){c=!1;n();d.markAsFocussed(!1)};this.setAvatarImageUrl=function(a){d.setImageUrl(a)};this.setColor=function(a){h.style.borderColor=a;d.setColor(a)};this.getCursor=function(){return g};this.getFocusElement=function(){return h};this.toggleHandleVisibility=function(){d.isVisible()?d [...]
++this.showHandle=function(){d.show()};this.hideHandle=function(){d.hide()};this.ensureVisible=function(){var a,b,c,d,e=g.getOdtDocument().getOdfCanvas().getElement().parentNode,f;c=e.offsetWidth-e.clientWidth+5;d=e.offsetHeight-e.clientHeight+5;f=h.getBoundingClientRect();a=f.left-c;b=f.top-d;c=f.right+c;d=f.bottom+d;f=e.getBoundingClientRect();b<f.top?e.scrollTop-=f.top-b:d>f.bottom&&(e.scrollTop+=d-f.bottom);a<f.left?e.scrollLeft-=f.left-a:c>f.right&&(e.scrollLeft+=c-f.right);n()};this [...]
++a(b):(m.removeChild(h),a())})};(function(){var a=g.getOdtDocument().getDOM();h=a.createElementNS(a.documentElement.namespaceURI,"span");h.style.top="5%";m=g.getNode();m.appendChild(h);d=new gui.Avatar(m,l);n()})()};
++// Input 55
++gui.EventManager=function(g){function l(){return g.getOdfCanvas().getElement()}function f(){var c=this,a=[];this.handlers=[];this.isSubscribed=!1;this.handleEvent=function(b){-1===a.indexOf(b)&&(a.push(b),c.handlers.forEach(function(a){a(b)}),runtime.setTimeout(function(){a.splice(a.indexOf(b),1)},0))}}function p(c){var a=c.scrollX,b=c.scrollY;this.restore=function(){c.scrollX===a&&c.scrollY===b||c.scrollTo(a,b)}}function r(c){var a=c.scrollTop,b=c.scrollLeft;this.restore=function(){if( [...]
++a||c.scrollLeft!==b)c.scrollTop=a,c.scrollLeft=b}}function n(c,a,b){var f="on"+a,h=!1;c.attachEvent&&(h=c.attachEvent(f,b));!h&&c.addEventListener&&(c.addEventListener(a,b,!1),h=!0);h&&!d[a]||!c.hasOwnProperty(f)||(c[f]=b)}var h=runtime.getWindow(),d={beforecut:!0,beforepaste:!0},m,c;this.subscribe=function(d,a){var b=m[d],f=l();b?(b.handlers.push(a),b.isSubscribed||(b.isSubscribed=!0,n(h,d,b.handleEvent),n(f,d,b.handleEvent),n(c,d,b.handleEvent))):n(f,d,a)};this.unsubscribe=function(c, [...]
++d=b&&b.handlers.indexOf(a),f=l();b?-1!==d&&b.handlers.splice(d,1):(b="on"+c,f.detachEvent&&f.detachEvent(b,a),f.removeEventListener&&f.removeEventListener(c,a,!1),f[b]===a&&(f[b]=null))};this.focus=function(){var d,a=l(),b=h.getSelection();if(g.getDOM().activeElement!==l()){for(d=a;d&&!d.scrollTop&&!d.scrollLeft;)d=d.parentNode;d=d?new r(d):new p(h);a.focus();d&&d.restore()}b&&b.extend&&(c.parentNode!==a&&a.appendChild(c),b.collapse(c.firstChild,0),b.extend(c,c.childNodes.length))};(fun [...]
++l(),a=d.ownerDocument;runtime.assert(Boolean(h),"EventManager requires a window object to operate correctly");m={mousedown:new f,mouseup:new f,focus:new f};c=a.createElement("div");c.id="eventTrap";c.setAttribute("contenteditable","true");c.style.position="absolute";c.style.left="-10000px";c.appendChild(a.createTextNode("dummy content"));d.appendChild(c)})()};
 +// 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 [...]
++runtime.loadClass("gui.SelectionMover");gui.ShadowCursor=function(g){var l=g.getDOM().createRange(),f=!0;this.removeFromOdtDocument=function(){};this.getMemberId=function(){return gui.ShadowCursor.ShadowCursorMemberId};this.getSelectedRange=function(){return l};this.setSelectedRange=function(g,r){l=g;f=!1!==r};this.hasForwardSelection=function(){return f};this.getOdtDocument=function(){return g};this.getSelectionType=function(){return ops.OdtCursor.RangeSelection};l.setStart(g.getRootNo [...]
 +gui.ShadowCursor.ShadowCursorMemberId="";(function(){return gui.ShadowCursor})();
- // Input 58
++// Input 57
 +/*
 +
 + 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(){};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=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 59
++// Input 58
 +/*
 +
 + 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(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
++gui.UndoStateRules=function(){function g(f){return f.spec().optype}function l(f){return f.isEdit}this.getOpType=g;this.isEditOperation=l;this.isPartOfOperationSet=function(f,p){if(f.isEdit){if(0===p.length)return!0;var r;if(r=p[p.length-1].isEdit)a:{r=p.filter(l);var n=g(f),h;b:switch(n){case "RemoveText":case "InsertText":h=!0;break b;default:h=!1}if(h&&n===g(r[0])){if(1===r.length){r=!0;break a}n=r[r.length-2].spec().position;r=r[r.length-1].spec().position;h=f.spec().position;if(r=== [...]
++!0;break a}}r=!1}return r}return!0}};
++// Input 59
 +/*
 +
 + 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.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
++ops.EditInfo=function(g,l){function f(){var f=[],h;for(h in r)r.hasOwnProperty(h)&&f.push({memberid:h,time:r[h].time});f.sort(function(d,f){return d.time-f.time});return f}var p,r={};this.getNode=function(){return p};this.getOdtDocument=function(){return l};this.getEdits=function(){return r};this.getSortedEdits=function(){return f()};this.addEdit=function(f,h){r[f]={time:h}};this.clearEdits=function(){r={}};this.destroy=function(f){g.parentNode&&g.removeChild(p);f()};p=l.getDOM().create [...]
++"editinfo");g.insertBefore(p,g.firstChild)};
++// Input 60
 +/*
 +
 + 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(){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
++ops.OpAddAnnotation=function(){function g(d,f,c){var e=d.getTextNodeAtStep(c,l);e&&(d=e.textNode,c=d.parentNode,e.offset!==d.length&&d.splitText(e.offset),c.insertBefore(f,d.nextSibling),0===d.length&&c.removeChild(d))}var l,f,p,r,n,h;this.init=function(d){l=d.memberid;f=parseInt(d.timestamp,10);p=parseInt(d.position,10);r=parseInt(d.length,10)||0;n=d.name};this.isEdit=!0;this.execute=function(d){var m={},c=d.getCursor(l),e,a;a=new core.DomUtils;h=d.getDOM();var b=new Date(f),q,k,t,A;e= [...]
++"office:annotation");e.setAttributeNS(odf.Namespaces.officens,"office:name",n);q=h.createElementNS(odf.Namespaces.dcns,"dc:creator");q.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",l);q.textContent=d.getMember(l).getProperties().fullName;k=h.createElementNS(odf.Namespaces.dcns,"dc:date");k.appendChild(h.createTextNode(b.toISOString()));b=h.createElementNS(odf.Namespaces.textns,"text:list");t=h.createElementNS(odf.Namespaces.textns,"text:list-item");A=h.createElementNS(o [...]
++"text:p");t.appendChild(A);b.appendChild(t);e.appendChild(q);e.appendChild(k);e.appendChild(b);m.node=e;if(!m.node)return!1;if(r){e=h.createElementNS(odf.Namespaces.officens,"office:annotation-end");e.setAttributeNS(odf.Namespaces.officens,"office:name",n);m.end=e;if(!m.end)return!1;g(d,m.end,p+r)}g(d,m.node,p);d.emit(ops.OdtDocument.signalStepsInserted,{position:p,length:r});c&&(e=h.createRange(),a=a.getElementsByTagNameNS(m.node,odf.Namespaces.textns,"p")[0],e.selectNodeContents(a),c. [...]
++d.emit(ops.OdtDocument.signalCursorMoved,c));d.getOdfCanvas().addAnnotation(m);d.fixCursorPositions();return!0};this.spec=function(){return{optype:"AddAnnotation",memberid:l,timestamp:f,position:p,length:r,name:n}}};
++// 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.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
++ops.OpAddCursor=function(){var g,l;this.init=function(f){g=f.memberid;l=f.timestamp};this.isEdit=!1;this.execute=function(f){var l=f.getCursor(g);if(l)return!1;l=new ops.OdtCursor(g,f);f.addCursor(l);f.emit(ops.OdtDocument.signalCursorAdded,l);return!0};this.spec=function(){return{optype:"AddCursor",memberid:g,timestamp:l}}};
++// 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,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
++runtime.loadClass("ops.Member");ops.OpAddMember=function(){var g,l,f;this.init=function(p){g=p.memberid;l=parseInt(p.timestamp,10);f=p.setProperties};this.isEdit=!1;this.execute=function(l){if(l.getMember(g))return!1;var r=new ops.Member(g,f);l.addMember(r);l.emit(ops.OdtDocument.signalMemberAdded,r);return!0};this.spec=function(){return{optype:"AddMember",memberid:g,timestamp:l,setProperties:f}}};
++// Input 63
 +/*
 +
 + 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,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
++ops.OpAddStyle=function(){var g,l,f,p,r,n,h=odf.Namespaces.stylens;this.init=function(d){g=d.memberid;l=d.timestamp;f=d.styleName;p=d.styleFamily;r="true"===d.isAutomaticStyle||!0===d.isAutomaticStyle;n=d.setProperties};this.isEdit=!0;this.execute=function(d){var g=d.getOdfCanvas().odfContainer(),c=d.getFormatting(),e=d.getDOM().createElementNS(h,"style:style");if(!e)return!1;n&&c.updateStyle(e,n);e.setAttributeNS(h,"style:family",p);e.setAttributeNS(h,"style:name",f);r?g.rootElement.au [...]
++g.rootElement.styles.appendChild(e);d.getOdfCanvas().refreshCSS();r||d.emit(ops.OdtDocument.signalCommonStyleCreated,{name:f,family:p});return!0};this.spec=function(){return{optype:"AddStyle",memberid:g,timestamp:l,styleName:f,styleFamily:p,isAutomaticStyle:r,setProperties:n}}};
++// 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("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
++runtime.loadClass("core.DomUtils");runtime.loadClass("odf.OdfUtils");runtime.loadClass("odf.TextStyleApplicator");
++ops.OpApplyDirectStyling=function(){function g(f,c,e){var a=f.getOdfCanvas().odfContainer(),b=d.splitBoundaries(c),g=h.getTextNodes(c,!1);c={startContainer:c.startContainer,startOffset:c.startOffset,endContainer:c.endContainer,endOffset:c.endOffset};(new odf.TextStyleApplicator(new odf.ObjectNameGenerator(a,l),f.getFormatting(),a.rootElement.automaticStyles)).applyStyle(g,c,e);b.forEach(d.normalizeTextNodes)}var l,f,p,r,n,h=new odf.OdfUtils,d=new core.DomUtils;this.init=function(d){l=d. [...]
++d.timestamp;p=parseInt(d.position,10);r=parseInt(d.length,10);n=d.setProperties};this.isEdit=!0;this.execute=function(d){var c=d.convertCursorToDomRange(p,r),e=h.getImpactedParagraphs(c);g(d,c,n);c.detach();d.getOdfCanvas().refreshCSS();d.fixCursorPositions();e.forEach(function(a){d.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:a,memberId:l,timeStamp:f})});d.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"ApplyDirectStyling",memberid:l, [...]
++position:p,length:r,setProperties:n}}};
++// 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.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
++ops.OpInsertImage=function(){var g,l,f,p,r,n,h,d,m=odf.Namespaces.drawns,c=odf.Namespaces.svgns,e=odf.Namespaces.textns,a=odf.Namespaces.xlinkns;this.init=function(a){g=a.memberid;l=a.timestamp;f=a.position;p=a.filename;r=a.frameWidth;n=a.frameHeight;h=a.frameStyleName;d=a.frameName};this.isEdit=!0;this.execute=function(b){var q=b.getOdfCanvas(),k=b.getTextNodeAtStep(f,g),t,A;if(!k)return!1;t=k.textNode;A=b.getParagraphElement(t);var k=k.offset!==t.length?t.splitText(k.offset):t.nextSib [...]
++x=w.createElementNS(m,"draw:image"),w=w.createElementNS(m,"draw:frame");x.setAttributeNS(a,"xlink:href",p);x.setAttributeNS(a,"xlink:type","simple");x.setAttributeNS(a,"xlink:show","embed");x.setAttributeNS(a,"xlink:actuate","onLoad");w.setAttributeNS(m,"draw:style-name",h);w.setAttributeNS(m,"draw:name",d);w.setAttributeNS(e,"text:anchor-type","as-char");w.setAttributeNS(c,"svg:width",r);w.setAttributeNS(c,"svg:height",n);w.appendChild(x);t.parentNode.insertBefore(w,k);b.emit(ops.OdtDo [...]
++{position:f,length:1});0===t.length&&t.parentNode.removeChild(t);q.addCssForFrameWithImage(w);q.refreshCSS();b.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:A,memberId:g,timeStamp:l});q.rerenderAnnotations();return!0};this.spec=function(){return{optype:"InsertImage",memberid:g,timestamp:l,filename:p,position:f,frameWidth:r,frameHeight:n,frameStyleName:h,frameName:d}}};
++// Input 66
 +/*
 +
 + 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(){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
++ops.OpInsertTable=function(){function g(d,a){var b;if(1===c.length)b=c[0];else if(3===c.length)switch(d){case 0:b=c[0];break;case p-1:b=c[2];break;default:b=c[1]}else b=c[d];if(1===b.length)return b[0];if(3===b.length)switch(a){case 0:return b[0];case r-1:return b[2];default:return b[1]}return b[a]}var l,f,p,r,n,h,d,m,c;this.init=function(e){l=e.memberid;f=e.timestamp;n=e.position;p=e.initialRows;r=e.initialColumns;h=e.tableName;d=e.tableStyleName;m=e.tableColumnStyleName;c=e.tableCellS [...]
++this.isEdit=!0;this.execute=function(c){var a=c.getTextNodeAtStep(n),b=c.getRootNode();if(a){var q=c.getDOM(),k=q.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table"),t=q.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table-column"),A,w,x,v;d&&k.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:style-name",d);h&&k.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:name",h);t.setAttributeNS(" [...]
++"table:number-columns-repeated",r);m&&t.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:style-name",m);k.appendChild(t);for(x=0;x<p;x+=1){t=q.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table-row");for(v=0;v<r;v+=1)A=q.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table-cell"),(w=g(x,v))&&A.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:style-name",w),w=q.createElementNS("urn:oasis:n [...]
++"text:p"),A.appendChild(w),t.appendChild(A);k.appendChild(t)}a=c.getParagraphElement(a.textNode);b.insertBefore(k,a.nextSibling);c.emit(ops.OdtDocument.signalStepsInserted,{position:n,length:r*p+1});c.getOdfCanvas().refreshSize();c.emit(ops.OdtDocument.signalTableAdded,{tableElement:k,memberId:l,timeStamp:f});c.getOdfCanvas().rerenderAnnotations();return!0}return!1};this.spec=function(){return{optype:"InsertTable",memberid:l,timestamp:f,position:n,initialRows:p,initialColumns:r,tableNam [...]
++tableColumnStyleName:m,tableCellStyleMatrix:c}}};
++// Input 67
 +/*
 +
 + 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(){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
++ops.OpInsertText=function(){var g,l,f,p,r;this.init=function(n){g=n.memberid;l=n.timestamp;f=n.position;p=n.text;r="true"===n.moveCursor||!0===n.moveCursor};this.isEdit=!0;this.execute=function(n){var h,d,m,c=null,e=n.getDOM(),a,b=0,q,k=n.getCursor(g),t;n.upgradeWhitespacesAtPosition(f);if(h=n.getTextNodeAtStep(f)){d=h.textNode;c=d.nextSibling;m=d.parentNode;a=n.getParagraphElement(d);for(t=0;t<p.length;t+=1)if(" "===p[t]&&(0===t||t===p.length-1||" "===p[t-1])||"\t"===p[t])0===b?(h.offs [...]
++(c=d.splitText(h.offset)),0<t&&d.appendData(p.substring(0,t))):b<t&&(b=p.substring(b,t),m.insertBefore(e.createTextNode(b),c)),b=t+1,q=" "===p[t]?"text:s":"text:tab",q=e.createElementNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0",q),q.appendChild(e.createTextNode(p[t])),m.insertBefore(q,c);0===b?d.insertData(h.offset,p):b<p.length&&(h=p.substring(b),m.insertBefore(e.createTextNode(h),c));m=d.parentNode;c=d.nextSibling;m.removeChild(d);m.insertBefore(d,c);0===d.length&&d.parentNode. [...]
++n.emit(ops.OdtDocument.signalStepsInserted,{position:f,length:p.length});k&&r&&(n.moveCursor(g,f+p.length,0),n.emit(ops.OdtDocument.signalCursorMoved,k));0<f&&(1<f&&n.downgradeWhitespacesAtPosition(f-2),n.downgradeWhitespacesAtPosition(f-1));n.downgradeWhitespacesAtPosition(f);n.downgradeWhitespacesAtPosition(f+p.length-1);n.downgradeWhitespacesAtPosition(f+p.length);n.getOdfCanvas().refreshSize();n.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:a,memberId:g,timeStamp:l}) [...]
++return!0}return!1};this.spec=function(){return{optype:"InsertText",memberid:g,timestamp:l,position:f,text:p,moveCursor:r}}};
++// Input 68
 +/*
 +
 + 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,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
++ops.OpMoveCursor=function(){var g,l,f,p,r;this.init=function(n){g=n.memberid;l=n.timestamp;f=n.position;p=n.length||0;r=n.selectionType||ops.OdtCursor.RangeSelection};this.isEdit=!1;this.execute=function(l){var h=l.getCursor(g),d;if(!h)return!1;d=l.convertCursorToDomRange(f,p);h.setSelectedRange(d,0<=p);h.setSelectionType(r);l.emit(ops.OdtDocument.signalCursorMoved,h);return!0};this.spec=function(){return{optype:"MoveCursor",memberid:g,timestamp:l,position:f,length:p,selectionType:r}}};
++// 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("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
++ops.OpRemoveAnnotation=function(){var g,l,f,p,r;this.init=function(n){g=n.memberid;l=n.timestamp;f=parseInt(n.position,10);p=parseInt(n.length,10);r=new core.DomUtils};this.isEdit=!0;this.execute=function(g){for(var h=g.getIteratorAtPosition(f).container(),d,l,c;h.namespaceURI!==odf.Namespaces.officens||"annotation"!==h.localName;)h=h.parentNode;if(null===h)return!1;(d=h.getAttributeNS(odf.Namespaces.officens,"name"))&&(l=r.getElementsByTagNameNS(g.getRootNode(),odf.Namespaces.officens, [...]
++c.getAttributeNS(odf.Namespaces.officens,"name")})[0]||null);g.getOdfCanvas().forgetAnnotations();for(c=r.getElementsByTagNameNS(h,"urn:webodf:names:cursor","cursor");c.length;)h.parentNode.insertBefore(c.pop(),h);h.parentNode.removeChild(h);l&&l.parentNode.removeChild(l);g.emit(ops.OdtDocument.signalStepsRemoved,{position:0<f?f-1:f,length:p});g.fixCursorPositions();g.getOdfCanvas().refreshAnnotations();return!0};this.spec=function(){return{optype:"RemoveAnnotation",memberid:g,timestamp [...]
++length:p}}};
++// 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/
 +*/
- 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
++ops.OpRemoveBlob=function(){var g,l,f;this.init=function(p){g=p.memberid;l=p.timestamp;f=p.filename};this.isEdit=!0;this.execute=function(g){g.getOdfCanvas().odfContainer().removeBlob(f);return!0};this.spec=function(){return{optype:"RemoveBlob",memberid:g,timestamp:l,filename:f}}};
++// 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/
 +*/
- 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
++ops.OpRemoveCursor=function(){var g,l;this.init=function(f){g=f.memberid;l=f.timestamp};this.isEdit=!1;this.execute=function(f){return f.removeCursor(g)?!0:!1};this.spec=function(){return{optype:"RemoveCursor",memberid:g,timestamp:l}}};
++// Input 72
 +/*
 +
 + 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(){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
++runtime.loadClass("ops.Member");ops.OpRemoveMember=function(){var g,l;this.init=function(f){g=f.memberid;l=parseInt(f.timestamp,10)};this.isEdit=!1;this.execute=function(f){if(!f.getMember(g))return!1;f.removeMember(g);f.emit(ops.OdtDocument.signalMemberRemoved,g);return!0};this.spec=function(){return{optype:"RemoveMember",memberid:g,timestamp:l}}};
++// Input 73
 +/*
 +
 + 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,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
++ops.OpRemoveStyle=function(){var g,l,f,p;this.init=function(r){g=r.memberid;l=r.timestamp;f=r.styleName;p=r.styleFamily};this.isEdit=!0;this.execute=function(g){var l=g.getStyleElement(f,p);if(!l)return!1;l.parentNode.removeChild(l);g.getOdfCanvas().refreshCSS();g.emit(ops.OdtDocument.signalCommonStyleDeleted,{name:f,family:p});return!0};this.spec=function(){return{optype:"RemoveStyle",memberid:g,timestamp:l,styleName:f,styleFamily:p}}};
++// Input 74
 +/*
 +
 + 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(){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
++ops.OpRemoveText=function(){function g(f){function c(a){return d.hasOwnProperty(a.namespaceURI)||"br"===a.localName&&n.isLineBreak(a.parentNode)||a.nodeType===Node.TEXT_NODE&&d.hasOwnProperty(a.parentNode.namespaceURI)}function e(a){if(n.isCharacterElement(a))return!1;if(a.nodeType===Node.TEXT_NODE)return 0===a.textContent.length;for(a=a.firstChild;a;){if(d.hasOwnProperty(a.namespaceURI)||!e(a))return!1;a=a.nextSibling}return!0}function a(b){var d;b.nodeType===Node.TEXT_NODE?(d=b.parent [...]
++d=h.removeUnwantedNodes(b,c);return!n.isParagraph(d)&&d!==f&&e(d)?a(d):d}this.isEmpty=e;this.mergeChildrenIntoParent=a}var l,f,p,r,n,h,d={};this.init=function(g){runtime.assert(0<=g.length,"OpRemoveText only supports positive lengths");l=g.memberid;f=g.timestamp;p=parseInt(g.position,10);r=parseInt(g.length,10);n=new odf.OdfUtils;h=new core.DomUtils;d[odf.Namespaces.dbns]=!0;d[odf.Namespaces.dcns]=!0;d[odf.Namespaces.dr3dns]=!0;d[odf.Namespaces.drawns]=!0;d[odf.Namespaces.chartns]=!0;d[ [...]
++!0;d[odf.Namespaces.numberns]=!0;d[odf.Namespaces.officens]=!0;d[odf.Namespaces.presentationns]=!0;d[odf.Namespaces.stylens]=!0;d[odf.Namespaces.svgns]=!0;d[odf.Namespaces.tablens]=!0;d[odf.Namespaces.textns]=!0};this.isEdit=!0;this.execute=function(d){var c,e,a,b,q=d.getCursor(l),k=new g(d.getRootNode());d.upgradeWhitespacesAtPosition(p);d.upgradeWhitespacesAtPosition(p+r);e=d.convertCursorToDomRange(p,r);h.splitBoundaries(e);c=d.getParagraphElement(e.startContainer);a=n.getTextElement [...]
++b=n.getParagraphElements(e);e.detach();a.forEach(function(a){k.mergeChildrenIntoParent(a)});e=b.reduce(function(a,b){var c,d=!1,e=a,f=b,h,g=null;k.isEmpty(a)&&(d=!0,b.parentNode!==a.parentNode&&(h=b.parentNode,a.parentNode.insertBefore(b,a.nextSibling)),f=a,e=b,g=e.getElementsByTagNameNS("urn:webodf:names:editinfo","editinfo")[0]||e.firstChild);for(;f.hasChildNodes();)c=d?f.lastChild:f.firstChild,f.removeChild(c),"editinfo"!==c.localName&&e.insertBefore(c,g);h&&k.isEmpty(h)&&k.mergeChil [...]
++k.mergeChildrenIntoParent(f);return e});d.emit(ops.OdtDocument.signalStepsRemoved,{position:p,length:r});d.downgradeWhitespacesAtPosition(p);d.fixCursorPositions();d.getOdfCanvas().refreshSize();d.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:e||c,memberId:l,timeStamp:f});q&&(q.resetSelectionType(),d.emit(ops.OdtDocument.signalCursorMoved,q));d.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"RemoveText",memberid:l,timestamp:f,position:p [...]
++// Input 75
 +/*
 +
 + 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,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
++ops.OpSetBlob=function(){var g,l,f,p,r;this.init=function(n){g=n.memberid;l=n.timestamp;f=n.filename;p=n.mimetype;r=n.content};this.isEdit=!0;this.execute=function(g){g.getOdfCanvas().odfContainer().setBlob(f,p,r);return!0};this.spec=function(){return{optype:"SetBlob",memberid:g,timestamp:l,filename:f,mimetype:p,content:r}}};
++// Input 76
 +/*
 +
 + 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,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
++ops.OpSetParagraphStyle=function(){var g,l,f,p;this.init=function(r){g=r.memberid;l=r.timestamp;f=r.position;p=r.styleName};this.isEdit=!0;this.execute=function(r){var n;n=r.getIteratorAtPosition(f);return(n=r.getParagraphElement(n.container()))?(""!==p?n.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0","text:style-name",p):n.removeAttributeNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0","style-name"),r.getOdfCanvas().refreshSize(),r.emit(ops.OdtDocument.signalParagra [...]
++{paragraphElement:n,timeStamp:l,memberId:g}),r.getOdfCanvas().rerenderAnnotations(),!0):!1};this.spec=function(){return{optype:"SetParagraphStyle",memberid:g,timestamp:l,position:f,styleName:p}}};
++// Input 77
 +/*
 +
 + 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(){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
++ops.OpSplitParagraph=function(){var g,l,f,p,r;this.init=function(n){g=n.memberid;l=n.timestamp;f=n.position;p="true"===n.moveCursor||!0===n.moveCursor;r=new odf.OdfUtils};this.isEdit=!0;this.execute=function(n){var h,d,m,c,e,a,b,q=n.getCursor(g);n.upgradeWhitespacesAtPosition(f);h=n.getTextNodeAtStep(f);if(!h)return!1;d=n.getParagraphElement(h.textNode);if(!d)return!1;m=r.isListItem(d.parentNode)?d.parentNode:d;0===h.offset?(b=h.textNode.previousSibling,a=null):(b=h.textNode,a=h.offset> [...]
++null:h.textNode.splitText(h.offset));for(c=h.textNode;c!==m;){c=c.parentNode;e=c.cloneNode(!1);a&&e.appendChild(a);if(b)for(;b&&b.nextSibling;)e.appendChild(b.nextSibling);else for(;c.firstChild;)e.appendChild(c.firstChild);c.parentNode.insertBefore(e,c.nextSibling);b=c;a=e}r.isListItem(a)&&(a=a.childNodes[0]);0===h.textNode.length&&h.textNode.parentNode.removeChild(h.textNode);n.emit(ops.OdtDocument.signalStepsInserted,{position:f,length:1});q&&p&&(n.moveCursor(g,f+1,0),n.emit(ops.OdtD [...]
++q));n.fixCursorPositions();n.getOdfCanvas().refreshSize();n.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:d,memberId:g,timeStamp:l});n.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:a,memberId:g,timeStamp:l});n.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"SplitParagraph",memberid:g,timestamp:l,position:f,moveCursor:p}}};
++// Input 78
 +/*
 +
 + 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
++ops.OpUpdateMember=function(){function g(){var f="//dc:creator[@editinfo:memberid='"+l+"']",f=xmldom.XPath.getODFElementsWithXPath(n.getRootNode(),f,function(d){return"editinfo"===d?"urn:webodf:names:editinfo":odf.Namespaces.lookupNamespaceURI(d)}),d;for(d=0;d<f.length;d+=1)f[d].textContent=p.fullName}var l,f,p,r,n;this.init=function(h){l=h.memberid;f=parseInt(h.timestamp,10);p=h.setProperties;r=h.removedProperties};this.isEdit=!1;this.execute=function(f){n=f;var d=f.getMember(l);if(!d) [...]
++d.removeProperties(r);p&&(d.setProperties(p),p.fullName&&g());f.emit(ops.OdtDocument.signalMemberUpdated,d);return!0};this.spec=function(){return{optype:"UpdateMember",memberid:l,timestamp:f,setProperties:p,removedProperties:r}}};
++// 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/
 +*/
- 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
++ops.OpUpdateMetadata=function(){var g,l,f,p;this.init=function(r){g=r.memberid;l=parseInt(r.timestamp,10);f=r.setProperties;p=r.removedProperties};this.isEdit=!0;this.execute=function(g){g=g.getOdfCanvas().odfContainer();var l=[],h=["dc:date","dc:creator","meta:editing-cycles"];f&&h.forEach(function(d){if(f[d])return!1});p&&(h.forEach(function(d){if(-1!==l.indexOf(d))return!1}),l=p.attributes.split(","));g.setMetadata(f,l);return!0};this.spec=function(){return{optype:"UpdateMetadata",me [...]
++setProperties:f,removedProperties:p}}};
++// Input 80
 +/*
 +
 + 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,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
++ops.OpUpdateParagraphStyle=function(){function g(d,f){var c,e,a=f?f.split(","):[];for(c=0;c<a.length;c+=1)e=a[c].split(":"),d.removeAttributeNS(odf.Namespaces.lookupNamespaceURI(e[0]),e[1])}var l,f,p,r,n,h=odf.Namespaces.stylens;this.init=function(d){l=d.memberid;f=d.timestamp;p=d.styleName;r=d.setProperties;n=d.removedProperties};this.isEdit=!0;this.execute=function(d){var f=d.getFormatting(),c,e,a;return(c=""!==p?d.getParagraphStyleElement(p):f.getDefaultStyleElement("paragraph"))?(e= [...]
++"paragraph-properties")[0],a=c.getElementsByTagNameNS(h,"text-properties")[0],r&&f.updateStyle(c,r),n&&(n["style:paragraph-properties"]&&(g(e,n["style:paragraph-properties"].attributes),0===e.attributes.length&&c.removeChild(e)),n["style:text-properties"]&&(g(a,n["style:text-properties"].attributes),0===a.attributes.length&&c.removeChild(a)),g(c,n.attributes)),d.getOdfCanvas().refreshCSS(),d.emit(ops.OdtDocument.signalParagraphStyleModified,p),d.getOdfCanvas().rerenderAnnotations(),!0): [...]
++function(){return{optype:"UpdateParagraphStyle",memberid:l,timestamp:f,styleName:p,setProperties:r,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("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 [...]
++ops.OperationFactory=function(){function g(f){return function(){return new f}}var l;this.register=function(f,g){l[f]=g};this.create=function(f){var g=null,r=l[f.optype];r&&(g=r(f),g.init(f));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 83
++// Input 82
 +/*
 +
 + 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(){};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
++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,l){};ops.OperationRouter.prototype.unsubscribe=function(g,l){};ops.OperationRouter.prototype.hasLocalUnsyncedOps=function(){};ops.OperationRouter.prototype.hasSessionHostConnection [...]
++// Input 83
 +/*
 +
 + 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
++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 f(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 p(a,b){a&&["style:parent-style-name","style:next-style-name"].forEach(function(c){a[c]===b&&delete a[c]})}function r(a){var b={};Object.keys(a).forEach(function(c){b[c]="object"===typeof a[c]?r(a[c]):a[c]});return b [...]
++b,c,d){var e,f,h=!1,g=!1,l,m,n=d&&d.attributes?d.attributes.split(","):[];a&&(c||0<n.length)&&Object.keys(a).forEach(function(b){e=a[b];"object"!==typeof e&&(l=c&&c[b],void 0!==l?(delete a[b],g=!0,l===e&&(delete c[b],h=!0)):n&&-1!==n.indexOf(b)&&(delete a[b],g=!0))});if(b&&b.attributes&&(c||0<n.length)){m=b.attributes.split(",");for(d=0;d<m.length;d+=1)if(f=m[d],c&&void 0!==c[f]||n&&-1!==n.indexOf(f))m.splice(d,1),d-=1,g=!0;0<m.length?b.attributes=m.join(","):delete b.attributes}return{ [...]
++minorChanged:g}}function h(a){for(var b in a)if(a.hasOwnProperty(b))return!0;return!1}function d(a){for(var b in a)if(a.hasOwnProperty(b)&&("attributes"!==b||0<a.attributes.length))return!0;return!1}function m(a,b,c){var e=a.setProperties?a.setProperties[c]:null,f=a.removedProperties?a.removedProperties[c]:null,g=b.setProperties?b.setProperties[c]:null,l=b.removedProperties?b.removedProperties[c]:null,m;m=n(e,f,g,l);e&&!h(e)&&delete a.setProperties[c];f&&!d(f)&&delete a.removedPropertie [...]
++delete b.setProperties[c];l&&!d(l)&&delete b.removedProperties[c];return m}function c(a,b){return{opSpecsA:[a],opSpecsB:[b]}}var e={AddCursor:{AddCursor:c,AddMember:c,AddStyle:c,ApplyDirectStyling:c,InsertText:c,MoveCursor:c,RemoveCursor:c,RemoveMember:c,RemoveStyle:c,RemoveText:c,SetParagraphStyle:c,SplitParagraph:c,UpdateMember:c,UpdateMetadata:c,UpdateParagraphStyle:c},AddMember:{AddStyle:c,InsertText:c,MoveCursor:c,RemoveCursor:c,RemoveStyle:c,RemoveText:c,SetParagraphStyle:c,SplitP [...]
++UpdateMetadata:c,UpdateParagraphStyle:c},AddStyle:{AddStyle:c,ApplyDirectStyling:c,InsertText:c,MoveCursor:c,RemoveCursor:c,RemoveMember:c,RemoveStyle:function(a,b){var c,d=[a],e=[b];a.styleFamily===b.styleFamily&&(c=f(a.setProperties,b.styleName),0<c.length&&(c={optype:"UpdateParagraphStyle",memberid:b.memberid,timestamp:b.timestamp,styleName:a.styleName,removedProperties:{attributes:c.join(",")}},e.unshift(c)),p(a.setProperties,b.styleName));return{opSpecsA:d,opSpecsB:e}},RemoveText:c [...]
++SplitParagraph:c,UpdateMember:c,UpdateMetadata:c,UpdateParagraphStyle:c},ApplyDirectStyling:{ApplyDirectStyling:function(a,b,c){var d,e,f,g,l,n,p,s;g=[a];f=[b];if(!(a.position+a.length<=b.position||a.position>=b.position+b.length)){d=c?a:b;e=c?b:a;if(a.position!==b.position||a.length!==b.length)n=r(d),p=r(e);b=m(e,d,"style:text-properties");if(b.majorChanged||b.minorChanged)f=[],a=[],g=d.position+d.length,l=e.position+e.length,e.position<d.position?b.minorChanged&&(s=r(p),s.length=d.pos [...]
++a.push(s),e.position=d.position,e.length=l-e.position):d.position<e.position&&b.majorChanged&&(s=r(n),s.length=e.position-d.position,f.push(s),d.position=e.position,d.length=g-d.position),l>g?b.minorChanged&&(n=p,n.position=g,n.length=l-g,a.push(n),e.length=g-e.position):g>l&&b.majorChanged&&(n.position=l,n.length=g-l,f.push(n),d.length=l-d.position),d.setProperties&&h(d.setProperties)&&f.push(d),e.setProperties&&h(e.setProperties)&&a.push(e),c?(g=f,f=a):g=a}return{opSpecsA:g,opSpecsB:f [...]
++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:c,RemoveCursor:c,RemoveStyle:c,RemoveText:function(a,b){var c=a.position+a.length,d=b.position+b.length,e=[a],f=[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:e=[]));return{opSpecsA:e,opSpecsB:f}},SetParagraphSty [...]
++b){b.position<a.position?a.position+=1:b.position<a.position+a.length&&(a.length+=1);return{opSpecsA:[a],opSpecsB:[b]}},UpdateMetadata:c,UpdateParagraphStyle:c},InsertText:{InsertText:function(a,b,c){a.position<b.position?b.position+=a.text.length:a.position>b.position?a.position+=b.text.length:c?b.position+=a.text.length:a.position+=b.text.length;return{opSpecsA:[a],opSpecsB:[b]}},MoveCursor:function(a,b){var c=l(b);a.position<b.position?b.position+=a.text.length:a.position<b.position+ [...]
++(b.length+=a.text.length);c&&g(b);return{opSpecsA:[a],opSpecsB:[b]}},RemoveCursor:c,RemoveMember:c,RemoveStyle:c,RemoveText:function(a,b){var c;c=b.position+b.length;var d=[a],e=[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},e.unshift(c),a.position=b.position);return{opSpecsA:d,opSpecsB:e}},SplitP [...]
++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:c,UpdateMetadata:c,UpdateParagraphStyle:c},MoveCursor:{MoveCursor:c,RemoveCursor:function(a,b){return{opSpecsA:a.memberid===b.memberid?[]:[a],opSpecsB:[b]}},RemoveMember:c,RemoveStyle:c,RemoveText:function(a,b){var c=l(a),d=a.position+a.length,e=b.position+b.length;e<=a.position?a.po [...]
++b.position<d&&(a.position<b.position?a.length=e<d?a.length-b.length:b.position-a.position:(a.position=b.position,a.length=e<d?d-e:0));c&&g(a);return{opSpecsA:[a],opSpecsB:[b]}},SetParagraphStyle:c,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:c,UpdateMetadata:c,UpdateParagraphStyle:c},RemoveCursor:{RemoveCursor:function(a,b){var c=a.memberid===b.memberid;re [...]
++[]:[a],opSpecsB:c?[]:[b]}},RemoveMember:c,RemoveStyle:c,RemoveText:c,SetParagraphStyle:c,SplitParagraph:c,UpdateMember:c,UpdateMetadata:c,UpdateParagraphStyle:c},RemoveMember:{RemoveStyle:c,RemoveText:c,SetParagraphStyle:c,SplitParagraph:c,UpdateMetadata:c,UpdateParagraphStyle:c},RemoveStyle:{RemoveStyle:function(a,b){var c=a.styleName===b.styleName&&a.styleFamily===b.styleFamily;return{opSpecsA:c?[]:[a],opSpecsB:c?[]:[b]}},RemoveText:c,SetParagraphStyle:function(a,b){var c,d=[a],e=[b]; [...]
++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:e}},SplitParagraph:c,UpdateMember:c,UpdateMetadata:c,UpdateParagraphStyle:function(a,b){var c,d=[a],e=[b];"paragraph"===a.styleFamily&&(c=f(b.setProperties,a.styleName),0<c.length&&(c={optype:"UpdateParagraphStyle",memberid:a.memberid,timestamp:a.timestamp,styleName:b.styleName,removed [...]
++d.unshift(c)),a.styleName===b.styleName?e=[]:p(b.setProperties,a.styleName));return{opSpecsA:d,opSpecsB:e}}},RemoveText:{RemoveText:function(a,b){var c=a.position+a.length,d=b.position+b.length,e=[a],f=[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):f=[]):(c<d?b.length-=a.length:b.position<a.position?b.length=a.position-b.position: [...]
++b.position,a.length=c-d):e=[]));return{opSpecsA:e,opSpecsB:f}},SplitParagraph:function(a,b){var c=a.position+a.length,d=[a],e=[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);return{opSpecsA:d,opSpecsB:e}},UpdateMember:c,UpdateMeta [...]
++SetParagraphStyle:{UpdateMember:c,UpdateMetadata:c,UpdateParagraphStyle:c},SplitParagraph:{SplitParagraph:function(a,b,c){a.position<b.position?b.position+=1:a.position>b.position?a.position+=1:a.position===b.position&&(c?b.position+=1:a.position+=1);return{opSpecsA:[a],opSpecsB:[b]}},UpdateMember:c,UpdateMetadata:c,UpdateParagraphStyle:c},UpdateMember:{UpdateMetadata:c,UpdateParagraphStyle:c},UpdateMetadata:{UpdateMetadata:function(a,b,c){var e,f=[a],g=[b];e=c?a:b;a=c?b:a;n(a.setProper [...]
++a.removedProperties||null,e.setProperties||null,e.removedProperties||null);e.setProperties&&h(e.setProperties)||e.removedProperties&&d(e.removedProperties)||(c?f=[]:g=[]);a.setProperties&&h(a.setProperties)||a.removedProperties&&d(a.removedProperties)||(c?g=[]:f=[]);return{opSpecsA:f,opSpecsB:g}},UpdateParagraphStyle:c},UpdateParagraphStyle:{UpdateParagraphStyle:function(a,b,c){var e,f=[a],g=[b];a.styleName===b.styleName&&(e=c?a:b,a=c?b:a,m(a,e,"style:paragraph-properties"),m(a,e,"style [...]
++n(a.setProperties||null,a.removedProperties||null,e.setProperties||null,e.removedProperties||null),e.setProperties&&h(e.setProperties)||e.removedProperties&&d(e.removedProperties)||(c?f=[]:g=[]),a.setProperties&&h(a.setProperties)||a.removedProperties&&d(a.removedProperties)||(c?g=[]:f=[]));return{opSpecsA:f,opSpecsB:g}}}};this.passUnchanged=c;this.extendTransformations=function(a){Object.keys(a).forEach(function(b){var c=a[b],d,f=e.hasOwnProperty(b);runtime.log((f?"Extending":"Adding") [...]
++b);f||(e[b]={});d=e[b];Object.keys(c).forEach(function(a){var e=d.hasOwnProperty(a);runtime.assert(b<=a,"Wrong order:"+b+", "+a);runtime.log("  "+(e?"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=e[a.optype])&&d[b.optype])?(d=d(a,b,!c),c||null===d||(d={opSpecsA:d.opSpecsB,opSpecsB:d. [...]
++d=null;runtime.log("result:");d?(runtime.log(runtime.toJson(d.opSpecsA)),runtime.log(runtime.toJson(d.opSpecsB))):runtime.log("null");return d}};
++// 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/
 +*/
 +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
++ops.OperationTransformer=function(){function g(g){var l=[];g.forEach(function(h){l.push(f.create(h))});return l}function l(f,g){for(var h,d,m=[],c=[];0<f.length&&g;){h=f.shift();h=p.transformOpspecVsOpspec(h,g);if(!h)return null;m=m.concat(h.opSpecsA);if(0===h.opSpecsB.length){m=m.concat(f);g=null;break}for(;1<h.opSpecsB.length;){d=l(f,h.opSpecsB.shift());if(!d)return null;c=c.concat(d.opSpecsB);f=d.opSpecsA}g=h.opSpecsB.pop()}g&&c.push(g);return{opSpecsA:m,opSpecsB:c}}var f,p=new ops.O [...]
++this.setOperationFactory=function(g){f=g};this.getOperationTransformMatrix=function(){return p};this.transform=function(f,n){for(var h,d=[];0<n.length;){h=l(f,n.shift());if(!h)return null;f=h.opSpecsA;d=d.concat(h.opSpecsB)}return{opsA:g(f),opsB:g(d)}}};
++// Input 85
 +/*
 +
 + 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(){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
++ops.TrivialOperationRouter=function(){var g,l;this.setOperationFactory=function(f){g=f};this.setPlaybackFunction=function(f){l=f};this.push=function(f){f.forEach(function(f){f=f.spec();f.timestamp=(new Date).getTime();f=g.create(f);l(f)})};this.close=function(f){f()};this.subscribe=function(f,g){};this.unsubscribe=function(f,g){};this.hasLocalUnsyncedOps=function(){return!1};this.hasSessionHostConnection=function(){return!0}};
++// Input 86
 +/*
 +
 + 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(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
++gui.EditInfoMarker=function(g,l){function f(c,d){return runtime.setTimeout(function(){h.style.opacity=c},d)}var p=this,r,n,h,d,m;this.addEdit=function(c,e){var a=Date.now()-e;g.addEdit(c,e);n.setEdits(g.getSortedEdits());h.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",c);d&&runtime.clearTimeout(d);m&&runtime.clearTimeout(m);1E4>a?(f(1,0),d=f(0.5,1E4-a),m=f(0.2,2E4-a)):1E4<=a&&2E4>a?(f(0.5,0),m=f(0.2,2E4-a)):f(0.2,0)};this.getEdits=function(){return g.getEdits()};this.cl [...]
++n.setEdits([]);h.hasAttributeNS("urn:webodf:names:editinfo","editinfo:memberid")&&h.removeAttributeNS("urn:webodf:names:editinfo","editinfo:memberid")};this.getEditInfo=function(){return g};this.show=function(){h.style.display="block"};this.hide=function(){p.hideHandle();h.style.display="none"};this.showHandle=function(){n.show()};this.hideHandle=function(){n.hide()};this.destroy=function(c){r.removeChild(h);n.destroy(function(d){d?c(d):g.destroy(c)})};(function(){var c=g.getOdtDocument [...]
++h=c.createElementNS(c.documentElement.namespaceURI,"div");h.setAttribute("class","editInfoMarker");h.onmouseover=function(){p.showHandle()};h.onmouseout=function(){p.hideHandle()};r=g.getNode();r.appendChild(h);n=new gui.EditInfoHandle(r);l||p.hide()})()};
++// Input 87
 +/*
 +
 + 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(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
++gui.PlainTextPasteboard=function(g,l){function f(f,g){f.init(g);return f}this.createPasteOps=function(p){var r=g.getCursorPosition(l),n=r,h=[];p.replace(/\r/g,"").split("\n").forEach(function(d){h.push(f(new ops.OpSplitParagraph,{memberid:l,position:n,moveCursor:!0}));n+=1;h.push(f(new ops.OpInsertText,{memberid:l,position:n,text:d,moveCursor:!0}));n+=d.length});h.push(f(new ops.OpRemoveText,{memberid:l,position:r,length:1}));return h}};
++// Input 88
 +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
++gui.SelectionView=function(g){function l(){var a=q.getRootNode();k!==a&&(k=a,t=k.parentNode.parentNode.parentNode,t.appendChild(w),t.appendChild(x),t.appendChild(v))}function f(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 p(a){H=a;w.style.display=x.style.display=v.style.display=!0===a?"block":"none"}function r(a){var b=s.getBoundingClientRect(t),c=q.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 h(a){var b=u.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 d(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 m(a,b){b&&0<b.width&&0<b.height&&(a=a?d(a,b):b);return a}function c(a){function b(a){y.setUnfilteredPosition(a,0);return w.acceptNode(a)===B&&t.acceptPosition(y)===B?B:L}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,h=a.endOffset,k,l,n=null,p,r=A.createRange(),t,w=new odf.OdfNodeFilter,v;if(e===d||f===d)return r=a.cloneRange(),n=r.getBoundingClientRect [...]
++n;for(a=e;a.parentNode!==d;)a=a.parentNode;for(l=f;l.parentNode!==d;)l=l.parentNode;t=q.createRootFilter(e);for(d=a.nextSibling;d&&d!==l;)p=c(d),n=m(n,p),d=d.nextSibling;if(u.isParagraph(a))n=m(n,s.getBoundingClientRect(a));else if(a.nodeType===Node.TEXT_NODE)d=a,r.setStart(d,g),r.setEnd(d,d===l?h:d.length),p=r.getBoundingClientRect(),n=m(n,p);else for(v=A.createTreeWalker(a,NodeFilter.SHOW_TEXT,b,!1),d=v.currentNode=e;d&&d!==f;)r.setStart(d,g),r.setEnd(d,d.length),p=r.getBoundingClient [...]
++p),k=d,g=0,d=v.nextNode();k||(k=e);if(u.isParagraph(l))n=m(n,s.getBoundingClientRect(l));else if(l.nodeType===Node.TEXT_NODE)d=l,r.setStart(d,d===a?g:0),r.setEnd(d,h),p=r.getBoundingClientRect(),n=m(n,p);else for(v=A.createTreeWalker(l,NodeFilter.SHOW_TEXT,b,!1),d=v.currentNode=f;d&&d!==k;)if(r.setStart(d,0),r.setEnd(d,h),p=r.getBoundingClientRect(),n=m(n,p),d=v.previousNode())h=d.length;return n}function e(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){p(!0);var a=g.getSelectedRange(),b=h(a),k,m,n,q;a.collapsed||!b?p(!1):(p(!0),a=b.firstRange,k=b.lastRange,b=b.fillerRange,m=r(e(a,!1)),q=r(e(k,!0)),n=(n=c(b))?r(n):d(m,q),f(w,{left:m.left,top:m.top,width:Math.max(0,n.width-(m.left-n.left)),height:m.height}),q.top===m.top||q.bottom===m.bottom?x.style.display=v.style.display="none":(f(v,{left:n.left,top:q.top,width:Math.max(0, [...]
++height:q.height}),f(x,{left:n.left,top:m.top+m.height,width:Math.max(0,parseFloat(w.style.left)+parseFloat(w.style.width)-parseFloat(v.style.left)),height:Math.max(0,q.top-m.bottom)})),a.detach(),k.detach(),b.detach())}else p(!1)}function b(b){b===g&&a()}var q=g.getOdtDocument(),k,t,A=q.getDOM(),w=A.createElement("div"),x=A.createElement("div"),v=A.createElement("div"),u=new odf.OdfUtils,s=new core.DomUtils,H=!0,y=gui.SelectionMover.createPositionIterator(q.getRootNode()),B=NodeFilter.F [...]
++L=NodeFilter.FILTER_REJECT;this.show=this.rerender=a;this.hide=function(){p(!1)};this.visible=function(){return H};this.destroy=function(a){t.removeChild(w);t.removeChild(x);t.removeChild(v);g.getOdtDocument().unsubscribe(ops.OdtDocument.signalCursorMoved,b);a()};(function(){var a=g.getMemberId();l();w.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",a);x.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",a);v.setAttributeNS("urn:webodf:names:editinfo","editinf [...]
++a);w.className=x.className=v.className="selectionOverlay";g.getOdtDocument().subscribe(ops.OdtDocument.signalCursorMoved,b)})()};
++// Input 89
 +/*
 +
 + 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(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
++gui.SelectionViewManager=function(){function g(){return Object.keys(l).map(function(f){return l[f]})}var l={};this.getSelectionView=function(f){return l.hasOwnProperty(f)?l[f]:null};this.getSelectionViews=g;this.removeSelectionView=function(f){l.hasOwnProperty(f)&&(l[f].destroy(function(){}),delete l[f])};this.hideSelectionView=function(f){l.hasOwnProperty(f)&&l[f].hide()};this.showSelectionView=function(f){l.hasOwnProperty(f)&&l[f].show()};this.rerenderSelectionViews=function(){Object. [...]
++l[f].rerender()})};this.registerCursor=function(f,g){var r=f.getMemberId(),n=new gui.SelectionView(f);g?n.show():n.hide();return l[r]=n};this.destroy=function(f){var l=g();(function n(g,d){d?f(d):g<l.length?l[g].destroy(function(d){n(g+1,d)}):f()})(0,void 0)}};
++// Input 90
 +/*
 +
 + 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 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
++gui.TrivialUndoManager=function(g){function l(){t.emit(gui.UndoManager.signalUndoStackChanged,{undoAvailable:h.hasUndoStates(),redoAvailable:h.hasRedoStates()})}function f(){b!==c&&b!==q[q.length-1]&&q.push(b)}function p(a){var b=a.previousSibling||a.nextSibling;a.parentNode.removeChild(a);d.normalizeTextNodes(b)}function r(a){return Object.keys(a).map(function(b){return a[b]})}function n(b){function c(a){var b=a.spec();if(f[b.memberid])switch(b.optype){case "AddCursor":d[b.memberid]||( [...]
++a,delete f[b.memberid],g-=1);break;case "MoveCursor":e[b.memberid]||(e[b.memberid]=a)}}var d={},e={},f={},g,h=b.pop();a.getCursors().forEach(function(a){f[a.getMemberId()]=!0});for(g=Object.keys(f).length;h&&0<g;)h.reverse(),h.forEach(c),h=b.pop();return r(d).concat(r(e))}var h=this,d=new core.DomUtils,m,c=[],e,a,b=[],q=[],k=[],t=new core.EventNotifier([gui.UndoManager.signalUndoStackChanged,gui.UndoManager.signalUndoStateCreated,gui.UndoManager.signalUndoStateModified,gui.TrivialUndoMa [...]
++A=g||new gui.UndoStateRules;this.subscribe=function(a,b){t.subscribe(a,b)};this.unsubscribe=function(a,b){t.unsubscribe(a,b)};this.hasUndoStates=function(){return 0<q.length};this.hasRedoStates=function(){return 0<k.length};this.setOdtDocument=function(b){a=b};this.resetInitialState=function(){q.length=0;k.length=0;c.length=0;b.length=0;m=null;l()};this.saveInitialState=function(){var e=a.getOdfCanvas().odfContainer(),g=a.getOdfCanvas().getAnnotationViewManager();g&&g.forgetAnnotations( [...]
++a.getOdfCanvas().refreshAnnotations();e=m;d.getElementsByTagNameNS(e,"urn:webodf:names:cursor","cursor").forEach(p);d.getElementsByTagNameNS(e,"urn:webodf:names:cursor","anchor").forEach(p);f();q.unshift(c);b=c=n(q);q.length=0;k.length=0;l()};this.setPlaybackFunction=function(a){e=a};this.onOperationExecuted=function(a){k.length=0;A.isEditOperation(a)&&b===c||!A.isPartOfOperationSet(a,b)?(f(),b=[a],q.push(b),t.emit(gui.UndoManager.signalUndoStateCreated,{operations:b}),l()):(b.push(a),t [...]
++{operations:b}))};this.moveForward=function(a){for(var c=0,d;a&&k.length;)d=k.pop(),q.push(d),d.forEach(e),a-=1,c+=1;c&&(b=q[q.length-1],l());return c};this.moveBackward=function(d){for(var f=a.getOdfCanvas(),g=f.odfContainer(),h=0;d&&q.length;)k.push(q.pop()),d-=1,h+=1;h&&(g.setRootElement(m.cloneNode(!0)),f.setOdfContainer(g,!0),t.emit(gui.TrivialUndoManager.signalDocumentRootReplaced,{}),a.getCursors().forEach(function(b){a.removeCursor(b.getMemberId())}),c.forEach(e),q.forEach(funct [...]
++f.refreshCSS(),b=q[q.length-1]||c,l());return h}};gui.TrivialUndoManager.signalDocumentRootReplaced="documentRootReplaced";(function(){return gui.TrivialUndoManager})();
++// Input 91
 +/*
 +
 + 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 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
++ops.Session=function(g){var l=new ops.OperationFactory,f=new ops.OdtDocument(g),p=null;this.setOperationFactory=function(f){l=f;p&&p.setOperationFactory(l)};this.setOperationRouter=function(g){p=g;g.setPlaybackFunction(function(g){return g.execute(f)?(f.emit(ops.OdtDocument.signalOperationExecuted,g),!0):!1});g.setOperationFactory(l)};this.getOperationFactory=function(){return l};this.getOdtDocument=function(){return f};this.enqueue=function(f){p.push(f)};this.close=function(g){p.close( [...]
++g(l):f.close(g)})};this.destroy=function(g){f.destroy(g)};this.setOperationRouter(new ops.TrivialOperationRouter)};
++// Input 92
 +/*
 +
 + 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=function(g,l){function f(){var e=h.getCursor(l),e=e&&e.getNode(),a=!1;if(e){a:{for(a=h.getRootNode();e&&e!==a;){if(e.namespaceURI===c&&"annotation"===e.localName){e=!0;break a}e=e.parentNode}e=!1}a=!e}a!==d&&(d=a,m.emit(gui.AnnotationController.annotatableChanged,d))}function p(c){c.getMemberId()===l&&f()}function r(c){c===l&&f()}function n(c){c.getMemberId()===l&&f()}var h=g.getOdtDocument(),d=!1,m=new core.EventNotifier([gui.AnnotationController.annotatableCha [...]
++this.isAnnotatable=function(){return d};this.addAnnotation=function(){var c=new ops.OpAddAnnotation,a=h.getCursorSelection(l),b=a.length,a=a.position;d&&(a=0<=b?a:a+b,b=Math.abs(b),c.init({memberid:l,position:a,length:b,name:l+Date.now()}),g.enqueue([c]))};this.removeAnnotation=function(c){var a,b;a=h.convertDomPointToCursorStep(c,0)+1;b=h.convertDomPointToCursorStep(c,c.childNodes.length);c=new ops.OpRemoveAnnotation;c.init({memberid:l,position:a,length:b-a});b=new ops.OpMoveCursor;b.i [...]
++position:0<a?a-1:a,length:0});g.enqueue([c,b])};this.subscribe=function(c,a){m.subscribe(c,a)};this.unsubscribe=function(c,a){m.unsubscribe(c,a)};this.destroy=function(c){h.unsubscribe(ops.OdtDocument.signalCursorAdded,p);h.unsubscribe(ops.OdtDocument.signalCursorRemoved,r);h.unsubscribe(ops.OdtDocument.signalCursorMoved,n);c()};h.subscribe(ops.OdtDocument.signalCursorAdded,p);h.subscribe(ops.OdtDocument.signalCursorRemoved,r);h.subscribe(ops.OdtDocument.signalCursorMoved,n);f()};
 +gui.AnnotationController.annotatableChanged="annotatable/changed";(function(){return gui.AnnotationController})();
- // Input 94
++// Input 93
 +/*
 +
 + 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(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
++gui.DirectParagraphStyler=function(g,l,f){function p(){function a(b,d,e){b!==d&&(void 0===c&&(c={}),c[e]=d);return d}var b=k.getCursor(l),b=b&&b.getSelectedRange(),c;v=a(v,b?w.isAlignedLeft(b):!1,"isAlignedLeft");u=a(u,b?w.isAlignedCenter(b):!1,"isAlignedCenter");s=a(s,b?w.isAlignedRight(b):!1,"isAlignedRight");H=a(H,b?w.isAlignedJustified(b):!1,"isAlignedJustified");c&&x.emit(gui.DirectParagraphStyler.paragraphStylingChanged,c)}function r(a){a.getMemberId()===l&&p()}function n(a){a===l [...]
++l&&p()}function d(){p()}function m(a){var b=k.getCursor(l);b&&k.getParagraphElement(b.getNode())===a.paragraphElement&&p()}function c(a){return a===ops.StepsTranslator.NEXT_STEP}function e(a){var b=k.getCursor(l).getSelectedRange(),b=A.getParagraphElements(b),d=k.getFormatting();b.forEach(function(b){var e=k.convertDomPointToCursorStep(b,0,c),h=b.getAttributeNS(odf.Namespaces.textns,"style-name");b=f.generateStyleName();var m;h&&(m=d.createDerivedStyleObject(h,"paragraph",{}));m=a(m||{} [...]
++h.init({memberid:l,styleName:b,styleFamily:"paragraph",isAutomaticStyle:!0,setProperties:m});m=new ops.OpSetParagraphStyle;m.init({memberid:l,styleName:b,position:e});g.enqueue([h,m])})}function a(a){e(function(b){return t.mergeObjects(b,a)})}function b(b){a({"style:paragraph-properties":{"fo:text-align":b}})}function q(a,b){var c=k.getFormatting().getDefaultTabStopDistance(),d=b["style:paragraph-properties"],d=(d=d&&d["fo:margin-left"])&&A.parseLength(d);return t.mergeObjects(b,{"style [...]
++d.unit===c.unit?d.value+a*c.value+d.unit:a*c.value+c.unit}})}var k=g.getOdtDocument(),t=new core.Utils,A=new odf.OdfUtils,w=new gui.StyleHelper(k.getFormatting()),x=new core.EventNotifier([gui.DirectParagraphStyler.paragraphStylingChanged]),v,u,s,H;this.isAlignedLeft=function(){return v};this.isAlignedCenter=function(){return u};this.isAlignedRight=function(){return s};this.isAlignedJustified=function(){return H};this.alignParagraphLeft=function(){b("left");return!0};this.alignParagraph [...]
++return!0};this.alignParagraphRight=function(){b("right");return!0};this.alignParagraphJustified=function(){b("justify");return!0};this.indent=function(){e(q.bind(null,1));return!0};this.outdent=function(){e(q.bind(null,-1));return!0};this.subscribe=function(a,b){x.subscribe(a,b)};this.unsubscribe=function(a,b){x.unsubscribe(a,b)};this.destroy=function(a){k.unsubscribe(ops.OdtDocument.signalCursorAdded,r);k.unsubscribe(ops.OdtDocument.signalCursorRemoved,n);k.unsubscribe(ops.OdtDocument. [...]
++h);k.unsubscribe(ops.OdtDocument.signalParagraphStyleModified,d);k.unsubscribe(ops.OdtDocument.signalParagraphChanged,m);a()};k.subscribe(ops.OdtDocument.signalCursorAdded,r);k.subscribe(ops.OdtDocument.signalCursorRemoved,n);k.subscribe(ops.OdtDocument.signalCursorMoved,h);k.subscribe(ops.OdtDocument.signalParagraphStyleModified,d);k.subscribe(ops.OdtDocument.signalParagraphChanged,m);p()};gui.DirectParagraphStyler.paragraphStylingChanged="paragraphStyling/changed";(function(){return g [...]
++// 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/
 +*/
 +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 [...]
++gui.DirectTextStyler=function(g,l){function f(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 p(a,b){var c=f(a[0],b);return a.every(function(a){return c===f(a,b)})?c:void 0}function r(){var a=u.getCursor(l),a=(a=a&&a.getSelectedRange())&&s.getAppliedStyles(a)||[];a[0]&&y&&(a[0]=v.mergeObjects(a[0],y));return a}function n(){function a(b,d,e){b!==d&&(void 0===c&&(c={}),c[e]=d);return d}var b,c;B=r();L=a(L,B?s.isBold(B):!1,"isBold");I=a(I,B?s.isItalic [...]
++W=a(W,B?s.hasUnderline(B):!1,"hasUnderline");Q=a(Q,B?s.hasStrikeThrough(B):!1,"hasStrikeThrough");b=B&&p(B,["style:text-properties","fo:font-size"]);z=a(z,b&&parseFloat(b),"fontSize");ja=a(ja,B&&p(B,["style:text-properties","style:font-name"]),"fontName");c&&H.emit(gui.DirectTextStyler.textStylingChanged,c)}function h(a){a.getMemberId()===l&&n()}function d(a){a===l&&n()}function m(a){a.getMemberId()===l&&n()}function c(){n()}function e(a){var b=u.getCursor(l);b&&u.getParagraphElement(b. [...]
++a.paragraphElement&&n()}function a(a,b){var c=u.getCursor(l);if(!c)return!1;c=s.getAppliedStyles(c.getSelectedRange());b(!a(c));return!0}function b(a){var b=u.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])):(y=v.mergeObjects(y||{},c),n())}function q(a,c){var d={};d[a]=c;b(d)}function k(a){a=a.spec();y&&a.memberid===l&&"SplitParagraph"!==a.optype&&(y=n [...]
++a?"bold":"normal")}function A(a){q("fo:font-style",a?"italic":"normal")}function w(a){q("style:text-underline-style",a?"solid":"none")}function x(a){q("style:text-line-through-style",a?"solid":"none")}var v=new core.Utils,u=g.getOdtDocument(),s=new gui.StyleHelper(u.getFormatting()),H=new core.EventNotifier([gui.DirectTextStyler.textStylingChanged]),y,B=[],L=!1,I=!1,W=!1,Q=!1,z,ja;this.formatTextSelection=b;this.createCursorStyleOp=function(a,b){var c=null;y&&(c=new ops.OpApplyDirectSty [...]
++position:a,length:b,setProperties:y}),y=null,n());return c};this.setBold=t;this.setItalic=A;this.setHasUnderline=w;this.setHasStrikethrough=x;this.setFontSize=function(a){q("fo:font-size",a+"pt")};this.setFontName=function(a){q("style:font-name",a)};this.getAppliedStyles=function(){return B};this.toggleBold=a.bind(this,s.isBold,t);this.toggleItalic=a.bind(this,s.isItalic,A);this.toggleUnderline=a.bind(this,s.hasUnderline,w);this.toggleStrikethrough=a.bind(this,s.hasStrikeThrough,x);this [...]
++this.isItalic=function(){return I};this.hasUnderline=function(){return W};this.hasStrikeThrough=function(){return Q};this.fontSize=function(){return z};this.fontName=function(){return ja};this.subscribe=function(a,b){H.subscribe(a,b)};this.unsubscribe=function(a,b){H.unsubscribe(a,b)};this.destroy=function(a){u.unsubscribe(ops.OdtDocument.signalCursorAdded,h);u.unsubscribe(ops.OdtDocument.signalCursorRemoved,d);u.unsubscribe(ops.OdtDocument.signalCursorMoved,m);u.unsubscribe(ops.OdtDocu [...]
++c);u.unsubscribe(ops.OdtDocument.signalParagraphChanged,e);u.unsubscribe(ops.OdtDocument.signalOperationExecuted,k);a()};u.subscribe(ops.OdtDocument.signalCursorAdded,h);u.subscribe(ops.OdtDocument.signalCursorRemoved,d);u.subscribe(ops.OdtDocument.signalCursorMoved,m);u.subscribe(ops.OdtDocument.signalParagraphStyleModified,c);u.subscribe(ops.OdtDocument.signalParagraphChanged,e);u.subscribe(ops.OdtDocument.signalOperationExecuted,k);n()};gui.DirectTextStyler.textStylingChanged="textSt [...]
 +(function(){return gui.DirectTextStyler})();
- // Input 96
++// Input 95
 +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 [...]
++gui.ImageManager=function(g,l,f){var p={"image/gif":".gif","image/jpeg":".jpg","image/png":".png"},r=odf.Namespaces.textns,n=g.getOdtDocument(),h=n.getFormatting(),d={};this.insertImage=function(m,c,e,a){var b;runtime.assert(0<e&&0<a,"Both width and height of the image should be greater than 0px.");b=n.getParagraphElement(n.getCursor(l).getNode()).getAttributeNS(r,"style-name");d.hasOwnProperty(b)||(d[b]=h.getContentSize(b,"paragraph"));b=d[b];e*=0.0264583333333334;a*=0.0264583333333334 [...]
++1;e>b.width&&(q=b.width/e);a>b.height&&(k=b.height/a);q=Math.min(q,k);b=e*q;e=a*q;k=n.getOdfCanvas().odfContainer().rootElement.styles;a=m.toLowerCase();var q=p.hasOwnProperty(a)?p[a]:null,t;a=[];runtime.assert(null!==q,"Image type is not supported: "+m);q="Pictures/"+f.generateImageName()+q;t=new ops.OpSetBlob;t.init({memberid:l,filename:q,mimetype:m,content:c});a.push(t);h.getStyleElement("Graphics","graphic",[k])||(m=new ops.OpAddStyle,m.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(m));m=f.generateStyleName();c=new ops.OpAddStyle;c.init({memberid:l,styleName:m,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
++a.push(c);t=new ops.OpInsertImage;t.init({memberid:l,position:n.getCursorPosition(l),filename:q,frameWidth:b+"cm",frameHeight:e+"cm",frameStyleName:m,frameName:f.generateFrameName()});a.push(t);g.enqueue(a)}};
++// Input 96
 +/*
 +
 + 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,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
++gui.TextManipulator=function(g,l,f){function p(d){var c=new ops.OpRemoveText;c.init({memberid:l,position:d.position,length:d.length});return c}function r(d){0>d.length&&(d.position+=d.length,d.length=-d.length);return d}function n(f,c){var e=new core.PositionFilterChain,a=gui.SelectionMover.createPositionIterator(h.getRootElement(f)),b=c?a.nextPosition:a.previousPosition;e.addFilter("BaseFilter",h.getPositionFilter());e.addFilter("RootFilter",h.createRootFilter(l));for(a.setUnfilteredPo [...]
++d)return!0;return!1}var h=g.getOdtDocument(),d=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.enqueueParagraphSplittingOps=function(){var d=r(h.getCursorSelection(l)),c,e=[];0<d.length&&(c=p(d),e.push(c));c=new ops.OpSplitParagraph;c.init({memberid:l,position:d.position,moveCursor:!0});e.push(c);g.enqueue(e);return!0};this.removeTextByBackspaceKey=function(){var d=h.getCursor(l),c=r(h.getCursorSelection(l)),e=null;0===c.length?n(d.getNode(),!1)&&(e=new ops.OpRemoveText,e.init({memb [...]
++1,length:1}),g.enqueue([e])):(e=p(c),g.enqueue([e]));return null!==e};this.removeTextByDeleteKey=function(){var d=h.getCursor(l),c=r(h.getCursorSelection(l)),e=null;0===c.length?n(d.getNode(),!0)&&(e=new ops.OpRemoveText,e.init({memberid:l,position:c.position,length:1}),g.enqueue([e])):(e=p(c),g.enqueue([e]));return null!==e};this.removeCurrentSelection=function(){var d=r(h.getCursorSelection(l));0!==d.length&&(d=p(d),g.enqueue([d]));return!0};this.insertText=function(d){var c=r(h.getCu [...]
++e,a=[];0<c.length&&(e=p(c),a.push(e));e=new ops.OpInsertText;e.init({memberid:l,position:c.position,text:d,moveCursor:!0});a.push(e);f&&(d=f(c.position,d.length))&&a.push(d);g.enqueue(a)}};(function(){return gui.TextManipulator})();
++// Input 97
 +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
++gui.SessionController=function(){var g=core.PositionFilter.FilterResult.FILTER_ACCEPT;gui.SessionController=function(l,f,p,r){function n(a){a.preventDefault?a.preventDefault():a.returnValue=!1}function h(a,b,c){var d=new ops.OpMoveCursor;d.init({memberid:f,position:a,length:b||0,selectionType:c});return d}function d(a){var b=/[A-Za-z0-9]/,c=gui.SelectionMover.createPositionIterator(D.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 m(a){var b=D.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 c(a){a=D.getDistanceFromCursor(f,a,0);var b=null!==a?a+1:null,c;if(b||a)c=D.getCursorPosition(f),a=h(c+a,b-a,ops.OdtCursor.RegionSelection),l.enqueue([a]);K.focus()}function e(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 b(b,c,e){var g=D.getOdfCanvas().getElement(),k;k=ha.containsNode(g,b.startContainer);g=ha.containsNode(g,b.endContainer);if(k||g)if(k&&g&&(2===e?d(b):3<=e&&m(b)),b=c?{anchorNode:b.startContainer,anchorOffset:b.startOffset,focusNode:b.endContainer,focusOffset:b.endOffset}:{anchorNode [...]
++anchorOffset:b.endOffset,focusNode:b.startContainer,focusOffset:b.startOffset},c=D.convertDomToCursorRange(b,a(ia.getParagraphElement)),b=D.getCursorSelection(f),c.position!==b.position||c.length!==b.length)b=h(c.position,c.length,ops.OdtCursor.RangeSelection),l.enqueue([b])}function q(a){var b=D.getCursorSelection(f),c=D.getCursor(f).getStepCounter();0!==a&&(a=0<a?c.convertForwardStepsBetweenFilters(a,sa,xa):-c.convertBackwardStepsBetweenFilters(-a,sa,xa),a=b.length+a,l.enqueue([h(b.po [...]
++function k(a){var b=D.getCursorPosition(f),c=D.getCursor(f).getStepCounter();0!==a&&(a=0<a?c.convertForwardStepsBetweenFilters(a,sa,xa):-c.convertBackwardStepsBetweenFilters(-a,sa,xa),l.enqueue([h(b+a,0)]))}function t(){k(-1);return!0}function A(){k(1);return!0}function w(){q(-1);return!0}function x(){q(1);return!0}function v(a,b){var c=D.getParagraphElement(D.getCursor(f).getNode());runtime.assert(Boolean(c),"SessionController: Cursor outside paragraph");c=D.getCursor(f).getStepCounter [...]
++sa);b?q(c):k(c)}function u(){v(-1,!1);return!0}function s(){v(1,!1);return!0}function H(){v(-1,!0);return!0}function y(){v(1,!0);return!0}function B(a,b){var c=D.getCursor(f).getStepCounter().countStepsToLineBoundary(a,sa);b?q(c):k(c)}function L(){B(-1,!1);return!0}function I(){B(1,!1);return!0}function W(){B(-1,!0);return!0}function Q(){B(1,!0);return!0}function z(){var a=D.getParagraphElement(D.getCursor(f).getNode()),b,c;runtime.assert(Boolean(a),"SessionController: Cursor outside pa [...]
++c=D.getDistanceFromCursor(f,a,0);b=gui.SelectionMover.createPositionIterator(D.getRootNode());for(b.setUnfilteredPosition(a,0);0===c&&b.previousPosition();)a=b.getCurrentNode(),ia.isParagraph(a)&&(c=D.getDistanceFromCursor(f,a,0));q(c);return!0}function ja(){var a=D.getParagraphElement(D.getCursor(f).getNode()),b,c;runtime.assert(Boolean(a),"SessionController: Cursor outside paragraph");b=gui.SelectionMover.createPositionIterator(D.getRootNode());b.moveToEndOfNode(a);for(c=D.getDistance [...]
++b.container(),b.unfilteredDomOffset());0===c&&b.nextPosition();)a=b.getCurrentNode(),ia.isParagraph(a)&&(b.moveToEndOfNode(a),c=D.getDistanceFromCursor(f,b.container(),b.unfilteredDomOffset()));q(c);return!0}function ka(a,b){var c=gui.SelectionMover.createPositionIterator(D.getRootNode());0<a&&c.moveToEnd();c=D.getDistanceFromCursor(f,c.container(),c.unfilteredDomOffset());b?q(c):k(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 J(){var a=D.getRootNode(),a=D.convertDomPointToCursorStep(a,a.childNodes.length);l.enqueue([h(0,a)]);return!0}function F(){var a=D.getCursor(f);if(a&&a.getSelectionType()===ops.OdtCursor.RegionSelection&&(a=ia.getImageElements(a.getSelectedRange())[0])){ya.select(a.parentNode);return}ya.clearSelection()}function C(a){var b=D.getCursor(f).getSelectedRange();b.collapsed?a.preventDefault():Da.setDataFromRange(a,b)?oa.removeCurrentSelection():runtime.log("Cut operation [...]
++function Y(){return!1!==D.getCursor(f).getSelectedRange().collapsed}function U(a){var b=D.getCursor(f).getSelectedRange();b.collapsed?a.preventDefault():Da.setDataFromRange(a,b)||runtime.log("Copy operation failed")}function R(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(),l.enqueue(Fa.createPasteOps(b)));a.preventDefault?a.preventDe [...]
++!1}function P(){return!1}function M(a){if(V)V.onOperationExecuted(a)}function ba(a){D.emit(ops.OdtDocument.signalUndoStackChanged,a)}function la(){return V?(V.moveBackward(1),va.trigger(),!0):!1}function ca(){return V?(V.moveForward(1),va.trigger(),!0):!1}function ma(){var a=fa.getSelection(),b=0<a.rangeCount&&e(a);ra&&b&&(ta=!0,ya.clearSelection(),Ea.setUnfilteredPosition(a.focusNode,a.focusOffset),Ba.acceptPosition(Ea)===g&&(2===wa?d(b.range):3<=wa&&m(b.range),p.setSelectedRange(b.ran [...]
++D.emit(ops.OdtDocument.signalCursorMoved,p)))}function T(a){var b=a.target||a.srcElement,c=D.getCursor(f);if(ra=b&&ha.containsNode(D.getOdfCanvas().getElement(),b))ta=!1,Ba=D.createRootFilter(b),wa=a.detail,c&&a.shiftKey?fa.getSelection().collapse(c.getAnchorNode(),0):(a=fa.getSelection(),b=c.getSelectedRange(),a.extend?c.hasForwardSelection()?(a.collapse(b.startContainer,b.startOffset),a.extend(b.endContainer,b.endOffset)):(a.collapse(b.endContainer,b.endOffset),a.extend(b.startContain [...]
++(a.removeAllRanges(),a.addRange(b.cloneRange()),D.getOdfCanvas().getElement().setActive())),1<wa&&ma()}function $(a){var d=a.target||a.srcElement,f=a.detail,g=a.clientX,h=a.clientY;za.processRequests();ia.isImage(d)&&ia.isCharacterFrame(d.parentNode)?(c(d.parentNode),K.focus()):ra&&!ya.isSelectorElement(d)&&(ta?(b(p.getSelectedRange(),p.hasForwardSelection(),a.detail),K.focus()):runtime.setTimeout(function(){var a;a=(a=fa.getSelection())?{anchorNode:a.anchorNode,anchorOffset:a.anchorOff [...]
++focusOffset:a.focusOffset}:null;var c;if(!a.anchorNode&&!a.focusNode){var d=D.getDOM();c=null;d.caretRangeFromPoint?(d=d.caretRangeFromPoint(g,h),c={container:d.startContainer,offset:d.startOffset}):d.caretPositionFromPoint&&(d=d.caretPositionFromPoint(g,h))&&d.offsetNode&&(c={container:d.offsetNode,offset:d.offset});c&&(a.anchorNode=c.container,a.anchorOffset=c.offset,a.focusNode=a.anchorNode,a.focusOffset=a.anchorOffset)}a.anchorNode&&a.focusNode&&(a=e(a),b(a.range,a.hasForwardSelecti [...]
++0));wa=0;ta=ra=!1}function X(){ra&&K.focus();wa=0;ta=ra=!1}function da(a){$(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)):$(a)}function ga(a){return function(){a();return!0}}function E(a){return function(b){return D.getCursor(f).getSelectionType()===ops.OdtCursor.RangeSelection?a(b):!0}}var fa=runtime.getWindow(),D=l.getOdtDocument(),pa [...]
++ha=new core.DomUtils,ia=new odf.OdfUtils,Da=new gui.Clipboard,N=new gui.KeyboardHandler,qa=new gui.KeyboardHandler,sa=new core.PositionFilterChain,xa=D.getPositionFilter(),ra=!1,Aa=new odf.ObjectNameGenerator(D.getOdfCanvas().odfContainer(),f),ta=!1,Ba=null,V=null,K=new gui.EventManager(D),ua=new gui.AnnotationController(l,f),na=new gui.DirectTextStyler(l,f),ea=r&&r.directParagraphStylingEnabled?new gui.DirectParagraphStyler(l,f,Aa):null,oa=new gui.TextManipulator(l,f,na.createCursorSty [...]
++f,Aa),ya=new gui.ImageSelector(D.getOdfCanvas()),Ea=gui.SelectionMover.createPositionIterator(D.getRootNode()),za,va,Fa=new gui.PlainTextPasteboard(D,f),wa=0;runtime.assert(null!==fa,"Expected to be run in an environment which has a global window, like a browser.");sa.addFilter("BaseFilter",xa);sa.addFilter("RootFilter",D.createRootFilter(f));this.selectRange=b;this.moveCursorToLeft=t;this.moveCursorToDocumentBoundary=ka;this.extendSelectionToEntireDocument=J;this.startEditing=function( [...]
++K.subscribe("keydown",N.handleEvent);K.subscribe("keypress",qa.handleEvent);K.subscribe("keyup",n);K.subscribe("beforecut",Y);K.subscribe("cut",C);K.subscribe("copy",U);K.subscribe("beforepaste",P);K.subscribe("paste",R);K.subscribe("mousedown",T);K.subscribe("mousemove",za.trigger);K.subscribe("mouseup",S);K.subscribe("contextmenu",da);K.subscribe("dragend",X);D.subscribe(ops.OdtDocument.signalOperationExecuted,va.trigger);D.subscribe(ops.OdtDocument.signalOperationExecuted,M);a=new op [...]
++a.init({memberid:f});l.enqueue([a]);V&&V.saveInitialState()};this.endEditing=function(){var a;a=new ops.OpRemoveCursor;a.init({memberid:f});l.enqueue([a]);V&&V.resetInitialState();D.unsubscribe(ops.OdtDocument.signalOperationExecuted,M);D.unsubscribe(ops.OdtDocument.signalOperationExecuted,va.trigger);K.unsubscribe("keydown",N.handleEvent);K.unsubscribe("keypress",qa.handleEvent);K.unsubscribe("keyup",n);K.unsubscribe("cut",C);K.unsubscribe("beforecut",Y);K.unsubscribe("copy",U);K.unsub [...]
++R);K.unsubscribe("beforepaste",P);K.unsubscribe("mousemove",za.trigger);K.unsubscribe("mousedown",T);K.unsubscribe("mouseup",S);K.unsubscribe("contextmenu",da);K.unsubscribe("dragend",X);D.getOdfCanvas().getElement().classList.remove("virtualSelections")};this.getInputMemberId=function(){return f};this.getSession=function(){return l};this.setUndoManager=function(a){V&&V.unsubscribe(gui.UndoManager.signalUndoStackChanged,ba);if(V=a)V.setOdtDocument(D),V.setPlaybackFunction(function(a){a. [...]
++V.subscribe(gui.UndoManager.signalUndoStackChanged,ba)};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 K};this.getKeyboardHandlers=function(){return{keydown:N,keypress:qa}};this.destroy=function(a){var b=[za.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;za=new core.ScheduledTask(ma,0);va=new core.ScheduledTask(F,0);N.bind(c.Tab,b.None,E(function(){oa.insertText("\t");return!0}));N.bind(c.Left,b.None,E(t));N.bind(c.Right,b.None,E(A));N.bind(c.Up,b.None,E(u));N.bind(c.Down,b.None,E(s));N.bind(c.Backspace,b.None,ga(oa.removeTextByBackspaceKey));N.bind(c.Delete,b.Non [...]
++N.bind(c.Left,b.Shift,E(w));N.bind(c.Right,b.Shift,E(x));N.bind(c.Up,b.Shift,E(H));N.bind(c.Down,b.Shift,E(y));N.bind(c.Home,b.None,E(L));N.bind(c.End,b.None,E(I));N.bind(c.Home,b.Ctrl,E(G));N.bind(c.End,b.Ctrl,E(Z));N.bind(c.Home,b.Shift,E(W));N.bind(c.End,b.Shift,E(Q));N.bind(c.Up,b.CtrlShift,E(z));N.bind(c.Down,b.CtrlShift,E(ja));N.bind(c.Home,b.CtrlShift,E(O));N.bind(c.End,b.CtrlShift,E(aa));a?(N.bind(c.Clear,b.None,oa.removeCurrentSelection),N.bind(c.Left,b.Meta,E(L)),N.bind(c.Righ [...]
++N.bind(c.Home,b.Meta,E(G)),N.bind(c.End,b.Meta,E(Z)),N.bind(c.Left,b.MetaShift,E(W)),N.bind(c.Right,b.MetaShift,E(Q)),N.bind(c.Up,b.AltShift,E(z)),N.bind(c.Down,b.AltShift,E(ja)),N.bind(c.Up,b.MetaShift,E(O)),N.bind(c.Down,b.MetaShift,E(aa)),N.bind(c.A,b.Meta,E(J)),N.bind(c.B,b.Meta,E(na.toggleBold)),N.bind(c.I,b.Meta,E(na.toggleItalic)),N.bind(c.U,b.Meta,E(na.toggleUnderline)),ea&&(N.bind(c.L,b.MetaShift,E(ea.alignParagraphLeft)),N.bind(c.E,b.MetaShift,E(ea.alignParagraphCenter)),N.bin [...]
++E(ea.alignParagraphRight)),N.bind(c.J,b.MetaShift,E(ea.alignParagraphJustified))),ua&&N.bind(c.C,b.MetaShift,ua.addAnnotation),N.bind(c.Z,b.Meta,la),N.bind(c.Z,b.MetaShift,ca)):(N.bind(c.A,b.Ctrl,E(J)),N.bind(c.B,b.Ctrl,E(na.toggleBold)),N.bind(c.I,b.Ctrl,E(na.toggleItalic)),N.bind(c.U,b.Ctrl,E(na.toggleUnderline)),ea&&(N.bind(c.L,b.CtrlShift,E(ea.alignParagraphLeft)),N.bind(c.E,b.CtrlShift,E(ea.alignParagraphCenter)),N.bind(c.R,b.CtrlShift,E(ea.alignParagraphRight)),N.bind(c.J,b.CtrlSh [...]
++ua&&N.bind(c.C,b.CtrlAlt,ua.addAnnotation),N.bind(c.Z,b.Ctrl,la),N.bind(c.Z,b.CtrlShift,ca));qa.setDefault(E(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,E(oa.enqueueParagraphSplittingOps))})()};return gui.SessionController}();
++// Input 98
 +/*
 +
 + 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.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
++gui.CaretManager=function(g){function l(a){return b.hasOwnProperty(a)?b[a]:null}function f(){return Object.keys(b).map(function(a){return b[a]})}function p(a){a===g.getInputMemberId()&&g.getSession().getOdtDocument().getOdfCanvas().getElement().removeAttribute("tabindex");delete b[a]}function r(a){a=a.getMemberId();a===g.getInputMemberId()&&(a=l(a))&&a.refreshCursorBlinking()}function n(){var a=l(g.getInputMemberId());k=!1;a&&a.ensureVisible()}function h(){var a=l(g.getInputMemberId()); [...]
++k||(k=!0,runtime.setTimeout(n,50)))}function d(a){a.memberId===g.getInputMemberId()&&h()}function m(){var a=l(g.getInputMemberId());a&&a.setFocus()}function c(){var a=l(g.getInputMemberId());a&&a.removeFocus()}function e(){var a=l(g.getInputMemberId());a&&a.show()}function a(){var a=l(g.getInputMemberId());a&&a.hide()}var b={},q=runtime.getWindow(),k=!1;this.registerCursor=function(a,c,d){var e=a.getMemberId();c=new gui.Caret(a,c,d);b[e]=c;e===g.getInputMemberId()?(runtime.log("Starting [...]
++e),a.handleUpdate=h,g.getSession().getOdtDocument().getOdfCanvas().getElement().setAttribute("tabindex",-1),g.getEventManager().focus()):a.handleUpdate=c.handleUpdate;return c};this.getCaret=l;this.getCarets=f;this.destroy=function(h){var k=g.getSession().getOdtDocument(),l=g.getEventManager(),n=f();k.unsubscribe(ops.OdtDocument.signalParagraphChanged,d);k.unsubscribe(ops.OdtDocument.signalCursorMoved,r);k.unsubscribe(ops.OdtDocument.signalCursorRemoved,p);l.unsubscribe("focus",m);l.uns [...]
++c);q.removeEventListener("focus",e,!1);q.removeEventListener("blur",a,!1);(function u(a,b){b?h(b):a<n.length?n[a].destroy(function(b){u(a+1,b)}):h()})(0,void 0);b={}};(function(){var b=g.getSession().getOdtDocument(),f=g.getEventManager();b.subscribe(ops.OdtDocument.signalParagraphChanged,d);b.subscribe(ops.OdtDocument.signalCursorMoved,r);b.subscribe(ops.OdtDocument.signalCursorRemoved,p);f.subscribe("focus",m);f.subscribe("blur",c);q.addEventListener("focus",e,!1);q.addEventListener(" [...]
++// 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("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
++gui.SessionView=function(){return function(g,l,f,p,r){function n(a,b,c){function d(b,c,e){c=b+'[editinfo|memberid="'+a+'"]'+e+c;a:{var f=t.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:t.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 h(a){var b,c;for(c in w)w.hasOwnProperty(c)&&(b=w[c],a?b.show():b.hide())}function d(a){p.getCarets().forEach(function(b){a?b.showHandle():b.hideHandle()})}function m(a){var b=a.getMemberId();a=a.getProperties();n(b,a.fullName,a.color);l===b&&n("","",a.color)}function c(a){var b=a.getMemberId(),c=f.getOdtDocument().getMember(b).getProperties();p.registerCursor [...]
++!0);if(a=p.getCaret(b))a.setAvatarImageUrl(c.imageUrl),a.setColor(c.color);runtime.log("+++ View here +++ eagerly created an Caret for '"+b+"'! +++")}function e(a){a=a.getMemberId();var b=r.getSelectionView(l),c=r.getSelectionView(gui.ShadowCursor.ShadowCursorMemberId),d=p.getCaret(l);a===l?(c.hide(),b&&b.show(),d&&d.show()):a===gui.ShadowCursor.ShadowCursorMemberId&&(c.show(),b&&b.hide(),d&&d.hide())}function a(a){r.removeSelectionView(a)}function b(a){var b=a.paragraphElement,c=a.memb [...]
++var d,e="",g=b.getElementsByTagNameNS(A,"editinfo")[0];g?(e=g.getAttributeNS(A,"id"),d=w[e]):(e=Math.random().toString(),d=new ops.EditInfo(b,f.getOdtDocument()),d=new gui.EditInfoMarker(d,x),g=b.getElementsByTagNameNS(A,"editinfo")[0],g.setAttributeNS(A,"id",e),w[e]=d);d.addEdit(c,new Date(a))}function q(){H=!0}function k(){s=runtime.getWindow().setInterval(function(){H&&(r.rerenderSelectionViews(),H=!1)},200)}var t,A="urn:webodf:names:editinfo",w={},x=void 0!==g.editInfoMarkersInitial [...]
++Boolean(g.editInfoMarkersInitiallyVisible):!0,v=void 0!==g.caretAvatarsInitiallyVisible?Boolean(g.caretAvatarsInitiallyVisible):!0,u=void 0!==g.caretBlinksOnRangeSelect?Boolean(g.caretBlinksOnRangeSelect):!0,s,H=!1;this.showEditInfoMarkers=function(){x||(x=!0,h(x))};this.hideEditInfoMarkers=function(){x&&(x=!1,h(x))};this.showCaretAvatars=function(){v||(v=!0,d(v))};this.hideCaretAvatars=function(){v&&(v=!1,d(v))};this.getSession=function(){return f};this.getCaret=function(a){return p.ge [...]
++this.destroy=function(d){var g=f.getOdtDocument(),h=Object.keys(w).map(function(a){return w[a]});g.unsubscribe(ops.OdtDocument.signalMemberAdded,m);g.unsubscribe(ops.OdtDocument.signalMemberUpdated,m);g.unsubscribe(ops.OdtDocument.signalCursorAdded,c);g.unsubscribe(ops.OdtDocument.signalCursorRemoved,a);g.unsubscribe(ops.OdtDocument.signalParagraphChanged,b);g.unsubscribe(ops.OdtDocument.signalCursorMoved,e);g.unsubscribe(ops.OdtDocument.signalParagraphChanged,q);g.unsubscribe(ops.OdtDo [...]
++q);g.unsubscribe(ops.OdtDocument.signalParagraphStyleModified,q);runtime.getWindow().clearInterval(s);t.parentNode.removeChild(t);(function W(a,b){b?d(b):a<h.length?h[a].destroy(function(b){W(a+1,b)}):d()})(0,void 0)};(function(){var d=f.getOdtDocument(),g=document.getElementsByTagName("head")[0];d.subscribe(ops.OdtDocument.signalMemberAdded,m);d.subscribe(ops.OdtDocument.signalMemberUpdated,m);d.subscribe(ops.OdtDocument.signalCursorAdded,c);d.subscribe(ops.OdtDocument.signalCursorRemo [...]
++b);d.subscribe(ops.OdtDocument.signalCursorMoved,e);k();d.subscribe(ops.OdtDocument.signalParagraphChanged,q);d.subscribe(ops.OdtDocument.signalTableAdded,q);d.subscribe(ops.OdtDocument.signalParagraphStyleModified,q);t=document.createElementNS(g.namespaceURI,"style");t.type="text/css";t.media="screen, print, handheld, projection";t.appendChild(document.createTextNode("@namespace editinfo url(urn:webodf:names:editinfo);"));t.appendChild(document.createTextNode("@namespace dc url(http:// [...]
++g.appendChild(t)})()}}();
++// Input 100
 +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 [...]
diff --cc apps/documents/js/documents.js
index decb3ff,0000000..612b0fe
mode 100644,000000..100644
--- a/apps/documents/js/documents.js
+++ b/apps/documents/js/documents.js
@@@ -1,456 -1,0 +1,557 @@@
 +/*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,
++	fileName: null,
 +	
 +	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(){
++		showProgress : function(message){
++			if (!message){
++				message = ' ';
++			}
++			$('.documentslist .progress div').text(message);
 +			$('.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.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.fileId = response.file_id;
++				documentsMain.fileName = documentsMain.getNameByFileid(response.file_id);
 +				documentsMain.UI.showEditor(
- 						documentsMain.getNameByFileid(response.file_id),
++						documentsMain.fileName,
 +						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});
 +	},
- 	
++
++	renameDocument: function(name) {
++		var url = OC.Router.generate('documents_session_renamedocument') + '/' + documentsMain.fileId;
++		$.post(
++			url,
++			{ name : name },
++			function(result) {
++				if (result && result.status === 'error') {
++					if (result.message){
++						OC.Notification.show(result.message);
++						setTimeout(function() {
++							OC.Notification.hide();
++						}, 10000);
++					}
++					return;
++				}
++				documentsMain.fileName = name;
++				$('title').text(documentsMain.UI.mainTitle + '| ' + name);
++				$('#document-title>div').text(name);
++			}
++		);
++	},
++
++	// FIXME: copy/pasted from Files.isFileNameValid, needs refactor into core
++	isFileNameValid:function (name) {
++		if (name === '.') {
++			throw t('files', '\'.\' is an invalid file name.');
++		} else if (name.length === 0) {
++			throw t('files', 'File name cannot be empty.');
++		}
++
++		// check for invalid characters
++		var invalid_characters = ['\\', '/', '<', '>', ':', '"', '|', '?', '*'];
++		for (var i = 0; i < invalid_characters.length; i++) {
++			if (name.indexOf(invalid_characters[i]) !== -1) {
++				throw t('files', "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed.");
++			}
++		}
++		return true;
++	},
++
++	onRenamePrompt: function() {
++		var name = documentsMain.fileName;
++		var lastPos = name.lastIndexOf('.');
++		var extension = name.substr(lastPos + 1);
++		name = name.substr(0, lastPos);
++		var input = $('<input type="text" class="filename"/>').val(name);
++		$('#document-title').append(input);
++		$('#document-title>div').hide();
++
++		input.on('blur', function(){
++			var newName = input.val();
++			if (!newName || newName === name) {
++				input.tipsy('hide');
++				input.remove();
++				$('#document-title>div').show();
++				return;
++			}
++			else {
++				newName = newName + '.' + extension;
++				try {
++					input.tipsy('hide');
++					input.removeClass('error');
++					if (documentsMain.isFileNameValid(newName)) {
++						input.tipsy('hide');
++						input.remove();
++						$('#document-title>div').show();
++						documentsMain.renameDocument(newName);
++					}
++				}
++				catch (error) {
++					input.attr('title', error);
++					input.tipsy({gravity: 'n', trigger: 'manual'});
++					input.tipsy('show');
++					input.addClass('error');
++				}
++			}
++		});
++		input.on('keyup', function(event){
++			if (event.keyCode === 27) {
++				// cancel by putting in an empty value
++				$(this).val('');
++				$(this).blur();
++				event.preventDefault();
++			}
++			if (event.keyCode === 13) {
++				$(this).blur();
++				event.preventDefault();
++			}
++		});
++		input.focus();
++		input.selectRange(0, name.length);
++	},
++
 +	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();
++		documentsMain.UI.showProgress(t('documents', 'Loading documents...'));
 +		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="emptycontent">'
 +				+ t('documents', 'No documents are found. Please upload or create a document!')
 +				+ '</div>'
 +			);
 +		} else {
 +			$('#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', '#document-title>div', documentsMain.onRenamePrompt);
 +	$(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 088bafa,0000000..398a409
mode 100644,000000..100644
--- a/apps/documents/js/viewer/viewer.js
+++ b/apps/documents/js/viewer/viewer.js
@@@ -1,112 -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: [
 +		'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.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.open(OC.linkTo('documents', 'index.php') + '#' + fileId);
 +	},
 +			
 +	onView: function(filename) {
 +		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');
++			OC.addStyle('documents', '3rdparty/webodf/editor');
 +		}
 +		
 +		OC.addStyle('documents', 'viewer/odfviewer');
 +		
 +		OC.addScript('documents', '3rdparty/webodf/' + webodfSource, function() {
 +			// 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>';
 +				if (odfViewer.isDocuments){
 +					$(attachToolbarTo).prepend(odfToolbarHtml);
 +					$('#odf-toolbar').css({position:'fixed'});
 +				} else {
 +					$(attachToolbarTo).append(odfToolbarHtml);
 +				}
 +			});
 +
 +			// fade out file list and show pdf canvas
 +			$('table, #documents-content').fadeOut('slow').promise().done(function() {
 +				var canvashtml = '<div id="odf-canvas"></div>';
 +				$(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, #documents-content').fadeIn('slow');
 +		});
 +	}
 +};
 +
 +$(document).ready(function() {
 +	if (typeof FileActions !== 'undefined') {
 +		odfViewer.register();
 +	}
 +
 +	$('#odf_close').live('click', odfViewer.onClose);
 +});
diff --cc apps/documents/lib/db/op.php
index 280b43c,0000000..4974adc
mode 100644,000000..100644
--- a/apps/documents/lib/db/op.php
+++ b/apps/documents/lib/db/op.php
@@@ -1,117 -1,0 +1,139 @@@
 +<?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 Db_Op extends Db {
 +
 +	const DB_TABLE = '`*PREFIX*documents_op`';
 +	
 +	protected $tableName = '`*PREFIX*documents_op`';
 +	
 +	protected $insertStatement = 'INSERT INTO `*PREFIX*documents_op` (`es_id`, `member`, `opspec`) VALUES (?, ?, ?)';
 +
 +	public static function addOpsArray($esId, $memberId, $ops){
 +		$lastSeq = "";
 +		$opObj = new Db_Op();
 +		foreach ($ops as $op) {
 +			$opObj->setData(array(
 +				$esId, 
 +				$memberId, 
 +				json_encode($op)
 +			));
 +			$opObj->insert();
 +			$lastSeq = $opObj->getLastInsertId();
 +		}
 +		return $lastSeq;
 +	}
 +	
 +	/**
 +	 * @returns "" when there are no Ops, or the seq of the last Op
 +	 */
 +	public function getHeadSeq($esId){
 +		$query = \OCP\DB::prepare('
 +			SELECT `seq`
 +			FROM ' . $this->tableName . '
 +			WHERE `es_id`=?
 +			ORDER BY `seq` DESC
 +			', 1);
 +		$result = $query->execute(array(
 +				$esId
 +			))
 +			->fetchOne()	
 +		;
 +		return !$result ? "" : $result;
 +	}
 +	
 +	public function getOpsAfterJson($esId, $seq){
 +		$ops = $this->getOpsAfter($esId, $seq);
 +		if (!is_array($ops)){
 +			$ops = array();
 +		}
 +		$ops =  array_map(
 +				function($x){
 +					$decoded = json_decode($x['opspec'], true);
 +					$decoded['memberid'] = strval($decoded['memberid']);
 +					return $decoded;
 +				}, 
 +				$ops
 +		);
 +		return $ops;
 +	}
 +	
 +	public function getOpsAfter($esId, $seq){
 +		if ($seq == ""){
 +			$seq = -1;
 +		}
 +		$query = \OCP\DB::prepare('
 +			SELECT `opspec`
 +			FROM ' . self::DB_TABLE . '
 +			WHERE `es_id`=?
 +				AND `seq`>?
 +			ORDER BY `seq` ASC
 +			');
 +		$result = $query->execute(array($esId, $seq));
 +		return $result->fetchAll();
 +	}
 +
 +	public function removeCursor($esId, $memberId){
- 		$op = '{"optype":"RemoveCursor","memberid":"'. $memberId .'","reason":"server-idle","timestamp":'. time() .'}';
- 		$this->insertOp($esId, $op);
++		if ($this->hasAddCursor($esId, $memberId)){
++			$op = '{"optype":"RemoveCursor","memberid":"'. $memberId .'","reason":"server-idle","timestamp":'. time() .'}';
++			$this->insertOp($esId, $op);
++		}
 +	}
 +	
 +	public function addMember($esId, $memberId, $fullName, $color, $imageUrl){
 +		$op = '{"optype":"AddMember","memberid":"'. $memberId .'","timestamp":"'. time() .'", "setProperties":{"fullName":"'. $fullName .'","color":"'. $color .'","imageUrl":"'. $imageUrl .'"}}';
 +		$this->insertOp($esId, $op);
 +	}
 +	
 +	public function removeMember($esId, $memberId){
- 		$op ='{"optype":"RemoveMember","memberid":"'. $memberId .'","timestamp":'. time() .'}';
- 		$this->insertOp($esId, $op);
++		if ($this->hasAddMember($esId, $memberId)){
++			$op ='{"optype":"RemoveMember","memberid":"'. $memberId .'","timestamp":'. time() .'}';
++			$this->insertOp($esId, $op);
++		}
 +	}
 +	
 +	public function updateMember($esId, $memberId, $fullName, $color, $imageUrl){
 +		//TODO: Follow the spec https://github.com/kogmbh/WebODF/blob/master/webodf/lib/ops/OpUpdateMember.js#L95
 +		$op = '{"optype":"UpdateMember","memberid":"'. $memberId .'","fullName":"'. $fullName .'","color":"'. $color .'","imageUrl":"'. $imageUrl .'","timestamp":'. time() .'}'
 +		;
 +		$this->insertOp($esId, $op);
 +	}
 +	
 +	protected function insertOp($esId, $op){
 +		$op = new Db_Op(array(
 +			$esId, 
 +			0,
 +			$op
 +		));
 +		$op->insert();
 +	}
 +	
++	protected function hasAddMember($esId, $memberId){
++		$ops = $this->execute(
++			'SELECT * FROM ' . $this->tableName . ' WHERE `es_id`=? AND `opspec` LIKE \'%"AddMember","memberid":"' . $memberId .'"%\'',
++			array($esId)
++		);
++		$result = $ops->fetchAll();
++		return is_array($result) && count($result)>0;
++	}
++	
++	protected function hasAddCursor($esId, $memberId){
++		$ops = $this->execute(
++			'SELECT * FROM ' . $this->tableName . ' WHERE `es_id`=? AND `opspec` LIKE \'%"AddCursor","memberid":"' . $memberId .'"%\'',
++			array($esId)
++		);
++		$result = $ops->fetchAll();
++		return is_array($result) && count($result)>0;
++	}
++	
 +}
diff --cc apps/documents/lib/file.php
index 265e6c7,0000000..af6fc28
mode 100644,000000..100644
--- a/apps/documents/lib/file.php
+++ b/apps/documents/lib/file.php
@@@ -1,263 -1,0 +1,275 @@@
 +<?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;
 +	}
 +
 +	/**
++	 * Rename this file to the given name
++	 * @param string $newName name to give (without path)
++	 * @return boolean true if rename succeeded, false otherwise
++	 */
++	public function renameTo($newName) {
++		list($owner, $path) = $this->getOwnerViewAndPath();
++		$newPath = dirname($path) . '/' . $newName;
++		return \OC\Files\Filesystem::rename($path, $newPath);
++	}
++
++	/**
 +	 * 
 +	 * @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);
++			$path = preg_replace('|^files|', '', $this->path);
 +			$view = new View('/' . $this->owner . '/files');
 +		} else {
++			$path = $this->path;
 +			$view = new View('/' . $this->owner);
 +		}
 +		
- 		if (!$view->file_exists($this->path)){
++		if (!$view->file_exists($path)){
 +			throw new \Exception($this->path . ' doesn\'t exist');
 +		}
 +		
- 		return array($view, $this->path);
++		return array($view, $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/src/patches/MemberListView-OCavatar.patch
index eb7b413,0000000..3320fc1
mode 100644,000000..100644
--- a/apps/documents/src/patches/MemberListView-OCavatar.patch
+++ b/apps/documents/src/patches/MemberListView-OCavatar.patch
@@@ -1,32 -1,0 +1,34 @@@
- diff --git a/js/3rdparty/webodf/editor/MemberListView.js b/js/3rdparty/webodf/editor/MemberListView.js
- index cbab8ec..f51aec3 100644
- --- a/js/3rdparty/webodf/editor/MemberListView.js
- +++ b/js/3rdparty/webodf/editor/MemberListView.js
- @@ -73,6 +73,9 @@ define("webodf/editor/MemberListView",
++diff --git b/js/3rdparty/webodf/editor/MemberListView.js a/js/3rdparty/webodf/editor/MemberListView.js
++index 83074ba..9f604c7 100644
++--- b/js/3rdparty/webodf/editor/MemberListView.js
+++++ a/js/3rdparty/webodf/editor/MemberListView.js
++@@ -76,6 +76,11 @@ define("webodf/editor/MemberListView",
 +                             node.src = memberDetails.imageUrl;
 +                             // update border color
 +                             node.style.borderColor = memberDetails.color;
 ++						} else if (node.localName === "span" && memberDetails.imageUrl){
- +							$(node).avatar(memberDetails.imageUrl, 60);
+++							try {
+++								$(node).avatar(memberDetails.imageUrl, 60);
+++							} catch (e){}
 ++							node.style.borderColor = memberDetails.color;
 +                         } else if (node.localName === "div") {
-                              node.setAttribute('fullname', memberDetails.fullname);
++                             node.setAttribute('fullname', memberDetails.fullName);
 +                         }
- @@ -92,7 +95,7 @@ define("webodf/editor/MemberListView",
++@@ -95,7 +100,7 @@ define("webodf/editor/MemberListView",
 +             var doc = memberListDiv.ownerDocument,
 +                 htmlns = doc.documentElement.namespaceURI,
 +                 avatarDiv = doc.createElementNS(htmlns, "div"),
 +-                imageElement = doc.createElement("img"),
 ++                imageElement = doc.createElement("span"),
 +                 fullnameNode = doc.createElement("div");
 + 
 +             avatarDiv.className = "memberListButton";
- @@ -110,7 +113,7 @@ define("webodf/editor/MemberListView",
++@@ -113,7 +118,7 @@ define("webodf/editor/MemberListView",
 +             avatarDiv.onclick = function () {
 +                 var caret = editorSession.sessionView.getCaret(memberId);
 +                 if (caret) {
 +-                    caret.toggleHandleVisibility();
 ++                    //caret.toggleHandleVisibility();
 +                 }
 +             };
 +             memberListDiv.appendChild(avatarDiv);
diff --cc apps/documents/src/updateWebODF.sh
index 212ecea,0000000..a91b658
mode 100644,000000..100644
--- a/apps/documents/src/updateWebODF.sh
+++ b/apps/documents/src/updateWebODF.sh
@@@ -1,41 -1,0 +1,42 @@@
 +#!/bin/bash
 +# Copies the needed files from the build dir of the WebODF pullbox branch
++#
++# Prepare the webodf build dir by calling: make webodf-debug.js-target editor-compiled.js-target
 +
 +WEBODF_BUILDDIR=${1%/}
 +
 +if [ ! -d "$WEBODF_BUILDDIR" ]; then
 +   echo "Provide the toplevel build directory of WebODF pullbox branch."
 +        exit 1
 +fi
 +if [ ! -e "README.md" ]; then
 +   echo "Call me in the toplevel dir of OwnCloud Documents."
 +        exit 1
 +fi
 +
 +# copy files
 +
 +# webodf.js
 +cp "$WEBODF_BUILDDIR"/webodf/webodf.js ./js/3rdparty/webodf
 +cp "$WEBODF_BUILDDIR"/webodf/webodf-debug.js ./js/3rdparty/webodf
 +# dojo
 +cp "$WEBODF_BUILDDIR"/programs/editor/dojo-amalgamation.js ./js/3rdparty/webodf
 +
 +# Tools, Editor, EditorSession, MemberListView:
 +cp "$WEBODF_BUILDDIR"/programs/editor/{Tools,Editor,EditorSession,MemberListView}.js ./js/3rdparty/webodf/editor
 +cp "$WEBODF_BUILDDIR"/programs/editor/server/pullbox/* ./js/3rdparty/webodf/editor/server/pullbox -R
 +cp "$WEBODF_BUILDDIR"/programs/editor/server/ServerFactory.js ./js/3rdparty/webodf/editor/server -R
 +cp "$WEBODF_BUILDDIR"/programs/editor/widgets ./js/3rdparty/webodf/editor -R
- cp "$WEBODF_BUILDDIR"/programs/editor/nls ./js/3rdparty/webodf/editor -R
 +cp "$WEBODF_BUILDDIR"/programs/editor/editor.css ./css/3rdparty/webodf
 +
 +# patches against upstream
 +patch -p1 -i src/patches/fontsCssPath.patch
 +patch -p1 -i src/patches/hideCaretAvatar.patch
 +patch -p1 -i src/patches/MemberListView-OCavatar.patch
 +patch -p1 -i src/patches/keepBodyStyle.patch
 +
 +
 +# files which need to be adapted manually:
 +# "$WEBODF_BUILDDIR"/programs/editor/dojo-deps/src/app/resources/app.css  -> ./css/3rdparty/webodf/dojo-app.css
 +# dojo-app.css has other paths then upstream, needs to be manually adapted to changes
 +# also is dojo.css is not imported here, other than in upstream
diff --cc apps/documents/templates/documents.php
index 0b461a7,0000000..21edb4e
mode 100644,000000..100644
--- a/apps/documents/templates/documents.php
+++ b/apps/documents/templates/documents.php
@@@ -1,38 -1,0 +1,38 @@@
 +<div id="documents-content">
 +	<ul class="documentslist">
 +		<li class="add-document">
 +			<a class="add svg" target="_blank" href="">
 +				<label><?php p($l->t('New document')) ?></label>
 +			</a> 
 +			<div id="upload" title="<?php p($l->t('Upload') . ' max. '.$_['uploadMaxHumanFilesize']) ?>">
 +				<form data-upload-id="1"
 +					  id="data-upload-form"
 +					  class="file_upload_form"
 +					  action="<?php print_unescaped(OCP\Util::linkTo('files', 'ajax/upload.php')); ?>"
 +					  method="post"
 +					  enctype="multipart/form-data"
 +					  target="file_upload_target_1">
 +					<?php if($_['uploadMaxFilesize'] >= 0):?>
 +					<input type="hidden" name="MAX_FILE_SIZE" id="max_upload"
 +						   value="<?php p($_['uploadMaxFilesize']) ?>" />
 +					<?php endif;?>
 +					<!-- Send the requesttoken, this is needed for older IE versions
 +						 because they don't send the CSRF token via HTTP header in this case -->
 +					<input type="hidden" name="requesttoken" value="<?php p($_['requesttoken']) ?>" id="requesttoken" />
 +					<input type="hidden" class="max_human_file_size"
 +						   value="(max <?php p($_['uploadMaxHumanFilesize']); ?>)" />
 +					<input type="hidden" name="dir" value="<?php p($_['savePath']) ?>" id="dir" />
 +					<input type="file" id="file_upload_start" name='files[]' />
 +					<a href="#" class="upload svg">
 +					<label><?php p($l->t('Upload')) ?></label></a>
 +				</form>
 +			</div>
 +		</li>
- 		<li class="progress"> </li>
++		<li class="progress"><div><?php p($l->t('Loading documents...')); ?></div></li>
 +		<li class="document template" data-id="" style="display:none;">
 +			<a target="_blank" href=""><label></label></a>
 +		</li>
 +	</ul>
 +</div>
 +<input type="hidden" id="webodf-unstable" value="<?php p($_['useUnstable']) ?>" />
 +<input type="hidden" name="allowShareWithLink" id="allowShareWithLink" value="<?php p($_['allowShareWithLink']) ?>" />
diff --cc apps/files_texteditor/css/style.css
index c3ddc18,0000000..5afa94b
mode 100644,000000..100644
--- a/apps/files_texteditor/css/style.css
+++ b/apps/files_texteditor/css/style.css
@@@ -1,36 -1,0 +1,37 @@@
 +.ie8 #editor_container div{
 +	/* override core style.css font-size:100% that messes up the editor in IE8 */
 +	font-size: 12px !important;
 +}
 +
 +#editor_container #editor {
 +	position: relative;
 +	display: block;
 +	top: 0;
 +	left: 0;
 +	z-index: 20;
 +	height: 100%;
 +	width: 100%;
 +}
 +
 +#editor_container{
 +	position: absolute;
 +	display: block;
 +	top: 0;
 +	left: 0;
 +	padding-top: 44px;
 +	height: 100%;
 +	width: 100%;
++	-moz-box-sizing: border-box;
 +	box-sizing: border-box;
 +}
 +
 +#editor_save {
 +	margin-left: 7px;
 +	margin-right: 20px;
 +	float: left;
 +}
 +
 +#editor_close {
 +	float: right;
 +	margin-right: 9px;
 +}
diff --cc apps/gallery/js/slideshow.js
index 30baf2a,0000000..000f679
mode 100644,000000..100644
--- a/apps/gallery/js/slideshow.js
+++ b/apps/gallery/js/slideshow.js
@@@ -1,350 -1,0 +1,356 @@@
 +jQuery.fn.slideShow = function (container, start, options) {
 +	var i, images = [], settings;
 +	start = start || 0;
 +	settings = jQuery.extend({
 +		'interval': 5000,
 +		'play'    : false,
 +		'maxScale': 2
 +	}, options);
 +	if (settings.play){
 +		$('#slideshow').children('.play').hide();
 +		$('#slideshow').children('.pause').show();
 +	}
 +	else{
 +		$('#slideshow').children('.play').show();
 +		$('#slideshow').children('.pause').hide();
 +	}
 +	jQuery.fn.slideShow.container = container;
 +	jQuery.fn.slideShow.settings = settings;
 +	jQuery.fn.slideShow.current = start;
 +	for (i = 0; i < this.length; i++) {
 +		var imageLink = this[i];
 +		images.push(imageLink.imageUrl || imageLink.href);
 +	}
 +	container.children('img').remove();
 +	container.show();
 +	jQuery.fn.slideShow.images = images;
 +	jQuery.fn.slideShow.cache = [];
 +	jQuery.fn.slideShow.showImage(images[start], images[start + 1]);
 +	jQuery.fn.slideShow.progressBar = container.find('.progress');
 +
- 	// hide arrows when only one pic
- 	$('#slideshow .next, #slideshow .previous').toggle(jQuery.fn.slideShow.images.length > 1);
++	// hide arrows and play/pause when only one pic
++	$('#slideshow').find('.next, .previous').toggle(images.length > 1);
++	if (images.length === 1) {
++		// note: only handling hide case here as we don't want to
++		// re-show the buttons that might have been hidden by
++		// the settings.play condition above
++		$('#slideshow').find('.play, .pause').hide();
++	}
 +
 +	jQuery(window).resize(function () {
 +		jQuery.fn.slideShow.loadImage(jQuery.fn.slideShow.images[jQuery.fn.slideShow.current]).then(function (image) {
 +			jQuery.fn.slideShow.fitImage(container, image);
 +		});
 +	});
 +	return jQuery.fn.slideShow;
 +};
 +
 +jQuery.fn.slideShow.progressBar = null;
 +
 +jQuery.fn.slideShow.loadImage = function (url) {
 +	if (!jQuery.fn.slideShow.cache[url]) {
 +		jQuery.fn.slideShow.cache[url] = new jQuery.Deferred();
 +		var image = new Image();
 +		jQuery.fn.slideShow.cache[url].fail(function (u) {
 +			image = false;
 +			jQuery.fn.slideShow.cache[url] = false;
 +		});
 +		image.onload = function () {
 +			if (image) {
 +				image.natWidth = image.width;
 +				image.natHeight = image.height;
 +			}
 +			if (jQuery.fn.slideShow.cache[url]) {
 +				jQuery.fn.slideShow.cache[url].resolve(image);
 +			}
 +		};
 +		image.onerror = function () {
 +			if (jQuery.fn.slideShow.cache[url]) {
 +				jQuery.fn.slideShow.cache[url].reject(url);
 +			}
 +		};
 +		image.src = url;
 +	}
 +	return jQuery.fn.slideShow.cache[url];
 +};
 +
 +jQuery.fn.slideShow.fitImage = function (container, image) {
 +	var ratio = image.natWidth / image.natHeight,
 +		screenRatio = container.width() / container.height(),
 +		width = null, height = null, top = null;
 +	if (ratio > screenRatio) {
 +		if (container.width() > image.natWidth * jQuery.fn.slideShow.settings.maxScale) {
 +			top = ((container.height() - image.natHeight) / 2) + 'px';
 +			height = image.natHeight + 'px';
 +			width = image.natWidth + 'px';
 +		} else {
 +			width = container.width() + 'px';
 +			height = (container.width() / ratio) + 'px';
 +			top = ((container.height() - (container.width() / ratio)) / 2) + 'px';
 +		}
 +	} else {
 +		if (container.height() > image.natHeight * jQuery.fn.slideShow.settings.maxScale) {
 +			top = ((container.height() - image.natHeight) / 2) + 'px';
 +			height = image.natHeight + 'px';
 +			width = image.natWidth + 'px';
 +		} else {
 +			top = 0;
 +			height = container.height() + 'px';
 +			width = (container.height() * ratio) + "px";
 +		}
 +	}
 +	jQuery(image).css({
 +		top   : top,
 +		width : width,
 +		height: height
 +	});
 +};
 +
 +jQuery.fn.slideShow.showImage = function (url, preloadUrl) {
 +	var container = jQuery.fn.slideShow.container;
 +
 +	container.css('background-position', 'center');
 +	jQuery.fn.slideShow.loadImage(url).then(function (image) {
 +		container.css('background-position', '-10000px 0');
 +		if (url === jQuery.fn.slideShow.images[jQuery.fn.slideShow.current]) {
 +			container.children('img').remove();
 +			container.append(image);
 +			jQuery.fn.slideShow.fitImage(container, image);
 +			if (jQuery.fn.slideShow.settings.play) {
 +				jQuery.fn.slideShow.setTimeout();
 +			}
 +			if (preloadUrl) {
 +				jQuery.fn.slideShow.loadImage(preloadUrl);
 +			}
 +		}
 +	});
 +};
 +
 +jQuery.fn.slideShow.play = function () {
 +	if (jQuery.fn.slideShow.settings) {
 +		jQuery.fn.slideShow.settings.play = true;
 +		jQuery.fn.slideShow.setTimeout();
 +	}
 +};
 +
 +jQuery.fn.slideShow.pause = function () {
 +	if (jQuery.fn.slideShow.settings) {
 +		jQuery.fn.slideShow.settings.play = false;
 +		jQuery.fn.slideShow.clearTimeout();
 +	}
 +};
 +
 +jQuery.fn.slideShow.setTimeout = function () {
 +	jQuery.fn.slideShow.clearTimeout();
 +	jQuery.fn.slideShow.timeout = setTimeout(jQuery.fn.slideShow.next, jQuery.fn.slideShow.settings.interval);
 +	jQuery.fn.slideShow.progressBar.stop();
 +	jQuery.fn.slideShow.progressBar.css('height', '6px');
 +	jQuery.fn.slideShow.progressBar.animate({'height': '26px'}, jQuery.fn.slideShow.settings.interval, 'linear');
 +};
 +
 +jQuery.fn.slideShow.clearTimeout = function () {
 +	if (jQuery.fn.slideShow.timeout) {
 +		clearTimeout(jQuery.fn.slideShow.timeout);
 +	}
 +	jQuery.fn.slideShow.progressBar.stop();
 +	jQuery.fn.slideShow.progressBar.css('height', '6px');
 +	jQuery.fn.slideShow.timeout = 0;
 +};
 +
 +jQuery.fn.slideShow.next = function () {
 +	if (jQuery.fn.slideShow.container) {
 +		jQuery.fn.slideShow.current++;
 +		if (jQuery.fn.slideShow.current >= jQuery.fn.slideShow.images.length) {
 +			jQuery.fn.slideShow.current = 0;
 +		}
 +		var image = jQuery.fn.slideShow.images[jQuery.fn.slideShow.current],
 +			nextImage = jQuery.fn.slideShow.images[(jQuery.fn.slideShow.current + 1) % jQuery.fn.slideShow.images.length];
 +		jQuery.fn.slideShow.showImage(image, nextImage);
 +	}
 +};
 +
 +jQuery.fn.slideShow.previous = function () {
 +	if (jQuery.fn.slideShow.container) {
 +		jQuery.fn.slideShow.current--;
 +		if (jQuery.fn.slideShow.current < 0) {
 +			jQuery.fn.slideShow.current = jQuery.fn.slideShow.images.length - 1;
 +		}
 +		var image = jQuery.fn.slideShow.images[jQuery.fn.slideShow.current],
 +			previousImage = jQuery.fn.slideShow.images[(jQuery.fn.slideShow.current - 1 + jQuery.fn.slideShow.images.length) % jQuery.fn.slideShow.images.length];
 +		jQuery.fn.slideShow.showImage(image, previousImage);
 +	}
 +};
 +
 +jQuery.fn.slideShow.stop = function () {
 +	if (jQuery.fn.slideShow.container) {
 +		jQuery.fn.slideShow.clearTimeout();
 +		jQuery.fn.slideShow.container.hide();
 +		jQuery.fn.slideShow.container = null;
 +		if (jQuery.fn.slideShow.onstop) {
 +			jQuery.fn.slideShow.onstop();
 +		}
 +	}
 +};
 +
 +jQuery.fn.slideShow.hideImage = function () {
 +	var container = jQuery.fn.slideShow.container;
 +	if (container) {
 +		container.children('img').remove();
 +	}
 +};
 +
 +jQuery.fn.slideShow.onstop = null;
 +
 +
 +Slideshow = {};
 +Slideshow.start = function (images, start, options) {
 +
 +	var content = $('#content');
 +	start = start || 0;
 +	Thumbnail.concurrent = 1; //make sure we can load the image and doesn't get blocked by loading thumbnail
 +	if (content.is(":visible") && typeof Gallery !== 'undefined') {
 +		Gallery.scrollLocation = $(window).scrollTop();
 +	}
 +	images.slideShow($('#slideshow'), start, options);
 +	content.hide();
 +};
 +
 +Slideshow.end = function () {
 +	jQuery.fn.slideShow.stop();
 +};
 +
 +Slideshow.next = function (event) {
 +	if (event) {
 +		event.stopPropagation();
 +	}
 +	jQuery.fn.slideShow.hideImage();
 +	jQuery.fn.slideShow.next();
 +};
 +
 +Slideshow.previous = function (event) {
 +	if (event) {
 +		event.stopPropagation();
 +	}
 +	jQuery.fn.slideShow.hideImage();
 +	jQuery.fn.slideShow.previous();
 +};
 +
 +Slideshow.pause = function (event) {
 +	if (event) {
 +		event.stopPropagation();
 +	}
 +	$('#slideshow').children('.play').show();
 +	$('#slideshow').children('.pause').hide();
 +	Slideshow.playPause.playing = false;
 +	jQuery.fn.slideShow.pause();
 +};
 +
 +Slideshow.play = function (event) {
 +	if (event) {
 +		event.stopPropagation();
 +	}
 +	$('#slideshow').children('.play').hide();
 +	$('#slideshow').children('.pause').show();
 +	Slideshow.playPause.playing = true;
 +	jQuery.fn.slideShow.play();
 +};
 +Slideshow.playPause = function () {
 +	if (Slideshow.playPause.playing) {
 +		Slideshow.pause();
 +	} else {
 +		Slideshow.play();
 +	}
 +};
 +Slideshow.playPause.playing = false;
 +Slideshow._getSlideshowTemplate = function () {
 +	var defer = $.Deferred();
 +	if (!this.$slideshowTemplate) {
 +		var self = this;
 +		$.get(OC.filePath('gallery', 'templates', 'slideshow.html'), function (tmpl) {
 +			self.$slideshowTemplate = $(tmpl);
 +			defer.resolve(self.$slideshowTemplate);
 +		})
 +			.fail(function () {
 +				defer.reject();
 +			});
 +	} else {
 +		defer.resolve(this.$slideshowTemplate);
 +	}
 +	return defer.promise();
 +};
 +
 +$(document).ready(function () {
 +	if ($('#body-login').length > 0) {
 +		return true; //deactivate slideshow on login page
 +	}
 +
 +	//close slideshow on esc
 +	$(document).keyup(function (e) {
 +		if (e.keyCode === 27) { // esc
 +			Slideshow.end();
 +		} else if (e.keyCode === 37) { // left
 +			Slideshow.previous();
 +		} else if (e.keyCode === 39) { // right
 +			Slideshow.next();
 +		} else if (e.keyCode === 32) { // space
 +			Slideshow.playPause();
 +		}
 +	});
 +
 +	$.when(Slideshow._getSlideshowTemplate()).then(function ($tmpl) {
 +		$('body').append($tmpl); //move the slideshow outside the content so we can hide the content
 +
 +		if (!SVGSupport()) { //replace all svg images with png images for browser that dont support svg
 +			replaceSVG();
 +		}
 +
 +		var slideshow = $('#slideshow');
 +		slideshow.children('.next').click(Slideshow.next);
 +		slideshow.children('.previous').click(Slideshow.previous);
 +		slideshow.children('.exit').click(jQuery.fn.slideShow.stop);
 +		slideshow.children('.pause').click(Slideshow.pause);
 +		slideshow.children('.play').click(Slideshow.play);
 +		slideshow.click(Slideshow.next);
 +
 +		if ($.fn.mousewheel) {
 +			slideshow.bind('mousewheel.fb', function (e, delta) {
 +				e.preventDefault();
 +				if ($(e.target).get(0).clientHeight === 0 || $(e.target).get(0).scrollHeight === $(e.target).get(0).clientHeight) {
 +					if (delta > 0) {
 +						Slideshow.previous();
 +					} else {
 +						Slideshow.next();
 +					}
 +				}
 +			});
 +		}
 +	})
 +		.fail(function () {
 +			alert(t('core', 'Error loading slideshow template'));
 +		});
 +
 +
 +	if (typeof FileActions !== 'undefined' && typeof Slideshow !== 'undefined' && $('#filesApp').val()) {
 +		FileActions.register('image', 'View', OC.PERMISSION_READ, '', function (filename) {
 +			var images = $('#fileList tr[data-mime^="image"] a.name');
 +			var dir = FileList.getCurrentDirectory() + '/';
 +			var user = OC.currentUser;
 +			if (!user) {
 +				user = $('#sharingToken').val();
 +			}
 +			var start = 0;
 +			$.each(images, function (i, e) {
 +				var tr = $(e).closest('tr');
 +				var imageFile = tr.data('file');
 +				if (imageFile === filename) {
 +					start = i;
 +				}
 +				// use gallery URL instead of download URL
 +				e.imageUrl = OC.linkTo('gallery', 'ajax/image.php') +
 +					'?file=' + encodeURIComponent(user + dir + imageFile);
 +			});
 +			images.slideShow($('#slideshow'), start);
 +		});
 +		FileActions.setDefault('image', 'View');
 +	}
 +});
diff --cc core/doc/user/_sources/files/encryption.txt
index 0968a53,0000000..8d8cba3
mode 100644,000000..100644
--- a/core/doc/user/_sources/files/encryption.txt
+++ b/core/doc/user/_sources/files/encryption.txt
@@@ -1,69 -1,0 +1,65 @@@
 +Files Encryption
 +================
 +
 +ownCloud ships a encryption app, which allows to encrypt all files stored in
 +your ownCloud. Once the encryption app was enabled by the admin all your files
 +will be encrypted automatically. Encryption and decryption always happens
 +server-side. This enables the user to continue to use all the other apps to
 +view and edit his data. But this also means that the server administrator could
 +intercept your data. Server-Side encryption is especially interesting if you
 +use external storages. This way you can make sure that the storage provider is
 +not able to read your data.
 +
 +Please remember. Once the encryption app is enabled you need your log-in
 +password to decrypt and access your data. By default your data will be lost if
 +you loss your log-in pasword. If you want to protect yourself against password
 +loss store your log-in password on a secure place or enable the recovery key
 +as described below.
 +
 +What gets encrypted
 +-------------------
 +
 +The current version encrypts all your files stored in ownCloud.
 +
 +At the moment we don't encrypt:
 +
- - old versions (versions created before the encryption app was enabled)
 +- old files in the trash bin (files which were deleted before the encryption app was enabled)
- - image thumbnails from the gallery app
++- image thumbnails from the gallery app and previews from the files app
 +- search index from the full text search app
 +
 +All this data is stored directly on your ownCloud server, so you don't have to worry to expose
 +your data to a third party storage provider.
 +
 +Decrypt your data again
 +-----------------------
 +
- Corrently there is no way to decrypt your files directly on the server if you decide to stop
- using the encryption app. The only way to get a comlete copy of your unencrypted data is
- to download/sync all files as long as the encryption app is enabled. After the encryption
- app was disabled you can upload your unencrypted data again.
++If the encryption app was disabled users can decrypt their files again in their
++personal settings. After this was done they can continue to use their ownCloud
++without encryption.
 +
- It is already planned to add a option to switch from encrypted to unencrypted files
- directly on the server.
 +
 +Settings
 +--------
 +
 +Once the encryption app is enabled you will find some additional settings on
 +your personal settings page.
 +
 +Recovery Key
 +~~~~~~~~~~~~
 +
 +If the admin enabled the recovery-key you can decide by your own if you
 +want to use this feature for your account. If you enable "Password recovery"
 +the admin will be able to read your data with a special password. This allows
 +him to recover your files in case of password loss. If the recovery-key is not
 +enabled than there is no way to restore your files if you loss your log-in
 +password.
 +
 +Change Private Key Password
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~
 +
 +This option will be only available if your log-in password but not your
 +encryption password was changed by your admin. This can happen if your ownCloud
 +provider uses a external user back-end, e.g. LDAP, and changed your log-in
 +password there. In this case you can set your encryption password to your new
 +log-in password by providing your old and new log-in password. The encryption
 +app only works if log-in password and encryption password is identical.
diff --cc core/doc/user/files/encryption.html
index dadede6,0000000..ae364b1
mode 100644,000000..100644
--- a/core/doc/user/files/encryption.html
+++ b/core/doc/user/files/encryption.html
@@@ -1,221 -1,0 +1,217 @@@
 +
 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 +  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 +
 +
 +<html xmlns="http://www.w3.org/1999/xhtml">
 +  <head>
 +    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 +    
 +    <title>Files Encryption — ownCloud User Manual 6.0 documentation</title>
 +    
 +    <link rel="stylesheet" href="../_static/style.css" type="text/css" />
 +    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
 +    <link rel="stylesheet" href="../_static/style.css" type="text/css" />
 +    <link rel="stylesheet" href="../_static/bootstrap-sphinx.css" type="text/css" />
 +    
 +    <script type="text/javascript">
 +      var DOCUMENTATION_OPTIONS = {
 +        URL_ROOT:    '../',
 +        VERSION:     '6.0',
 +        COLLAPSE_INDEX: false,
 +        FILE_SUFFIX: '.html',
 +        HAS_SOURCE:  true
 +      };
 +    </script>
 +    <script type="text/javascript" src="../_static/jquery.js"></script>
 +    <script type="text/javascript" src="../_static/underscore.js"></script>
 +    <script type="text/javascript" src="../_static/doctools.js"></script>
 +    <script type="text/javascript" src="../_static/bootstrap.js"></script>
 +    <link rel="top" title="ownCloud User Manual 6.0 documentation" href="../index.html" />
 +    <link rel="up" title="Files & Synchronization" href="index.html" />
 +    <link rel="next" title="Storage Quota" href="quota.html" />
 +    <link rel="prev" title="Desktop Synchronisation" href="sync.html" />
 +<script type="text/javascript">
 +(function () {
 +  /**
 +   * Patch TOC list.
 +   *
 +   * Will mutate the underlying span to have a correct ul for nav.
 +   *
 +   * @param $span: Span containing nested UL's to mutate.
 +   * @param minLevel: Starting level for nested lists. (1: global, 2: local).
 +   */
 +  var patchToc = function ($ul, minLevel) {
 +    var findA;
 +
 +    // Find all a "internal" tags, traversing recursively.
 +    findA = function ($elem, level) {
 +      var level = level || 0,
 +        $items = $elem.find("> li > a.internal, > ul, > li > ul");
 +
 +      // Iterate everything in order.
 +      $items.each(function (index, item) {
 +        var $item = $(item),
 +          tag = item.tagName.toLowerCase(),
 +          pad = 15 + ((level - minLevel) * 10);
 +
 +        if (tag === 'a' && level >= minLevel) {
 +          // Add to existing padding.
 +          $item.css('padding-left', pad + "px");
 +          console.log(level, $item, 'padding-left', pad + "px");
 +        } else if (tag === 'ul') {
 +          // Recurse.
 +          findA($item, level + 1);
 +        }
 +      });
 +    };
 +
 +    console.log("HERE");
 +    findA($ul);
 +  };
 +
 +  $(document).ready(function () {
 +    // Add styling, structure to TOC's.
 +    $(".dropdown-menu").each(function () {
 +      $(this).find("ul").each(function (index, item){
 +        var $item = $(item);
 +        $item.addClass('unstyled');
 +      });
 +      $(this).find("li").each(function () {
 +        $(this).parent().append(this);
 +      });
 +    });
 +
 +    // Patch in level.
 +    patchToc($("ul.globaltoc"), 2);
 +    patchToc($("ul.localtoc"), 2);
 +
 +    // Enable dropdown.
 +    $('.dropdown-toggle').dropdown();
 +  });
 +}());
 +</script>
 +
 +  </head>
 +  <body>
 +  
 +
 +<div class="container">
 +  <div class="content">
 +    <div class="page-header">
 +      <h1><a href="../contents.html">ownCloud User Manual</a></h1>
 +
 +    </div>
 +    
 +			<div class="row">
 +				<div class="span3">
 +					<div class="sidebar">
 +						<div class="well">
 +							<div class="menu-support-container">
 +								<ul id="menu-support" class="menu">
 +									<ul>
 +										<li><a href="../contents.html">Overview</a></li>
 +									</ul>
 +                  <ul>
 +<li class="toctree-l1"><a class="reference internal" href="../index.html">User Documentation</a></li>
 +</ul>
 +<ul class="current">
 +<li class="toctree-l1"><a class="reference internal" href="../webinterface.html">The ownCloud Web Interface</a></li>
 +<li class="toctree-l1 current"><a class="reference internal" href="index.html">Files & Synchronization</a><ul class="current">
 +<li class="toctree-l2"><a class="reference internal" href="files.html">Accessing your Files (WebDav)</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="versioncontrol.html">Version Control</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="deletedfiles.html">Deleted Files</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="sync.html">Desktop Synchronisation</a></li>
 +<li class="toctree-l2 current"><a class="current reference internal" href="">Files Encryption</a><ul>
 +<li class="toctree-l3"><a class="reference internal" href="#what-gets-encrypted">What gets encrypted</a></li>
 +<li class="toctree-l3"><a class="reference internal" href="#decrypt-your-data-again">Decrypt your data again</a></li>
 +<li class="toctree-l3"><a class="reference internal" href="#settings">Settings</a></li>
 +</ul>
 +</li>
 +<li class="toctree-l2"><a class="reference internal" href="quota.html">Storage Quota</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="configuring_big_file_upload.html">Big Files</a></li>
 +</ul>
 +</li>
 +<li class="toctree-l1"><a class="reference internal" href="../pim/index.html">Contacts & Calendar</a></li>
 +<li class="toctree-l1"><a class="reference internal" href="../bookmarks.html">Using the Bookmarks App</a></li>
 +<li class="toctree-l1"><a class="reference internal" href="../migration.html">User Account Migration</a></li>
 +<li class="toctree-l1"><a class="reference internal" href="../external_storage/google_drive.html">External storage</a></li>
 +</ul>
 +
 +								</ul>
 +							</div>
 +						</div>
 +					</div>
 +				</div>
 +        
 +
 +				<div class="span9">
 +					<div class="page-content">
 +						
 +  <div class="section" id="files-encryption">
 +<h1>Files Encryption<a class="headerlink" href="#files-encryption" title="Permalink to this headline">¶</a></h1>
 +<p>ownCloud ships a encryption app, which allows to encrypt all files stored in
 +your ownCloud. Once the encryption app was enabled by the admin all your files
 +will be encrypted automatically. Encryption and decryption always happens
 +server-side. This enables the user to continue to use all the other apps to
 +view and edit his data. But this also means that the server administrator could
 +intercept your data. Server-Side encryption is especially interesting if you
 +use external storages. This way you can make sure that the storage provider is
 +not able to read your data.</p>
 +<p>Please remember. Once the encryption app is enabled you need your log-in
 +password to decrypt and access your data. By default your data will be lost if
 +you loss your log-in pasword. If you want to protect yourself against password
 +loss store your log-in password on a secure place or enable the recovery key
 +as described below.</p>
 +<div class="section" id="what-gets-encrypted">
 +<h2>What gets encrypted<a class="headerlink" href="#what-gets-encrypted" title="Permalink to this headline">¶</a></h2>
 +<p>The current version encrypts all your files stored in ownCloud.</p>
 +<p>At the moment we don’t encrypt:</p>
 +<ul class="simple">
- <li>old versions (versions created before the encryption app was enabled)</li>
 +<li>old files in the trash bin (files which were deleted before the encryption app was enabled)</li>
- <li>image thumbnails from the gallery app</li>
++<li>image thumbnails from the gallery app and previews from the files app</li>
 +<li>search index from the full text search app</li>
 +</ul>
 +<p>All this data is stored directly on your ownCloud server, so you don’t have to worry to expose
 +your data to a third party storage provider.</p>
 +</div>
 +<div class="section" id="decrypt-your-data-again">
 +<h2>Decrypt your data again<a class="headerlink" href="#decrypt-your-data-again" title="Permalink to this headline">¶</a></h2>
- <p>Corrently there is no way to decrypt your files directly on the server if you decide to stop
- using the encryption app. The only way to get a comlete copy of your unencrypted data is
- to download/sync all files as long as the encryption app is enabled. After the encryption
- app was disabled you can upload your unencrypted data again.</p>
- <p>It is already planned to add a option to switch from encrypted to unencrypted files
- directly on the server.</p>
++<p>If the encryption app was disabled users can decrypt their files again in their
++personal settings. After this was done they can continue to use their ownCloud
++without encryption.</p>
 +</div>
 +<div class="section" id="settings">
 +<h2>Settings<a class="headerlink" href="#settings" title="Permalink to this headline">¶</a></h2>
 +<p>Once the encryption app is enabled you will find some additional settings on
 +your personal settings page.</p>
 +<div class="section" id="recovery-key">
 +<h3>Recovery Key<a class="headerlink" href="#recovery-key" title="Permalink to this headline">¶</a></h3>
 +<p>If the admin enabled the recovery-key you can decide by your own if you
 +want to use this feature for your account. If you enable “Password recovery”
 +the admin will be able to read your data with a special password. This allows
 +him to recover your files in case of password loss. If the recovery-key is not
 +enabled than there is no way to restore your files if you loss your log-in
 +password.</p>
 +</div>
 +<div class="section" id="change-private-key-password">
 +<h3>Change Private Key Password<a class="headerlink" href="#change-private-key-password" title="Permalink to this headline">¶</a></h3>
 +<p>This option will be only available if your log-in password but not your
 +encryption password was changed by your admin. This can happen if your ownCloud
 +provider uses a external user back-end, e.g. LDAP, and changed your log-in
 +password there. In this case you can set your encryption password to your new
 +log-in password by providing your old and new log-in password. The encryption
 +app only works if log-in password and encryption password is identical.</p>
 +</div>
 +</div>
 +</div>
 +
 +
 +					</div>
 +				</div>
 +			</div>
 +    
 +  </div>
 +</div>
 +  </body>
 +</html>
diff --cc core/skeleton/ownCloudUserManual.pdf
index 54ac200,0000000..287bc77
mode 100644,000000..100644
Binary files differ
diff --cc version.php
index 018d81b,4c5f760..f9aa6c3
--- 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, 12);
 -
 -// The human readable string
 -$OC_VersionString='6.0 RC4';
 -
 -// The ownCloud edition
 -$OC_Edition='';
 -
 -// The ownCloud channel
 -$OC_Channel='git';
 -
 -// The build number
 -$OC_Build='';
 -
 +<?php 
- $OC_Version = array(6,0,0,11);
- $OC_VersionString = '6.0 RC3';
++$OC_Version = array(6,0,0,12);
++$OC_VersionString = '6.0 RC4';
 +$OC_Edition = '';
 +$OC_Channel = 'testing';
- $OC_Build = '2013-12-05T11:18:30+00:00';
++$OC_Build = '2013-12-06T20:13:14+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