From bb3f3c758ad11a567b15a7e491ba85ca5a589eda Mon Sep 17 00:00:00 2001 From: Mihai Varga Date: Tue, 1 Sep 2015 17:53:44 +0300 Subject: [PATCH] loleaflet: moved the socket init/communication to core/Socket.js The socket is now available through the L.Socket object which now also handles the initial connection and reconnection to the server. The document (tile layer) is now added automatically in the map initialization. --- loleaflet/build/deps.js | 1 + .../document/document_simple_example.html | 21 +- loleaflet/src/control/Buttons.js | 4 +- loleaflet/src/control/Control.Search.js | 2 +- loleaflet/src/control/Parts.js | 10 +- loleaflet/src/control/Permission.js | 4 +- loleaflet/src/control/Search.js | 4 +- loleaflet/src/control/Styles.js | 2 +- loleaflet/src/core/Socket.js | 178 ++++++++++++++++ loleaflet/src/layer/Layer.js | 6 +- loleaflet/src/layer/tile/GridLayer.js | 61 ++---- loleaflet/src/layer/tile/TileLayer.js | 200 ++++-------------- loleaflet/src/map/Map.js | 40 +--- .../src/map/handler/Map.DoubleClickZoom.js | 2 +- 14 files changed, 257 insertions(+), 278 deletions(-) create mode 100644 loleaflet/src/core/Socket.js diff --git a/loleaflet/build/deps.js b/loleaflet/build/deps.js index 5488e5031..d806268e8 100644 --- a/loleaflet/build/deps.js +++ b/loleaflet/build/deps.js @@ -5,6 +5,7 @@ var deps = { 'core/Util.js', 'core/Class.js', 'core/Events.js', + 'core/Socket.js', 'core/Browser.js', 'geometry/Point.js', 'geometry/Bounds.js', diff --git a/loleaflet/debug/document/document_simple_example.html b/loleaflet/debug/document/document_simple_example.html index eb55c1ef8..eaa173a8b 100644 --- a/loleaflet/debug/document/document_simple_example.html +++ b/loleaflet/debug/document/document_simple_example.html @@ -58,13 +58,12 @@ } var globalMap = L.map('map', { - center: [0, 0], - zoom: 10, - minZoom: 1, - maxZoom: 20, + doc: filePath, server: host, - doubleClickZoom: false - }); + edit: edit, + timestamp: timestamp, + readOnly: false + }); ////// Controls ///// globalMap.addControl(L.control.styles()); @@ -79,15 +78,5 @@ globalMap.addControl(L.control.dialog()); globalMap.addControl(L.control.partsPreview()); globalMap.addControl(L.control.tabs()); - - ////// Document layer //// - var docLayer = new L.TileLayer('', { - doc: filePath, - useSocket : true, - edit: edit, - timestamp: timestamp, - readOnly: false - }); - globalMap.addLayer(docLayer); diff --git a/loleaflet/src/control/Buttons.js b/loleaflet/src/control/Buttons.js index 2f085f523..d9327c876 100644 --- a/loleaflet/src/control/Buttons.js +++ b/loleaflet/src/control/Buttons.js @@ -4,7 +4,7 @@ L.Map.include({ toggleCommandState: function (unoState) { if (this._docLayer._permission === 'edit') { - this._docLayer.sendMessage('uno .uno:' + unoState); + L.Socket.sendMessage('uno .uno:' + unoState); } }, @@ -15,7 +15,7 @@ L.Map.include({ if (options === undefined || options === null) { options = ''; } - this._docLayer.sendMessage('saveas ' + + L.Socket.sendMessage('saveas ' + 'url=' + url + ' ' + 'format=' + format + ' ' + 'options=' + options); diff --git a/loleaflet/src/control/Control.Search.js b/loleaflet/src/control/Control.Search.js index 0154ad0fa..38ea2af6c 100644 --- a/loleaflet/src/control/Control.Search.js +++ b/loleaflet/src/control/Control.Search.js @@ -47,7 +47,7 @@ L.Control.Search = L.Control.extend({ this._refocusOnMap(); } else { - this._map._docLayer.sendMessage('requestloksession'); + L.Socket.sendMessage('requestloksession'); } }, diff --git a/loleaflet/src/control/Parts.js b/loleaflet/src/control/Parts.js index 138766380..7089cfbb1 100644 --- a/loleaflet/src/control/Parts.js +++ b/loleaflet/src/control/Parts.js @@ -22,14 +22,14 @@ L.Map.include({ } if (docLayer._isCursorOverlayVisible) { // a click outside the slide to clear any selection - docLayer.sendMessage('resetselection'); + L.Socket.sendMessage('resetselection'); } this.fire('updateparts', { currentPart: docLayer._currentPart, parts: docLayer._parts, docType: docLayer._docType }); - docLayer.sendMessage('setclientpart part=' + docLayer._currentPart); + L.Socket.sendMessage('setclientpart part=' + docLayer._currentPart); docLayer._update(); docLayer._pruneTiles(); docLayer._clearSelections(); @@ -46,7 +46,7 @@ L.Map.include({ else { maxHeight = Math.round(docLayer._docHeightTwips * maxWidth / docLayer._docWidthTwips); } - docLayer.sendMessage('tile ' + + L.Socket.sendMessage('tile ' + 'part=' + part + ' ' + 'width=' + maxWidth + ' ' + 'height=' + maxHeight + ' ' + @@ -72,7 +72,7 @@ L.Map.include({ y = Math.round(y / docLayer._tileSize * docLayer._tileHeightTwips); height = Math.round(height / docLayer._tileSize * docLayer._tileHeightTwips); - docLayer.sendMessage('tile ' + + L.Socket.sendMessage('tile ' + 'part=0 ' + 'width=' + maxWidth + ' ' + 'height=' + maxHeight + ' ' + @@ -98,7 +98,7 @@ L.Map.include({ else if (typeof (page) === 'number' && page >= 0 && page < docLayer._pages) { docLayer._currentPage = page; } - docLayer.sendMessage('setpage page=' + docLayer._currentPage); + L.Socket.sendMessage('setpage page=' + docLayer._currentPage); }, getNumberOfPages: function () { diff --git a/loleaflet/src/control/Permission.js b/loleaflet/src/control/Permission.js index 902afa7b4..5bb8a9a6d 100644 --- a/loleaflet/src/control/Permission.js +++ b/loleaflet/src/control/Permission.js @@ -5,7 +5,7 @@ L.Map.include({ setPermission: function (perm) { this._docLayer._permission = perm; if (perm === 'edit') { - this._docLayer.sendMessage('requestloksession'); + L.Socket.sendMessage('requestloksession'); this.dragging.disable(); } else if (perm === 'view' || perm === 'readonly') { @@ -22,7 +22,7 @@ L.Map.include({ if (this._docLayer._permission === 'edit') { return; } - this._docLayer.sendMessage('requestloksession'); + L.Socket.sendMessage('requestloksession'); this.dragging.disable(); }, diff --git a/loleaflet/src/control/Search.js b/loleaflet/src/control/Search.js index 174f08b5e..e9413e44c 100644 --- a/loleaflet/src/control/Search.js +++ b/loleaflet/src/control/Search.js @@ -29,10 +29,10 @@ L.Map.include({ searchCmd['SearchItem.SearchStartPointY'] = {}; searchCmd['SearchItem.SearchStartPointY'].type = 'long'; searchCmd['SearchItem.SearchStartPointY'].value = topLeftTwips.y; - this._docLayer.sendMessage('uno .uno:ExecuteSearch ' + JSON.stringify(searchCmd)); + L.Socket.sendMessage('uno .uno:ExecuteSearch ' + JSON.stringify(searchCmd)); }, resetSelection: function () { - this._docLayer.sendMessage('resetselection'); + L.Socket.sendMessage('resetselection'); } }); diff --git a/loleaflet/src/control/Styles.js b/loleaflet/src/control/Styles.js index ca233de79..2e37af2f4 100644 --- a/loleaflet/src/control/Styles.js +++ b/loleaflet/src/control/Styles.js @@ -12,6 +12,6 @@ L.Map.include({ '"Style":{"type":"string", "value": "' + style + '"},' + '"FamilyName":{"type":"string", "value":"' + familyName + '"}' + '}'; - this._docLayer.sendMessage(msg); + L.Socket.sendMessage(msg); } }); diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js new file mode 100644 index 000000000..78cb9227c --- /dev/null +++ b/loleaflet/src/core/Socket.js @@ -0,0 +1,178 @@ +/* + * L.Socket contains methods for the communication with the server + */ + +L.Socket = { + connect: function (map) { + try { + this.socket = new WebSocket(map.options.server); + } catch (e) { + this.fire('error', {msg: 'Socket connection error'}); + return null; + } + this._map = map; + this._msgQueue = []; + this.socket.onerror = L.bind(this._onSocketError, map); + this.socket.onclose = L.bind(this._onSocketClose, map); + this.socket.onopen = L.bind(this._onOpen, this); + this.socket.onmessage = L.bind(this._onMessage, this); + this.socket.binaryType = 'arraybuffer'; + return this.socket; + }, + + close: function () { + this.socket.onerror = function () {}; + this.socket.onclose = function () {}; + this.socket.close(); + }, + + sendMessage: function (msg, coords) { + var socketState = this.socket.readyState; + if (socketState === 2 || socketState === 3) { + this._socket = this.connect(this._map); + this._msgQueue.push({msg: msg, coords: coords}); + } + + if (socketState === 0) { + // push message while trying to connect socket again. + this._msgQueue.push({msg: msg, coords: coords}); + } + else if (socketState === 1) { + this.socket.send(msg); + L.Log.log(msg, L.OUTGOING, coords); + } + }, + + _onOpen: function () { + var msg = 'load url=' + this._map.options.doc; + if (this._map._docLayer) { + msg += ' part=' + this._map.getCurrentPartNumber(); + } + if (this._map.options.timestamp) { + msg += ' timestamp=' + this._map.options.timestamp; + } + this.socket.send(msg); + this.socket.send('status'); + this.socket.send('styles'); + for (var i = 0; i < this._msgQueue.length; i++) { + this.socket.send(this._msgQueue[i].msg); + L.Log.log(this._msgQueue[i].msg, this._msgQueue[i].coords); + } + this._msgQueue = []; + }, + + _onMessage: function (e) { + var imgBytes, index, textMsg; + + if (typeof (e.data) === 'string') { + textMsg = e.data; + } + else if (typeof (e.data) === 'object') { + imgBytes = new Uint8Array(e.data); + index = 0; + // search for the first newline which marks the end of the message + while (index < imgBytes.length && imgBytes[index] !== 10) { + index++; + } + textMsg = String.fromCharCode.apply(null, imgBytes.subarray(0, index)); + } + + if (!textMsg.startsWith('tile:')) { + // log the tile msg separately as we need the tile coordinates + L.Log.log(textMsg, L.INCOMING); + if (imgBytes !== undefined) { + // if it's not a tile, parse the whole message + textMsg = String.fromCharCode.apply(null, imgBytes); + } + } + + if (textMsg.startsWith('status:') && !this._map._docLayer) { + // first status message, we need to create the document layer + var command = this.parseServerCmd(textMsg); + this._map._docLayer = new L.TileLayer('', { + edit: this._map.options.edit, + readOnly: this._map.options.readOnly + }); + this._map.addLayer(this._map._docLayer); + } + this._map._docLayer._onMessage(textMsg, imgBytes, index); + }, + + _onSocketError: function () { + this.fire('error', {msg: 'Socket connection error'}); + }, + + _onSocketClose: function () { + this.fire('error', {msg: 'Socket connection closed'}); + }, + + parseServerCmd: function (msg) { + var tokens = msg.split(/[ \n]+/); + var command = {}; + for (var i = 0; i < tokens.length; i++) { + if (tokens[i].substring(0, 9) === 'tileposx=') { + command.x = parseInt(tokens[i].substring(9)); + } + else if (tokens[i].substring(0, 9) === 'tileposy=') { + command.y = parseInt(tokens[i].substring(9)); + } + else if (tokens[i].substring(0, 2) === 'x=') { + command.x = parseInt(tokens[i].substring(2)); + } + else if (tokens[i].substring(0, 2) === 'y=') { + command.y = parseInt(tokens[i].substring(2)); + } + else if (tokens[i].substring(0, 10) === 'tilewidth=') { + command.tileWidth = parseInt(tokens[i].substring(10)); + } + else if (tokens[i].substring(0, 11) === 'tileheight=') { + command.tileHeight = parseInt(tokens[i].substring(11)); + } + else if (tokens[i].substring(0, 6) === 'width=') { + command.width = parseInt(tokens[i].substring(6)); + } + else if (tokens[i].substring(0, 7) === 'height=') { + command.height = parseInt(tokens[i].substring(7)); + } + else if (tokens[i].substring(0, 5) === 'part=') { + command.part = parseInt(tokens[i].substring(5)); + } + else if (tokens[i].substring(0, 6) === 'parts=') { + command.parts = parseInt(tokens[i].substring(6)); + } + else if (tokens[i].substring(0, 8) === 'current=') { + command.currentPart = parseInt(tokens[i].substring(8)); + } + else if (tokens[i].substring(0, 3) === 'id=') { + // remove newline characters + command.id = tokens[i].substring(3).replace(/(\r\n|\n|\r)/gm, ''); + } + else if (tokens[i].substring(0, 5) === 'type=') { + // remove newline characters + command.type = tokens[i].substring(5).replace(/(\r\n|\n|\r)/gm, ''); + } + else if (tokens[i].substring(0, 9) === 'prefetch=') { + command.preFetch = tokens[i].substring(9); + } + else if (tokens[i].substring(0, 4) === 'cmd=') { + command.errorCmd = tokens[i].substring(4); + } + else if (tokens[i].substring(0, 5) === 'kind=') { + command.errorKind = tokens[i].substring(5); + } + } + if (command.tileWidth && command.tileHeight && this._map._docLayer) { + var scale = command.tileWidth / this._map._docLayer.options.tileWidthTwips; + // scale = 1.2 ^ (10 - zoom) + // zoom = 10 -log(scale) / log(1.2) + command.zoom = Math.round(10 - Math.log(scale) / Math.log(1.2)); + } + return command; + } +}; + +if (typeof String.prototype.startsWith !== 'function') { + String.prototype.startsWith = function (str) { + return this.slice(0, str.length) === str; + }; +} diff --git a/loleaflet/src/layer/Layer.js b/loleaflet/src/layer/Layer.js index 0af279f3c..579d30b5c 100644 --- a/loleaflet/src/layer/Layer.js +++ b/loleaflet/src/layer/Layer.js @@ -56,11 +56,7 @@ L.Layer = L.Evented.extend({ this.fire('add'); map.fire('layeradd', {layer: this}); - }, - - _initDocument: function () {}, - _onMessage: function () {}, - sendMessage: function () {} + } }); diff --git a/loleaflet/src/layer/tile/GridLayer.js b/loleaflet/src/layer/tile/GridLayer.js index ccc9b39fb..58ea647e0 100644 --- a/loleaflet/src/layer/tile/GridLayer.js +++ b/loleaflet/src/layer/tile/GridLayer.js @@ -29,31 +29,9 @@ L.GridLayer = L.Layer.extend({ onAdd: function () { this._initContainer(); - this._selections = new L.LayerGroup(); - this._map.addLayer(this._selections); - this._levels = {}; this._tiles = {}; - this._tileCache = {}; - - this._map._fadeAnimated = false; this._viewReset(); - this._map._docLayer = this; - - if (this._map.socket) { - this._map.socket.onopen = L.bind(this._initDocument, this); - this._map.socket.onmessage = L.bind(this._onMessage, this); - } - if (this._map.socket && this._map.socket.readyState === 1) { - // the connection is already open - this._initDocument(); - } - else if (this._map.socket && this._map.socket.readyState > 1) { - // the connection is closing or is closed - var socket = this._map._initSocket(); - socket.onopen = L.bind(this._initDocument, this); - socket.onmessage = L.bind(this._onMessage, this); - } }, beforeAdd: function (map) { @@ -67,12 +45,6 @@ L.GridLayer = L.Layer.extend({ this._tileZoom = null; clearTimeout(this._preFetchIdle); clearInterval(this._tilesPreFetcher); - if (this._map.socket) { - this._map.socket.onmessage = function () {}; - this._map.socket.onclose = function () {}; - this._map.socket.onerror = function () {}; - this._map.socket.close(); - } if (this._cursorMarker) { this._cursorMarker.remove(); } @@ -472,15 +444,14 @@ L.GridLayer = L.Layer.extend({ this._resetPreFetching(); }, - _move: function (e) { + _move: function () { this._update(); this._resetPreFetching(true); }, _update: function (center, zoom) { var map = this._map; - if (!map || this._documentInfo === '' || - (this.options.useSocket && map.socket && map.socket.readyState !== 1)) { + if (!map || this._documentInfo === '') { return; } @@ -530,7 +501,7 @@ L.GridLayer = L.Layer.extend({ if (newView) { // we know that a new set of tiles that cover the whole view has been requested // so we're able to cancel the previous requests that are being processed - this.sendMessage('canceltiles'); + L.Socket.sendMessage('canceltiles'); for (key in this._tiles) { if (!this._tiles[key].loaded) { L.DomUtil.remove(this._tiles[key].el); @@ -680,21 +651,19 @@ L.GridLayer = L.Layer.extend({ } if (!this._tileCache[key]) { - if (this.options.useSocket && this._map.socket && this._map.socket.readyState === 1) { - var twips = this._coordsToTwips(coords); - var msg = 'tile ' + - 'part=' + coords.part + ' ' + - 'width=' + this._tileSize + ' ' + - 'height=' + this._tileSize + ' ' + - 'tileposx=' + twips.x + ' ' + - 'tileposy=' + twips.y + ' ' + - 'tilewidth=' + this._tileWidthTwips + ' ' + - 'tileheight=' + this._tileHeightTwips; - if (coords.part !== this._currentPart) { - msg += ' prefetch=true'; - } - this.sendMessage(msg, key); + var twips = this._coordsToTwips(coords); + var msg = 'tile ' + + 'part=' + coords.part + ' ' + + 'width=' + this._tileSize + ' ' + + 'height=' + this._tileSize + ' ' + + 'tileposx=' + twips.x + ' ' + + 'tileposy=' + twips.y + ' ' + + 'tilewidth=' + this._tileWidthTwips + ' ' + + 'tileheight=' + this._tileHeightTwips; + if (coords.part !== this._currentPart) { + msg += ' prefetch=true'; } + L.Socket.sendMessage(msg, key); } else { tile.src = this._tileCache[key]; diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js index 2f0330aeb..78129362b 100644 --- a/loleaflet/src/layer/tile/TileLayer.js +++ b/loleaflet/src/layer/tile/TileLayer.js @@ -93,41 +93,38 @@ L.TileLayer = L.GridLayer.extend({ this._msgQueue = []; }, - _initDocument: function () { - if (!this._map.socket) { - this._map.fire('error', {msg: 'Socket initialization error'}); - return; - } - if (this.options.doc) { - var msg = 'load url=' + this.options.doc; - if (this.options.timestamp) { - msg += ' timestamp=' + this.options.timestamp; - } - this.sendMessage(msg); - this.sendMessage('status'); - this.sendMessage('styles'); - } - this._map.on('drag resize zoomend', this._updateScrollOffset, this); - this._map.on('clearselection', this._clearSelections, this); - this._map.on('copy', this._onCopy, this); - this._map.on('zoomend', this._onUpdateCursor, this); - this._map.on('dragstart', this._onDragStart, this); - this._map.on('requestloksession', this._onRequestLOKSession, this); - this._map.on('error', this._mapOnError, this); + onAdd: function (map) { + this._initContainer(); + this._selections = new L.LayerGroup(); + map.addLayer(this._selections); + + this._levels = {}; + this._tiles = {}; + this._tileCache = {}; + + map._fadeAnimated = false; + this._viewReset(); + map.on('drag resize zoomend', this._updateScrollOffset, this); + map.on('clearselection', this._clearSelections, this); + map.on('copy', this._onCopy, this); + map.on('zoomend', this._onUpdateCursor, this); + map.on('dragstart', this._onDragStart, this); + map.on('requestloksession', this._onRequestLOKSession, this); + map.on('error', this._mapOnError, this); this._startMarker.on('drag dragend', this._onSelectionHandleDrag, this); this._endMarker.on('drag dragend', this._onSelectionHandleDrag, this); - this._textArea = this._map._textArea; + this._textArea = map._textArea; this._textArea.focus(); if (this.options.readOnly) { - this._map.setPermission('readonly'); + map.setPermission('readonly'); } else if (this.options.edit) { - this._map.setPermission('edit'); + map.setPermission('edit'); } else { - this._map.setPermission('view'); + map.setPermission('view'); } - this._map.fire('statusindicator', {statusType: 'loleafletloaded'}); + map.fire('statusindicator', {statusType: 'loleafletloaded'}); }, getEvents: function () { @@ -177,31 +174,7 @@ L.TileLayer = L.GridLayer.extend({ return tile; }, - _onMessage: function (evt) { - var bytes, index, textMsg; - - if (typeof (evt.data) === 'string') { - textMsg = evt.data; - } - else if (typeof (evt.data) === 'object') { - bytes = new Uint8Array(evt.data); - index = 0; - // search for the first newline which marks the end of the message - while (index < bytes.length && bytes[index] !== 10) { - index++; - } - textMsg = String.fromCharCode.apply(null, bytes.subarray(0, index)); - } - - if (!textMsg.startsWith('tile:')) { - // log the tile msg separately as we need the tile coordinates - L.Log.log(textMsg, L.INCOMING); - if (bytes !== undefined) { - // if it's not a tile, parse the whole message - textMsg = String.fromCharCode.apply(null, bytes); - } - } - + _onMessage: function (textMsg, imgBytes, index) { if (textMsg.startsWith('cursorvisible:')) { var command = textMsg.match('cursorvisible: true'); this._isCursorVisible = command ? true : false; @@ -264,7 +237,7 @@ L.TileLayer = L.GridLayer.extend({ this._onUpdateGraphicSelection(); } else if (textMsg.startsWith('invalidatetiles:') && !textMsg.match('EMPTY')) { - command = this._parseServerCmd(textMsg); + command = L.Socket.parseServerCmd(textMsg); if (command.x === undefined || command.y === undefined || command.part === undefined) { strTwips = textMsg.match(/\d+/g); command.x = parseInt(strTwips[0]); @@ -319,7 +292,7 @@ L.TileLayer = L.GridLayer.extend({ cursorPos = cursorPos.divideBy(this._tileSize); toRequest.sort(function(x, y) {return x.coords.distanceTo(cursorPos) - y.coords.distanceTo(cursorPos);}); for (var i = 0; i < toRequest.length; i++) { - this.sendMessage(toRequest[i].msg, toRequest[i].key); + L.Socket.sendMessage(toRequest[i].msg, toRequest[i].key); } for (key in this._tileCache) { // compute the rectangle that each tile covers in the document based @@ -355,7 +328,7 @@ L.TileLayer = L.GridLayer.extend({ } } else if (textMsg.startsWith('status:')) { - command = this._parseServerCmd(textMsg); + command = L.Socket.parseServerCmd(textMsg); if (command.width && command.height && this._documentInfo !== textMsg) { this._docWidthTwips = command.width; this._docHeightTwips = command.height; @@ -376,7 +349,7 @@ L.TileLayer = L.GridLayer.extend({ }); } else { - this.sendMessage('setclientpart part=' + this._currentPart); + L.Socket.sendMessage('setclientpart part=' + this._currentPart); var partNames = textMsg.match(/[^\r\n]+/g); // only get the last matches partNames = partNames.slice(partNames.length - this._parts); @@ -405,11 +378,11 @@ L.TileLayer = L.GridLayer.extend({ this._map.fire('statusindicator', {statusType : 'finish'}); } else if (textMsg.startsWith('tile:')) { - command = this._parseServerCmd(textMsg); + command = L.Socket.parseServerCmd(textMsg); coords = this._twipsToCoords(command); coords.z = command.zoom; coords.part = command.part; - var data = bytes.subarray(index + 1); + var data = imgBytes.subarray(index + 1); // read the tile data var strBytes = ''; @@ -488,7 +461,7 @@ L.TileLayer = L.GridLayer.extend({ clearTimeout(this._selectionContentRequest); } this._selectionContentRequest = setTimeout(L.bind(function () { - this.sendMessage('gettextselection mimetype=text/plain;charset=utf-8');}, this), 100); + L.Socket.sendMessage('gettextselection mimetype=text/plain;charset=utf-8');}, this), 100); } this._onUpdateTextSelection(); } @@ -521,46 +494,11 @@ L.TileLayer = L.GridLayer.extend({ this._map.fire('updatestyles', {styles: this._docStyles}); } else if (textMsg.startsWith('error:')) { - command = this._parseServerCmd(textMsg); + command = L.Socket.parseServerCmd(textMsg); this._map.fire('error', {cmd: command.errorCmd, kind: command.errorKind}); } }, - _onOpenSocket: function () { - for (var i = 0; i < this._msgQueue.length; i++) { - this._map.socket.send(this._msgQueue[i].msg); - L.Log.log(this._msgQueue[i].msg, this._msgQueue[i].coords); - } - this._msgQueue = []; - }, - - sendMessage: function (msg, coords) { - var socketState = this._map.socket.readyState; - if (socketState === 2 || socketState === 3) { - var socket = this._map._initSocket(); - if (socket) { - socket.onopen = L.bind(this._onOpenSocket, this); - socket.onmessage = L.bind(this._onMessage, this); - // clear queue - this._msgQueue = []; - // reload interrupted document - this._msgQueue.push({msg:'load part=' + this._currentPart + ' url=' + this.options.doc + - (this.options.timestamp ? ' timestamp=' + this.options.timestamp : ''), coords: coords}); - // push next message - this._msgQueue.push({msg: msg, coords: coords}); - } - } - - if (socketState === 0) { - // push message while trying to connect socket again. - this._msgQueue.push({msg: msg, coords: coords}); - } - else if (socketState === 1) { - this._map.socket.send(msg); - L.Log.log(msg, L.OUTGOING, coords); - } - }, - _tileOnLoad: function (done, tile) { done(null, tile); }, @@ -579,70 +517,6 @@ L.TileLayer = L.GridLayer.extend({ } }, - _parseServerCmd: function (msg) { - var tokens = msg.split(/[ \n]+/); - var command = {}; - for (var i = 0; i < tokens.length; i++) { - if (tokens[i].substring(0, 9) === 'tileposx=') { - command.x = parseInt(tokens[i].substring(9)); - } - else if (tokens[i].substring(0, 9) === 'tileposy=') { - command.y = parseInt(tokens[i].substring(9)); - } - else if (tokens[i].substring(0, 2) === 'x=') { - command.x = parseInt(tokens[i].substring(2)); - } - else if (tokens[i].substring(0, 2) === 'y=') { - command.y = parseInt(tokens[i].substring(2)); - } - else if (tokens[i].substring(0, 10) === 'tilewidth=') { - command.tileWidth = parseInt(tokens[i].substring(10)); - } - else if (tokens[i].substring(0, 11) === 'tileheight=') { - command.tileHeight = parseInt(tokens[i].substring(11)); - } - else if (tokens[i].substring(0, 6) === 'width=') { - command.width = parseInt(tokens[i].substring(6)); - } - else if (tokens[i].substring(0, 7) === 'height=') { - command.height = parseInt(tokens[i].substring(7)); - } - else if (tokens[i].substring(0, 5) === 'part=') { - command.part = parseInt(tokens[i].substring(5)); - } - else if (tokens[i].substring(0, 6) === 'parts=') { - command.parts = parseInt(tokens[i].substring(6)); - } - else if (tokens[i].substring(0, 8) === 'current=') { - command.currentPart = parseInt(tokens[i].substring(8)); - } - else if (tokens[i].substring(0, 3) === 'id=') { - // remove newline characters - command.id = tokens[i].substring(3).replace(/(\r\n|\n|\r)/gm, ''); - } - else if (tokens[i].substring(0, 5) === 'type=') { - // remove newline characters - command.type = tokens[i].substring(5).replace(/(\r\n|\n|\r)/gm, ''); - } - else if (tokens[i].substring(0, 9) === 'prefetch=') { - command.preFetch = tokens[i].substring(9); - } - else if (tokens[i].substring(0, 4) === 'cmd=') { - command.errorCmd = tokens[i].substring(4); - } - else if (tokens[i].substring(0, 5) === 'kind=') { - command.errorKind = tokens[i].substring(5); - } - } - if (command.tileWidth && command.tileHeight) { - var scale = command.tileWidth / this.options.tileWidthTwips; - // scale = 1.2 ^ (10 - zoom) - // zoom = 10 -log(scale) / log(1.2) - command.zoom = Math.round(10 - Math.log(scale) / Math.log(1.2)); - } - return command; - }, - _onTileRemove: function (e) { e.tile.onload = null; }, @@ -652,22 +526,22 @@ L.TileLayer = L.GridLayer.extend({ }, _postMouseEvent: function(type, x, y, count) { - this.sendMessage('mouse type=' + type + + L.Socket.sendMessage('mouse type=' + type + ' x=' + x + ' y=' + y + ' count=' + count); }, _postKeyboardEvent: function(type, charcode, keycode) { - this.sendMessage('key type=' + type + + L.Socket.sendMessage('key type=' + type + ' char=' + charcode + ' key=' + keycode); }, _postSelectGraphicEvent: function(type, x, y) { - this.sendMessage('selectgraphic type=' + type + + L.Socket.sendMessage('selectgraphic type=' + type + ' x=' + x + ' y=' + y); }, _postSelectTextEvent: function(type, x, y) { - this.sendMessage('selecttext type=' + type + + L.Socket.sendMessage('selecttext type=' + type + ' x=' + x + ' y=' + y); }, @@ -802,7 +676,7 @@ L.TileLayer = L.GridLayer.extend({ }, _onRequestLOKSession: function () { - this.sendMessage('requestloksession'); + L.Socket.sendMessage('requestloksession'); } }); diff --git a/loleaflet/src/map/Map.js b/loleaflet/src/map/Map.js index c5a3cad8b..a8e8129b1 100644 --- a/loleaflet/src/map/Map.js +++ b/loleaflet/src/map/Map.js @@ -6,14 +6,10 @@ L.Map = L.Evented.extend({ options: { crs: L.CRS.Simple, - - /* - center: LatLng, - zoom: Number, - layers: Array, - */ - - doubleClickZoom: false, + center: [0, 0], + zoom: 10, + minZoom: 1, + maxZoom: 20, fadeAnimation: true, trackResize: true, markerZoomAnimation: true @@ -22,9 +18,6 @@ L.Map = L.Evented.extend({ initialize: function (id, options) { // (HTMLElement or String, Object) options = L.setOptions(this, options); - if (options.server) { - this._initSocket(); - } this._initContainer(id); this._initLayout(); @@ -57,6 +50,7 @@ L.Map = L.Evented.extend({ L.Icon.Default.imagePath = this.options.imagePath; } this._addLayers(this.options.layers); + L.Socket.connect(this); }, @@ -256,6 +250,7 @@ L.Map = L.Evented.extend({ this.removeLayer(this._docLayer); } this.removeControls(); + L.Socket.close(); return this; }, @@ -449,21 +444,6 @@ L.Map = L.Evented.extend({ } }, - // map initialization methods - _initSocket: function () { - try { - this.socket = new WebSocket(this.options.server); - } catch (e) { - this.fire('error', {msg: 'Socket connection error'}); - return; - } - this.socket.onerror = L.bind(this._onSocketError, this); - this.socket.onclose = L.bind(this._onSocketClose, this); - this.socket.binaryType = 'arraybuffer'; - return this.socket; - }, - - _initContainer: function (id) { var container = this._container = L.DomUtil.get(id); @@ -764,14 +744,6 @@ L.Map = L.Evented.extend({ max = this.getMaxZoom(); return Math.max(min, Math.min(max, zoom)); - }, - - _onSocketError: function () { - this.fire('error', {msg: 'Socket connection error'}); - }, - - _onSocketClose: function () { - this.fire('error', {msg: 'Socket connection closed'}); } }); diff --git a/loleaflet/src/map/handler/Map.DoubleClickZoom.js b/loleaflet/src/map/handler/Map.DoubleClickZoom.js index 8f3814069..fb9cf92bc 100644 --- a/loleaflet/src/map/handler/Map.DoubleClickZoom.js +++ b/loleaflet/src/map/handler/Map.DoubleClickZoom.js @@ -3,7 +3,7 @@ */ L.Map.mergeOptions({ - doubleClickZoom: true + doubleClickZoom: false }); L.Map.DoubleClickZoom = L.Handler.extend({