loleaflet/README | 60 ++++ loleaflet/debug/document/document_simple_example.html | 8 loleaflet/dist/dialog/vex-theme-plain.css | 183 +++++++++++++ loleaflet/dist/dialog/vex.combined.min.js | 2 loleaflet/dist/dialog/vex.css | 248 ++++++++++++++++++ loleaflet/dist/images/save.png |binary loleaflet/dist/images/saveas.png |binary loleaflet/src/control/Buttons.js | 13 loleaflet/src/control/Control.Buttons.js | 31 ++ loleaflet/src/layer/tile/TileLayer.js | 4 loleaflet/src/map/Map.js | 4 loolwsd/LOOLSession.cpp | 20 + loolwsd/protocol.txt | 2 13 files changed, 559 insertions(+), 16 deletions(-)
New commits: commit 606ef3679ec515332fc98da265b8249453078e7b Author: Mihai Varga <mihai.va...@collabora.com> Date: Thu Jul 16 12:50:53 2015 +0300 loleaflet: saveas icon and dialog diff --git a/loleaflet/dist/images/saveas.png b/loleaflet/dist/images/saveas.png new file mode 100644 index 0000000..03d78c9 Binary files /dev/null and b/loleaflet/dist/images/saveas.png differ diff --git a/loleaflet/src/control/Control.Buttons.js b/loleaflet/src/control/Control.Buttons.js index e25532c..432dfa0 100644 --- a/loleaflet/src/control/Control.Buttons.js +++ b/loleaflet/src/control/Control.Buttons.js @@ -20,7 +20,8 @@ L.Control.Buttons = L.Control.extend({ 'aligncenter': {title: 'Center horizontaly', uno: 'AlignCenter', iconName: 'aligncenter.png'}, 'alignright': {title: 'Align right', uno: 'AlignRight', iconName: 'alignright.png'}, 'alignblock': {title: 'Justified', uno: 'AlignBlock', iconName: 'alignblock.png'}, - 'save': {title: 'Save', uno: 'Save', iconName: 'save.png'} + 'save': {title: 'Save', uno: 'Save', iconName: 'save.png'}, + 'saveas': {title: 'Save As', uno: '', iconName: 'saveas.png'}, }; for (var key in this._buttons) { var button = this._buttons[key]; @@ -52,7 +53,16 @@ L.Control.Buttons = L.Control.extend({ _onButtonClick: function (e) { var id = e.target.id; var button = this._buttons[id]; - this._map.toggleCommandState(button.uno); + if (id === 'saveas') { + vex.dialog.open({ + message: 'Save as:', + input: this._getDialogHTML(), + callback: L.bind(this._onSaveAs, this) + }); + } + else { + this._map.toggleCommandState(button.uno); + } }, _onStateChange: function (e) { @@ -69,6 +79,22 @@ L.Control.Buttons = L.Control.extend({ } } } + }, + + _getDialogHTML: function () { + return ( + '<label for="url">URL</label>' + + '<input name="url" type="text" value=' + this._map._docLayer.options.doc + '/>' + + '<label for="format">Format</label>' + + '<input name="format" type="text" />' + + '<label for="options">Options</label>' + + '<input name="options" type="text" />'); + }, + + _onSaveAs: function (e) { + if (e !== false) { + this._map.saveAs(e.url, e.format, e.options); + } } }); commit 1c16fd89f3021e5e7ad2f8f5861b920325cc890f Author: Mihai Varga <mihai.va...@collabora.com> Date: Thu Jul 16 12:50:08 2015 +0300 loleaflet: saveAs API diff --git a/loleaflet/README b/loleaflet/README index b6b90b0..6a5729c 100644 --- a/loleaflet/README +++ b/loleaflet/README @@ -105,6 +105,10 @@ Statusindicator (when the document is loading): + e.value == a value from 0 to 100 indicating the status if the statusType is 'setvalue +Save: + - API: + map.saveAs(url, [format, options]) + Contributing ------------ diff --git a/loleaflet/src/control/Buttons.js b/loleaflet/src/control/Buttons.js index 07a37e2..1ce0c98 100644 --- a/loleaflet/src/control/Buttons.js +++ b/loleaflet/src/control/Buttons.js @@ -6,5 +6,18 @@ L.Map.include({ if (this._docLayer._permission === 'edit') { this.socket.send('uno .uno:' + unoState); } + }, + + saveAs: function (url, format, options) { + if (format === undefined || format === null) { + format = ''; + } + if (options === undefined || options === null) { + options = ''; + } + this.socket.send('saveas ' + + 'url=' + url + ' ' + + 'format=' + format + ' ' + + 'options=' + options); } }); commit 5085fd4e0c8a6e35e1b09f761cd470c504e15dab Author: Mihai Varga <mihai.va...@collabora.com> Date: Thu Jul 16 12:23:25 2015 +0300 loolwsd: move tiles to persistent folder on save diff --git a/loolwsd/LOOLSession.cpp b/loolwsd/LOOLSession.cpp index 87226a6..75f1fdc 100644 --- a/loolwsd/LOOLSession.cpp +++ b/loolwsd/LOOLSession.cpp @@ -306,6 +306,11 @@ bool MasterProcessSession::handleInput(const char *buffer, int length) if (_peer.expired()) dispatchChild(); forwardToPeer(buffer, length); + + if ((tokens.count() > 1 && tokens[0] == "uno" && tokens[1] == ".uno:Save") || + tokens[0] == "saveas") { + _tileCache->documentSaved(); + } } return true; } commit 2ebe9f1be1f434b029349b9721cd1a927bb66da4 Author: Mihai Varga <mihai.va...@collabora.com> Date: Thu Jul 16 12:00:27 2015 +0300 loolwsd: format and options in 'saveas' are optional diff --git a/loolwsd/LOOLSession.cpp b/loolwsd/LOOLSession.cpp index 448c08e..87226a6 100644 --- a/loolwsd/LOOLSession.cpp +++ b/loolwsd/LOOLSession.cpp @@ -967,19 +967,22 @@ bool ChildProcessSession::saveAs(const char *buffer, int length, StringTokenizer std::string url, format, filterOptions; if (tokens.count() < 4 || - !getTokenString(tokens[1], "url", url) || - !getTokenString(tokens[2], "format", format) || - !getTokenString(tokens[3], "options", filterOptions)) + !getTokenString(tokens[1], "url", url)) { sendTextFrame("error: cmd=saveas kind=syntax"); return false; } URI::decode(url, url, true); - URI::decode(format, format, true); + if (getTokenString(tokens[2], "format", format)) { + URI::decode(format, format, true); + } - if (tokens.count() > 4) - filterOptions += Poco::cat(std::string(" "), tokens.begin() + 4, tokens.end()); + if (getTokenString(tokens[3], "options", filterOptions)) { + if (tokens.count() > 4) { + filterOptions += Poco::cat(std::string(" "), tokens.begin() + 4, tokens.end()); + } + } _loKitDocument->pClass->saveAs(_loKitDocument, url.c_str(), format.c_str(), filterOptions.c_str()); diff --git a/loolwsd/protocol.txt b/loolwsd/protocol.txt index 0db74e0..cd44358 100644 --- a/loolwsd/protocol.txt +++ b/loolwsd/protocol.txt @@ -44,7 +44,7 @@ resetselection saveas url=<url> format=<format> options=<options> - <url> is a URL, encoded. <format> is also URL-encoded, i.e. spaces as %20 + <url> is a URL, encoded. <format> is also URL-encoded, i.e. spaces as %20 and it can be empty options are the whole rest of the line, not URL-encoded, and can be empty selecttext type=<type> x=<x> y=<y> commit c335bda3643577556c175885871627fcb1777df5 Author: Mihai Varga <mihai.va...@collabora.com> Date: Thu Jul 16 10:42:40 2015 +0300 loleaflet: use vex dialog alert diff --git a/loleaflet/debug/document/document_simple_example.html b/loleaflet/debug/document/document_simple_example.html index 0b9fd4d..a8c5a43 100644 --- a/loleaflet/debug/document/document_simple_example.html +++ b/loleaflet/debug/document/document_simple_example.html @@ -60,10 +60,10 @@ var host = getParameterByName('host'); var edit = getParameterByName('edit') === 'true'; if (filePath === '') { - alert('Wrong file_path, usage: file_path=/path/to/doc/'); + vex.dialog.alert('Wrong file_path, usage: file_path=/path/to/doc/'); } if (host === '') { - alert('Wrong host, usage: host=ws://localhost:9980'); + vex.dialog.alert('Wrong host, usage: host=ws://localhost:9980'); } var map = L.map('map', 'scroll-container', 'mock-document', { diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js index 0554ed7..2d23fbc 100644 --- a/loleaflet/src/layer/tile/TileLayer.js +++ b/loleaflet/src/layer/tile/TileLayer.js @@ -522,7 +522,7 @@ L.TileLayer = L.GridLayer.extend({ this._map.fire('searchnotfound'); } else if (textMsg.startsWith('error:')) { - alert(textMsg); + vex.dialog.alert(textMsg); } }, @@ -1023,7 +1023,7 @@ L.TileLayer = L.GridLayer.extend({ e = e.originalEvent; e.preventDefault(); if (!this._selectionTextContent) { - alert('Oops, no content available yet'); + vex.dialog.alert('Oops, no content available yet'); } else { e.clipboardData.setData('text/plain', this._selectionTextContent); diff --git a/loleaflet/src/map/Map.js b/loleaflet/src/map/Map.js index 4f25698..3e299f9 100644 --- a/loleaflet/src/map/Map.js +++ b/loleaflet/src/map/Map.js @@ -440,7 +440,7 @@ L.Map = L.Evented.extend({ this.socket = new WebSocket(this.options.server); } catch (e) { console.log(e); - alert('Socket connection error'); + vex.dialog.alert('Socket connection error'); return; } this.socket.onerror = L.bind(this._socketError, this); @@ -758,7 +758,7 @@ L.Map = L.Evented.extend({ _socketError: function (e) { console.log(e); - alert('Socket connection error'); + vex.dialog.alert('Socket connection error'); } }); commit 6a68d355029873fdc03dcb07b4d1ee6bb1081a0c Author: Mihai Varga <mihai.va...@collabora.com> Date: Thu Jul 16 10:36:59 2015 +0300 loleaflet: added vex dialog release 2.3.2 Github page: https://github.com/HubSpot/vex MIT license: https://github.com/HubSpot/vex/blob/master/LICENSE diff --git a/loleaflet/debug/document/document_simple_example.html b/loleaflet/debug/document/document_simple_example.html index d5cf836..0b9fd4d 100644 --- a/loleaflet/debug/document/document_simple_example.html +++ b/loleaflet/debug/document/document_simple_example.html @@ -9,6 +9,8 @@ <link rel="stylesheet" href="../../dist/leaflet.css"> <link rel="stylesheet" href="../../plugins/draw-0.2.4/dist/leaflet.draw.css"> <link rel="stylesheet" href="../../src/scrollbar/jquery.mCustomScrollbar.css"> +<link rel="stylesheet" href="../../dist/dialog/vex.css" /> +<link rel="stylesheet" href="../../dist/dialog/vex-theme-plain.css" /> <style type="text/css"></style></head> <body> <script src="../../dist/leaflet-src.js"></script> @@ -16,6 +18,8 @@ <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> <script>window.jQuery || document.write('<script src="../../src/scrollbar/jquery-1.11.0.min.js"><\/script>')</script> <script src="../../src/scrollbar/jquery.mCustomScrollbar.js"></script> + <script src="../../dist/dialog/vex.combined.min.js"></script> + <script>vex.defaultOptions.className = 'vex-theme-plain';</script> <!--The "controls" div holds map controls suchs as the Zoom button and it's separated from the map in order to have the controls on the top diff --git a/loleaflet/dist/dialog/vex-theme-plain.css b/loleaflet/dist/dialog/vex-theme-plain.css new file mode 100644 index 0000000..33a2f5b --- /dev/null +++ b/loleaflet/dist/dialog/vex-theme-plain.css @@ -0,0 +1,183 @@ +@keyframes vex-pulse { + 0% { + -moz-box-shadow: inset 0 0 0 300px transparent; + -webkit-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; } + + 70% { + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); } + + 100% { + -moz-box-shadow: inset 0 0 0 300px transparent; + -webkit-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; } } + +@-webkit-keyframes vex-pulse { + 0% { + -moz-box-shadow: inset 0 0 0 300px transparent; + -webkit-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; } + + 70% { + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); } + + 100% { + -moz-box-shadow: inset 0 0 0 300px transparent; + -webkit-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; } } + +@-moz-keyframes vex-pulse { + 0% { + -moz-box-shadow: inset 0 0 0 300px transparent; + -webkit-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; } + + 70% { + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); } + + 100% { + -moz-box-shadow: inset 0 0 0 300px transparent; + -webkit-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; } } + +@-ms-keyframes vex-pulse { + 0% { + -moz-box-shadow: inset 0 0 0 300px transparent; + -webkit-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; } + + 70% { + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); } + + 100% { + -moz-box-shadow: inset 0 0 0 300px transparent; + -webkit-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; } } + +@-o-keyframes vex-pulse { + 0% { + -moz-box-shadow: inset 0 0 0 300px transparent; + -webkit-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; } + + 70% { + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); } + + 100% { + -moz-box-shadow: inset 0 0 0 300px transparent; + -webkit-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; } } + +.vex.vex-theme-plain { + padding-top: 160px; + padding-bottom: 160px; } + .vex.vex-theme-plain .vex-content { + font-family: "Helvetica Neue", sans-serif; + background: #fff; + color: #444; + padding: 1em; + position: relative; + margin: 0 auto; + max-width: 100%; + width: 450px; + font-size: 1.1em; + line-height: 1.5em; } + .vex.vex-theme-plain .vex-content h1, .vex.vex-theme-plain .vex-content h2, .vex.vex-theme-plain .vex-content h3, .vex.vex-theme-plain .vex-content h4, .vex.vex-theme-plain .vex-content h5, .vex.vex-theme-plain .vex-content h6, .vex.vex-theme-plain .vex-content p, .vex.vex-theme-plain .vex-content ul, .vex.vex-theme-plain .vex-content li { + color: inherit; } + .vex.vex-theme-plain .vex-close { + position: absolute; + top: 0; + right: 0; + cursor: pointer; } + .vex.vex-theme-plain .vex-close:before { + position: absolute; + content: "\00D7"; + font-size: 26px; + font-weight: normal; + line-height: 31px; + height: 30px; + width: 30px; + text-align: center; + top: 3px; + right: 3px; + color: #bbb; + background: transparent; } + .vex.vex-theme-plain .vex-close:hover:before, .vex.vex-theme-plain .vex-close:active:before { + color: #777; + background: #e0e0e0; } + .vex.vex-theme-plain .vex-dialog-form .vex-dialog-message { + margin-bottom: 0.5em; } + .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input { + margin-bottom: 1em; } + .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input textarea, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="date"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="datetime"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="datetime-local"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="email"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="month"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="number"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="password"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="search"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="tel"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="text"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="time"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type=" url"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="week"] { + background: #f0f0f0; + width: 100%; + padding: 0.25em 0.67em; + border: 0; + font-family: inherit; + font-weight: inherit; + font-size: inherit; + min-height: 2.5em; + margin: 0 0 0.25em; } + .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input textarea:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="date"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="datetime"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="datetime-local"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="email"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="month"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="number"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="password"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="search"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="tel"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="text"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="time"]:f ocus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="url"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="week"]:focus { + -moz-box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.2); + -webkit-box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.2); + box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.2); + outline: none; } + .vex.vex-theme-plain .vex-dialog-form .vex-dialog-buttons { + *zoom: 1; } + .vex.vex-theme-plain .vex-dialog-form .vex-dialog-buttons:after { + content: ""; + display: table; + clear: both; } + .vex.vex-theme-plain .vex-dialog-button { + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; + border: 0; + float: right; + margin: 0 0 0 0.5em; + font-family: inherit; + text-transform: uppercase; + letter-spacing: 0.1em; + font-size: 0.8em; + line-height: 1em; + padding: 0.75em 2em; } + .vex.vex-theme-plain .vex-dialog-button.vex-last { + margin-left: 0; } + .vex.vex-theme-plain .vex-dialog-button:focus { + animation: vex-pulse 1.1s infinite; + -webkit-animation: vex-pulse 1.1s infinite; + -moz-animation: vex-pulse 1.1s infinite; + -ms-animation: vex-pulse 1.1s infinite; + -o-animation: vex-pulse 1.1s infinite; + -webkit-backface-visibility: hidden; + outline: none; } + @media (max-width: 568px) { + .vex.vex-theme-plain .vex-dialog-button:focus { + animation: none; + -webkit-animation: none; + -moz-animation: none; + -ms-animation: none; + -o-animation: none; + -webkit-backface-visibility: hidden; } } + .vex.vex-theme-plain .vex-dialog-button.vex-dialog-button-primary { + background: #3288e6; + color: #fff; } + .vex.vex-theme-plain .vex-dialog-button.vex-dialog-button-secondary { + background: #e0e0e0; + color: #777; } + +.vex-loading-spinner.vex-theme-plain { + height: 2.5em; + width: 2.5em; } diff --git a/loleaflet/dist/dialog/vex.combined.min.js b/loleaflet/dist/dialog/vex.combined.min.js new file mode 100644 index 0000000..0aa72ba --- /dev/null +++ b/loleaflet/dist/dialog/vex.combined.min.js @@ -0,0 +1,2 @@ +/*! vex.js, vex.dialog.js 2.3.2 */ +(function(){var a;a=function(a){var b,c;return b=!1,a(function(){var d;return d=(document.body||document.documentElement).style,b=void 0!==d.animation||void 0!==d.WebkitAnimation||void 0!==d.MozAnimation||void 0!==d.MsAnimation||void 0!==d.OAnimation,a(window).bind("keyup.vex",function(a){return 27===a.keyCode?c.closeByEscape():void 0})}),c={globalID:1,animationEndEvent:"animationend webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend",baseClassNames:{vex:"vex",content:"vex-content",overlay:"vex-overlay",close:"vex-close",closing:"vex-closing",open:"vex-open"},defaultOptions:{content:"",showCloseButton:!0,escapeButtonCloses:!0,overlayClosesOnClick:!0,appendLocation:"body",className:"",css:{},overlayClassName:"",overlayCSS:{},contentClassName:"",contentCSS:{},closeClassName:"",closeCSS:{}},open:function(b){return b=a.extend({},c.defaultOptions,b),b.id=c.globalID,c.globalID+=1,b.$vex=a("<div>").addClass(c.baseClassNames.vex).addClass(b.className).css(b.css).data({vex:b}),b .$vexOverlay=a("<div>").addClass(c.baseClassNames.overlay).addClass(b.overlayClassName).css(b.overlayCSS).data({vex:b}),b.overlayClosesOnClick&&b.$vexOverlay.bind("click.vex",function(b){return b.target===this?c.close(a(this).data().vex.id):void 0}),b.$vex.append(b.$vexOverlay),b.$vexContent=a("<div>").addClass(c.baseClassNames.content).addClass(b.contentClassName).css(b.contentCSS).append(b.content).data({vex:b}),b.$vex.append(b.$vexContent),b.showCloseButton&&(b.$closeButton=a("<div>").addClass(c.baseClassNames.close).addClass(b.closeClassName).css(b.closeCSS).data({vex:b}).bind("click.vex",function(){return c.close(a(this).data().vex.id)}),b.$vexContent.append(b.$closeButton)),a(b.appendLocation).append(b.$vex),c.setupBodyClassName(b.$vex),b.afterOpen&&b.afterOpen(b.$vexContent,b),setTimeout(function(){return b.$vexContent.trigger("vexOpen",b)},0),b.$vexContent},getSelectorFromBaseClass:function(a){return"."+a.split(" ").join(".")},getAllVexes:function(){return a("."+c.baseClassN ames.vex+':not(".'+c.baseClassNames.closing+'") '+c.getSelectorFromBaseClass(c.baseClassNames.content))},getVexByID:function(b){return c.getAllVexes().filter(function(){return a(this).data().vex.id===b})},close:function(a){var b;if(!a){if(b=c.getAllVexes().last(),!b.length)return!1;a=b.data().vex.id}return c.closeByID(a)},closeAll:function(){var b;return b=c.getAllVexes().map(function(){return a(this).data().vex.id}).toArray(),(null!=b?b.length:void 0)?(a.each(b.reverse(),function(a,b){return c.closeByID(b)}),!0):!1},closeByID:function(d){var e,f,g,h,i;return f=c.getVexByID(d),f.length?(e=f.data().vex.$vex,i=a.extend({},f.data().vex),g=function(){return i.beforeClose?i.beforeClose(f,i):void 0},h=function(){return f.trigger("vexClose",i),e.remove(),a("body").trigger("vexAfterClose",i),i.afterClose?i.afterClose(f,i):void 0},b?(g(),e.unbind(c.animationEndEvent).bind(c.animationEndEvent,function(){return h()}).addClass(c.baseClassNames.closing)):(g(),h()),!0):void 0},closeByEscape:funct ion(){var b,d,e;return e=c.getAllVexes().map(function(){return a(this).data().vex.id}).toArray(),(null!=e?e.length:void 0)?(d=Math.max.apply(Math,e),b=c.getVexByID(d),b.data().vex.escapeButtonCloses!==!0?!1:c.closeByID(d)):!1},setupBodyClassName:function(){return a("body").bind("vexOpen.vex",function(){return a("body").addClass(c.baseClassNames.open)}).bind("vexAfterClose.vex",function(){return c.getAllVexes().length?void 0:a("body").removeClass(c.baseClassNames.open)})},hideLoading:function(){return a(".vex-loading-spinner").remove()},showLoading:function(){return c.hideLoading(),a("body").append('<div class="vex-loading-spinner '+c.defaultOptions.className+'"></div>')}}},"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a(require("jquery")):window.vex=a(jQuery)}).call(this),function(){var a;a=function(a,b){var c,d;return null==b?a.error("Vex is required to use vex.dialog"):(c=function(b){var c;return c={},a.each(b.serializeArray(),f unction(){return c[this.name]?(c[this.name].push||(c[this.name]=[c[this.name]]),c[this.name].push(this.value||"")):c[this.name]=this.value||""}),c},d={},d.buttons={YES:{text:"OK",type:"submit",className:"vex-dialog-button-primary"},NO:{text:"Cancel",type:"button",className:"vex-dialog-button-secondary",click:function(a){return a.data().vex.value=!1,b.close(a.data().vex.id)}}},d.defaultOptions={callback:function(){},afterOpen:function(){},message:"Message",input:'<input name="vex" type="hidden" value="_vex-empty-value" />',value:!1,buttons:[d.buttons.YES,d.buttons.NO],showCloseButton:!1,onSubmit:function(e){var f,g;return f=a(this),g=f.parent(),e.preventDefault(),e.stopPropagation(),g.data().vex.value=d.getFormValueOnSubmit(c(f)),b.close(g.data().vex.id)},focusFirstInput:!0},d.defaultAlertOptions={message:"Alert",buttons:[d.buttons.YES]},d.defaultConfirmOptions={message:"Confirm"},d.open=function(c){var e;return c=a.extend({},b.defaultOptions,d.defaultOptions,c),c.content=d.buildDial ogForm(c),c.beforeClose=function(a){return c.callback(a.data().vex.value)},e=b.open(c),c.focusFirstInput&&e.find('button[type="submit"], button[type="button"], input[type="submit"], input[type="button"], textarea, input[type="date"], input[type="datetime"], input[type="datetime-local"], input[type="email"], input[type="month"], input[type="number"], input[type="password"], input[type="search"], input[type="tel"], input[type="text"], input[type="time"], input[type="url"], input[type="week"]').first().focus(),e},d.alert=function(b){return"string"==typeof b&&(b={message:b}),b=a.extend({},d.defaultAlertOptions,b),d.open(b)},d.confirm=function(b){return"string"==typeof b?a.error("dialog.confirm(options) requires options.callback."):(b=a.extend({},d.defaultConfirmOptions,b),d.open(b))},d.prompt=function(b){var c;return"string"==typeof b?a.error("dialog.prompt(options) requires options.callback."):(c={message:'<label for="vex">'+(b.label||"Prompt:")+"</label>",input:'<input name="vex" type ="text" class="vex-dialog-prompt-input" placeholder="'+(b.placeholder||"")+'" value="'+(b.value||"")+'" />'},b=a.extend({},c,b),d.open(b))},d.buildDialogForm=function(b){var c,e,f;return c=a('<form class="vex-dialog-form" />'),f=a('<div class="vex-dialog-message" />'),e=a('<div class="vex-dialog-input" />'),c.append(f.append(b.message)).append(e.append(b.input)).append(d.buttonsToDOM(b.buttons)).bind("submit.vex",b.onSubmit),c},d.getFormValueOnSubmit=function(a){return a.vex||""===a.vex?"_vex-empty-value"===a.vex?!0:a.vex:a},d.buttonsToDOM=function(c){var d;return d=a('<div class="vex-dialog-buttons" />'),a.each(c,function(e,f){var g;return g=a('<button type="'+f.type+'"></button>').text(f.text).addClass(f.className+" vex-dialog-button "+(0===e?"vex-first ":"")+(e===c.length-1?"vex-last ":"")).bind("click.vex",function(c){return f.click?f.click(a(this).parents(b.getSelectorFromBaseClass(b.baseClassNames.content)),c):void 0}),g.appendTo(d)}),d},d)},"function"==typeof define&&define. amd?define(["jquery","vex"],a):"object"==typeof exports?module.exports=a(require("jquery"),require("./vex.js")):window.vex.dialog=a(window.jQuery,window.vex)}.call(this); \ No newline at end of file diff --git a/loleaflet/dist/dialog/vex.css b/loleaflet/dist/dialog/vex.css new file mode 100644 index 0000000..f391221 --- /dev/null +++ b/loleaflet/dist/dialog/vex.css @@ -0,0 +1,248 @@ +@keyframes vex-fadein { + 0% { + opacity: 0; } + + 100% { + opacity: 1; } } + +@-webkit-keyframes vex-fadein { + 0% { + opacity: 0; } + + 100% { + opacity: 1; } } + +@-moz-keyframes vex-fadein { + 0% { + opacity: 0; } + + 100% { + opacity: 1; } } + +@-ms-keyframes vex-fadein { + 0% { + opacity: 0; } + + 100% { + opacity: 1; } } + +@-o-keyframes vex-fadein { + 0% { + opacity: 0; } + + 100% { + opacity: 1; } } + +@keyframes vex-fadeout { + 0% { + opacity: 1; } + + 100% { + opacity: 0; } } + +@-webkit-keyframes vex-fadeout { + 0% { + opacity: 1; } + + 100% { + opacity: 0; } } + +@-moz-keyframes vex-fadeout { + 0% { + opacity: 1; } + + 100% { + opacity: 0; } } + +@-ms-keyframes vex-fadeout { + 0% { + opacity: 1; } + + 100% { + opacity: 0; } } + +@-o-keyframes vex-fadeout { + 0% { + opacity: 1; } + + 100% { + opacity: 0; } } + +@keyframes vex-rotation { + 0% { + transform: rotate(0deg); + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -o-transform: rotate(0deg); } + + 100% { + transform: rotate(359deg); + -webkit-transform: rotate(359deg); + -moz-transform: rotate(359deg); + -ms-transform: rotate(359deg); + -o-transform: rotate(359deg); } } + +@-webkit-keyframes vex-rotation { + 0% { + transform: rotate(0deg); + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -o-transform: rotate(0deg); } + + 100% { + transform: rotate(359deg); + -webkit-transform: rotate(359deg); + -moz-transform: rotate(359deg); + -ms-transform: rotate(359deg); + -o-transform: rotate(359deg); } } + +@-moz-keyframes vex-rotation { + 0% { + transform: rotate(0deg); + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -o-transform: rotate(0deg); } + + 100% { + transform: rotate(359deg); + -webkit-transform: rotate(359deg); + -moz-transform: rotate(359deg); + -ms-transform: rotate(359deg); + -o-transform: rotate(359deg); } } + +@-ms-keyframes vex-rotation { + 0% { + transform: rotate(0deg); + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -o-transform: rotate(0deg); } + + 100% { + transform: rotate(359deg); + -webkit-transform: rotate(359deg); + -moz-transform: rotate(359deg); + -ms-transform: rotate(359deg); + -o-transform: rotate(359deg); } } + +@-o-keyframes vex-rotation { + 0% { + transform: rotate(0deg); + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -o-transform: rotate(0deg); } + + 100% { + transform: rotate(359deg); + -webkit-transform: rotate(359deg); + -moz-transform: rotate(359deg); + -ms-transform: rotate(359deg); + -o-transform: rotate(359deg); } } + +.vex, .vex *, .vex *:before, .vex *:after { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; } + +.vex { + position: fixed; + overflow: auto; + -webkit-overflow-scrolling: touch; + z-index: 1111; + top: 0; + right: 0; + bottom: 0; + left: 0; } + +.vex-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; } + +.vex-overlay { + background: #000; + filter: alpha(opacity=40); + /* IE 5â7 */ + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=40)"; + /* IE 8 */ } + +.vex-overlay { + animation: vex-fadein 0.5s; + -webkit-animation: vex-fadein 0.5s; + -moz-animation: vex-fadein 0.5s; + -ms-animation: vex-fadein 0.5s; + -o-animation: vex-fadein 0.5s; + -webkit-backface-visibility: hidden; + position: fixed; + background: rgba(0, 0, 0, 0.4); + top: 0; + right: 0; + bottom: 0; + left: 0; } + .vex.vex-closing .vex-overlay { + animation: vex-fadeout 0.5s; + -webkit-animation: vex-fadeout 0.5s; + -moz-animation: vex-fadeout 0.5s; + -ms-animation: vex-fadeout 0.5s; + -o-animation: vex-fadeout 0.5s; + -webkit-backface-visibility: hidden; } + +.vex-content { + animation: vex-fadein 0.5s; + -webkit-animation: vex-fadein 0.5s; + -moz-animation: vex-fadein 0.5s; + -ms-animation: vex-fadein 0.5s; + -o-animation: vex-fadein 0.5s; + -webkit-backface-visibility: hidden; + background: #fff; } + .vex.vex-closing .vex-content { + animation: vex-fadeout 0.5s; + -webkit-animation: vex-fadeout 0.5s; + -moz-animation: vex-fadeout 0.5s; + -ms-animation: vex-fadeout 0.5s; + -o-animation: vex-fadeout 0.5s; + -webkit-backface-visibility: hidden; } + +.vex-close:before { + font-family: Arial, sans-serif; + content: "\00D7"; } + +.vex-dialog-form { + margin: 0; } + +.vex-dialog-button { + text-rendering: optimizeLegibility; + -moz-appearance: none; + -webkit-appearance: none; + cursor: pointer; + -webkit-tap-highlight-color: transparent; } + +.vex-loading-spinner { + animation: vex-rotation 0.7s linear infinite; + -webkit-animation: vex-rotation 0.7s linear infinite; + -moz-animation: vex-rotation 0.7s linear infinite; + -ms-animation: vex-rotation 0.7s linear infinite; + -o-animation: vex-rotation 0.7s linear infinite; + -webkit-backface-visibility: hidden; + -moz-box-shadow: 0 0 1em rgba(0, 0, 0, 0.1); + -webkit-box-shadow: 0 0 1em rgba(0, 0, 0, 0.1); + box-shadow: 0 0 1em rgba(0, 0, 0, 0.1); + position: fixed; + z-index: 1112; + margin: auto; + top: 0; + right: 0; + bottom: 0; + left: 0; + height: 2em; + width: 2em; + background: #fff; } + +body.vex-open { + overflow: hidden; } commit 9c5cb3a1403074a36a99f49f9883c73a9c8c9a76 Author: Mihai Varga <mihai.va...@collabora.com> Date: Wed Jul 15 19:25:34 2015 +0300 loleaflet: added the document API in README diff --git a/loleaflet/README b/loleaflet/README index 48359c8..b6b90b0 100644 --- a/loleaflet/README +++ b/loleaflet/README @@ -46,11 +46,65 @@ To see an example: * modify the URL to allow loleaflet to connect to a server and open a document - http://web-page/document_simple_example.html?file_path=/PATH/TO/DOC&host=ws://localhost:9980 + http://web-page/document_simple_example.html?file_path=file:///PATH/TO/DOC&host=ws://localhost:9980 and you should see the document in the browser. In case anything goes wrong, check the loolwsd console for the debugging output. +API & events +------------ + +Search: + - API: + map.search(text, [backward]) + - events: + map.on('searchnotfound', function) + +Zoom: + - API: + map.zoomIn(amount) + map.zoomOut(amout) + map.getMinZoom() + map.getMaxZoom() + - events: + map.on('zoomend zoomlevelschange', function) + +Edit, view, readOnly: + - API: + map.setPermission('edit' | 'view' | 'readonly') + - events: + map.on('updatepermission', function (e) {}) where: + + e.perm == 'edit' | 'view' | 'readonly' + +Buttons like Bold, Italic, Strike through etc. + - API: + map.toggleCommandState('Bold' | 'Italic' | 'Underline' | 'Strikeout' | 'AlighLeft', etc) + - events: + map.on('commandstatechanged', function (e) {}) where: + + e.unoCmd == 'Bold' | 'Italic' etc. + + e.state = 'true' | 'false' + +Parts (like slides in presentation, or sheets in spreadsheets): + - API: + map.setPart('next' | 'prev' | partNumber) + map.getPartPreview(id, part, maxWidth, maxHeight) where: + + id = the ID of the request so that the response can be identified + + maxWidth / maxHeight are the desired dimensions of the preview, a smaller + image might be returned in order to keep the original ratio of the document + - events: + map.on('updateparts', function (e) {}) where: + + e.currentPart is the current part + + e.parts == the number of parts that the document has + + e.docType == 'text' | 'spreadsheet' | 'presentation' | 'drawing' | 'other' + + [e.partNames] if present, part names (e.g. sheet names) + +Statusindicator (when the document is loading): + - events + map.on('statusindicator', function (e) {}) where: + + e.statusType = 'start' | 'setvalue' | 'finish' + + e.value == a value from 0 to 100 indicating the status + if the statusType is 'setvalue + Contributing ------------ commit d7158497d5b3abdb9dce46c3cbf2218ea8494fee Author: Mihai Varga <mihai.va...@collabora.com> Date: Wed Jul 15 19:13:15 2015 +0300 loleaflet: save button diff --git a/loleaflet/dist/images/save.png b/loleaflet/dist/images/save.png new file mode 100644 index 0000000..325b074 Binary files /dev/null and b/loleaflet/dist/images/save.png differ diff --git a/loleaflet/src/control/Control.Buttons.js b/loleaflet/src/control/Control.Buttons.js index 1663f3c..e25532c 100644 --- a/loleaflet/src/control/Control.Buttons.js +++ b/loleaflet/src/control/Control.Buttons.js @@ -19,7 +19,8 @@ L.Control.Buttons = L.Control.extend({ 'alignleft': {title: 'Align left', uno: 'AlignLeft', iconName: 'alignleft.png'}, 'aligncenter': {title: 'Center horizontaly', uno: 'AlignCenter', iconName: 'aligncenter.png'}, 'alignright': {title: 'Align right', uno: 'AlignRight', iconName: 'alignright.png'}, - 'alignblock': {title: 'Justified', uno: 'AlignBlock', iconName: 'alignblock.png'} + 'alignblock': {title: 'Justified', uno: 'AlignBlock', iconName: 'alignblock.png'}, + 'save': {title: 'Save', uno: 'Save', iconName: 'save.png'} }; for (var key in this._buttons) { var button = this._buttons[key];
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits