diff --git a/examples/maps/world_map_with_countries/index.html b/examples/maps/world_map_with_countries/index.html index fa0fe639..b636b69e 100644 --- a/examples/maps/world_map_with_countries/index.html +++ b/examples/maps/world_map_with_countries/index.html @@ -5,7 +5,7 @@ - + diff --git a/examples/maps/world_map_with_countries/js/example.js b/examples/maps/world_map_with_countries/js/example.js index f4ba0f1b..e93b3295 100644 --- a/examples/maps/world_map_with_countries/js/example.js +++ b/examples/maps/world_map_with_countries/js/example.js @@ -7,7 +7,7 @@ on a world map. Ox.load(['UI', 'Geo'], function() { - var $map = Ox.LeafletMap({ + var $map = Ox.Map({ keys: ['region'], markerColor: function(place) { return Ox.getGeoColor(place.region); diff --git a/source/Ox.js b/source/Ox.js index 16d1ce97..675fbed3 100644 --- a/source/Ox.js +++ b/source/Ox.js @@ -37,7 +37,7 @@ } function getPath() { - var index, regexp = /Ox\.js(\?\d+|)$/, + var index, regexp = /Ox\.js(\?[\d\.]+|)$/, scripts = document.getElementsByTagName('script'), src; for (index = scripts.length - 1; index >= 0; index--) { src = scripts[index].src; diff --git a/source/Ox/js/Constants.js b/source/Ox/js/Constants.js index 8f88ca13..1fe2d45b 100644 --- a/source/Ox/js/Constants.js +++ b/source/Ox/js/Constants.js @@ -63,7 +63,8 @@ Ox.LOCALE_NAMES = { 'el': 'Ελληνικά', 'en': 'English', 'fr': 'Français', - 'hi': 'हिन्दी' + 'hi': 'हिन्दी', + 'tr': 'Türkçe' }; //@ Ox.LOCALES Locales per module Ox.LOCALES = {}; diff --git a/source/Ox/json/locale.tr.json b/source/Ox/json/locale.tr.json new file mode 100644 index 00000000..81c526bc --- /dev/null +++ b/source/Ox/json/locale.tr.json @@ -0,0 +1,89 @@ +{ + "%": "%", + ",": ",", + ".": ".", + "%A, %B %e, %Y": "%A, %B %e, %Y", + "%a, %b %e, %Y": "%a, %b %e, %Y", + "AD": "MS", + "AM": "", + "Apr": "", + "April": "Nisan", + "Aug": "", + "August": "Ağustos", + "BC": "MÖ", + "%B %e, %Y": "", + "%b %e, %Y": "", + "d": "g", + "day": "gün", + "days": "gün", + "days{2}": "gün", + "Dec": "", + "December": "Aralık", + "Fall": "Düşmek", + "Feb": "", + "February": "Şubat", + "Fri": "", + "Friday": "Cuma", + "h": "s", + "hour": "saat", + "hours": "saat", + "hours{2}": "saat", + "%I:%M %p": "", + "%I:%M:%S %p": "", + "Jan": "", + "January": "Ocak", + "Jul": "", + "July": "Temmuz", + "Jun": "", + "June": "Haziran", + "m": "d", + "Mar": "", + "March": "Mart", + "May": "Mayıs", + "%m/%d/%Y": "", + "%m/%d/%y": "", + "minute": "dakika", + "minutes": "dakika", + "minutes{2}": "dakika", + "Mon": "", + "Monday": "Pazartesi", + "nd": ".", + "nd{22}": ".", + "no": "hayır", + "Nov": "", + "November": "Kasım", + "Oct": "", + "October": "Ekim", + "PM": "", + "rd": ".", + "rd{23}": ".", + "s": "s", + "Sat": "", + "Saturday": "Cumartesi", + "second": "saniye", + "seconds": "saniye", + "seconds{2}": "saniye", + "Sep": "", + "September": "Eylül", + "Spring": "Bahar", + "st": ".", + "st{21}": ".", + "Summer": "Yaz", + "Sun": "", + "Sunday": "Pazar", + "th": ".", + "th{11}": ".", + "th{12}": ".", + "th{13}": ".", + "Thu": "", + "Thursday": "Perşembe", + "Tue": "", + "Tuesday": "Salı", + "Wed": "", + "Wednesday": "Çarşamba", + "Winter": "kış", + "y": "yy", + "year": "yıl", + "years": "yıl", + "years{2}": "yıl" +} diff --git a/source/UI/css/UI.css b/source/UI/css/UI.css index e6ea4dca..2b29ba4e 100644 --- a/source/UI/css/UI.css +++ b/source/UI/css/UI.css @@ -16,6 +16,9 @@ a:hover, .OxLink:hover { blockquote { margin: 0 1.5em 0 1.5em; } +html, body { + overscroll-behavior: none; +} body { margin: 0; cursor: default; @@ -2458,6 +2461,7 @@ Video font-size: 8px; line-height: 10px; text-align: center; + text-wrap: balance; text-overflow: ellipsis; text-shadow: rgba(0, 0, 0, 1) 1px 1px 1px; color: rgb(255, 255, 255); diff --git a/source/UI/css/theme.css b/source/UI/css/theme.css index 5c62887e..83ac746d 100644 --- a/source/UI/css/theme.css +++ b/source/UI/css/theme.css @@ -1188,8 +1188,10 @@ Scrollbars background: -webkit-linear-gradient(left, $buttonActiveGradient); } -body.$themeClass { - scrollbar-color: $bodyBorder $bodyBackground; +@supports not selector(::-webkit-scrollbar) { + body.$themeClass { + scrollbar-color: $bodyBorder $bodyBackground; + } } /* diff --git a/source/UI/js/Core/Element.js b/source/UI/js/Core/Element.js index 5e1ca456..df17ea0b 100644 --- a/source/UI/js/Core/Element.js +++ b/source/UI/js/Core/Element.js @@ -710,6 +710,7 @@ Ox.Focus.removeElement(this.oxid); this.self(_).unbindKeyboard(); this.$tooltip && this.$tooltip.remove(); + jQuery.cleanData(this.$element); delete Ox.$elements[this.oxid]; // If setElement($element) was used, delete $element too delete Ox.$elements[this.$element.oxid]; @@ -738,6 +739,7 @@ this.findElements().forEach(function($element) { $element.removeElement(false); }); + jQuery.cleanData(this.$element); this.$element.replaceWith($element); if ($element.$element) { // $element is Ox.Element this.$element = $element.$element; diff --git a/source/UI/js/Core/Event.js b/source/UI/js/Core/Event.js index 8df1650a..31c1fee8 100644 --- a/source/UI/js/Core/Event.js +++ b/source/UI/js/Core/Event.js @@ -438,7 +438,7 @@ Ox.forEach( Ox.makeObject(Ox.slice(arguments)), function(data, event) { - target.postMessage(JSON.stringify({ + target && target.postMessage(JSON.stringify({ data: data, event: event, target: isParent ? Ox.oxid : null diff --git a/source/UI/js/Core/Request.js b/source/UI/js/Core/Request.js index cadc6e5a..b5980252 100644 --- a/source/UI/js/Core/Request.js +++ b/source/UI/js/Core/Request.js @@ -25,6 +25,7 @@ Ox.Request = (function() { $element; return { + async: true, /*@ bindEvent Bind event @@ -139,6 +140,7 @@ Ox.Request = (function() { } else { pending[req] = true; $.ajax({ + async: Ox.Request.async, beforeSend: function(request) { var csrftoken = Ox.Cookies('csrftoken'); if (csrftoken) { diff --git a/source/UI/js/Form/ArrayEditable.js b/source/UI/js/Form/ArrayEditable.js index f361569d..11f62ff9 100644 --- a/source/UI/js/Form/ArrayEditable.js +++ b/source/UI/js/Form/ArrayEditable.js @@ -25,6 +25,7 @@ Ox.ArrayEditable = function(options, self) { var that = Ox.Element({}, self) .defaults({ clickLink: null, + confirmDeleteDialog: null, editable: true, format: null, getSortValue: null, @@ -116,23 +117,31 @@ Ox.ArrayEditable = function(options, self) { self.selected = getSelectedPosition(); - function deleteItem(id) { + function deleteItem(id, empty) { // it is possible to delete an (empty-value) item // by selecting another one id = id || self.options.selected; - var position = Ox.getIndexById(self.options.items, id) - if (self.options.editable) { - self.options.items.splice(position, 1); - renderItems(); - that.triggerEvent('delete', {id: id}); - self.editing = false; - if (self.options.selected == id) { - self.selected = -1; - self.options.selected = ''; - } else if (self.options.selected) { - self.selected = Ox.getIndexById(self.options.item, self.options.selected) + + (self.options.confirmDeleteDialog && !empty ? self.options.confirmDeleteDialog: Ox.noop)({ + items: Ox.isArray(id) ? id : [id], + }, function(result) { + if (self.options.editable) { + (Ox.isArray(id) ? id : [id]).forEach(id => { + var position = Ox.getIndexById(self.options.items, id) + self.options.items.splice(position, 1); + that.triggerEvent('delete', {id: id}); + }) + renderItems(); + self.editing = false; + if (self.options.selected == id) { + self.selected = -1; + self.options.selected = ''; + } else if (self.options.selected) { + self.selected = Ox.getIndexById(self.options.item, self.options.selected) + } } - } + }) + } function doubleclick(e) { @@ -146,12 +155,20 @@ Ox.ArrayEditable = function(options, self) { } } + function getId(position) { + return position > -1 ? self.options.items[position].id : ''; + } + function getSelectedId() { - return self.selected > -1 ? self.options.items[self.selected].id : ''; + return getId(self.selected); + } + + function getPosition(id) { + return Ox.getIndexById(self.options.items, id); } function getSelectedPosition() { - return Ox.getIndexById(self.options.items, self.options.selected); + return getPosition(self.options.selected); } function renderItems(blur) { @@ -267,6 +284,50 @@ Ox.ArrayEditable = function(options, self) { : that.triggerEvent('selectprevious'); } } + function toggleItem(idOrPosition) { + var id, position; + if (Ox.isString(idOrPosition)) { + id = idOrPosition + position = getPosition(id); + } else { + position = idOrPosition + id = getId(position); + } + if (!Ox.isArray(self.options.selected)) { + self.options.selected = [self.options.selected] + } + if (!Ox.isArray(self.selected)) { + self.selected = [self.selected] + } + if (!self.options.selected.includes(id)) { + var minPos, maxPos; + if (Ox.min(self.selected) > position) { + minPos = position + maxPos = Ox.min(self.selected) + } else { + minPos = Ox.max(self.selected) + 1 + maxPos = position + 1 + } + Ox.range(minPos, maxPos).forEach(pos => { + self.selected.push(pos) + self.options.selected.push(getId(pos)) + }) + + } + that.find('.OxSelected').removeClass('OxSelected').removeClass('OxMultiple'); + that.find('.OxGroup').removeClass('OxGroup') + if (self.options.selected.length == 1) { + self.options.selected = self.options.selected[0] + self.selected = self.selected[0] + self.$items[self.selected].addClass('OxSelected'); + self.options.highlightGroup && that.updateItemGroup() + } else { + Ox.forEach(self.selected, function(selected) { + self.$items[selected].addClass('OxSelected').addClass('OxMultiple'); + }) + } + triggerSelectEvent(); + } function selectItem(idOrPosition) { if (Ox.isString(idOrPosition)) { @@ -327,8 +388,14 @@ Ox.ArrayEditable = function(options, self) { position = $element.data('position'); // if clicked on an element if (position != self.selected) { - // select another item - selectItem(position); + if (e.shiftKey && self.selected != -1) { + // add/remove item from multiple selection + document.getSelection().removeAllRanges(); + toggleItem(position); + } else { + // select another item + selectItem(position); + } } else if (e.metaKey) { // or deselect current item selectNone(); @@ -370,7 +437,7 @@ Ox.ArrayEditable = function(options, self) { var item = Ox.getObjectById(self.options.items, id); Ox.Log('AE', 'submitItem', id, item) if (value === '') { - deleteItem(item.id); + deleteItem(item.id, true); } else { that.triggerEvent(item.value === value ? 'blur' : 'submit', { id: item.id, diff --git a/source/UI/js/Form/ButtonGroup.js b/source/UI/js/Form/ButtonGroup.js index c1c5ff5e..d8eb06ab 100644 --- a/source/UI/js/Form/ButtonGroup.js +++ b/source/UI/js/Form/ButtonGroup.js @@ -31,18 +31,29 @@ Ox.ButtonGroup = function(options, self) { .options(options || {}) .update({ value: function() { - // fixme: this doesn't work in cases where - // multiple buttons can be selected - var position = Ox.getIndexById( - self.options.buttons, self.options.value - ); - if (position > -1) { - self.$buttons[position].trigger('click'); - } else if (self.options.min == 0) { - self.$buttons.forEach(function($button, i) { - $button.options('value') && $button.trigger('click'); - }); + var positions = [], + values = Ox.makeArray(self.options.value); + + Ox.forEach(values, function(value) { + var position = Ox.getIndexById( + self.options.buttons, value + ); + + if (position > -1) { + positions.push(position); + } + }); + + if (positions.length < self.options.min) { + return; } + + Ox.forEach(self.$buttons, function(button, pos) { + var enabled = positions.indexOf(pos) > -1; + if (enabled !== button.value()) { + button.trigger('click'); + } + }); } }) .addClass( diff --git a/source/UI/js/Form/FormPanel.js b/source/UI/js/Form/FormPanel.js index b6b3409c..9eb7efe9 100644 --- a/source/UI/js/Form/FormPanel.js +++ b/source/UI/js/Form/FormPanel.js @@ -15,11 +15,18 @@ Ox.FormPanel = function(options, self) { var that = Ox.Element({}, self) .defaults({ form: [], - listSize: 256 + listSize: 256, + section: null }) - .options(options || {}); + .options(options || {}) + .update({ + section: setSection + }); - self.section = 0; + if (self.options.section === null) { + self.options.section = self.options.form[0].id; + } + self.section = Ox.getIndexById(self.options.form, self.options.section); self.sectionTitle = self.options.form[self.section].title; self.$list = Ox.TableList({ columns: [ @@ -62,7 +69,7 @@ Ox.FormPanel = function(options, self) { }), max: 1, min: 1, - selected: [self.options.form[0].id], + selected: [self.options.section], sort: [{key: 'id', operator: '+'}], unique: 'id', width: self.options.listSize @@ -70,7 +77,11 @@ Ox.FormPanel = function(options, self) { select: function(data) { self.$sections[self.section].hide(); self.section = Ox.getIndexById(self.options.form, data.ids[0]); + if (self.section == -1) { + self.section = 0 + } self.$sections[self.section].show(); + self.options.section = self.options.form[self.section].id; that.triggerEvent('select', {section: data.ids[0]}); } }); @@ -130,7 +141,18 @@ Ox.FormPanel = function(options, self) { }); }); - self.$sections[0].show(); + self.$sections[self.section].show(); + + function setSection() { + var id = self.options.section, + section = Ox.getIndexById(self.options.form, id); + if (section > -1 && self.section != section) { + self.$sections[self.section].hide(); + self.section = section; + self.$list.options('selected', [id]); + self.$sections[self.section].show(); + } + }; that.setElement(Ox.SplitPanel({ elements: [ @@ -191,13 +213,24 @@ Ox.FormPanel = function(options, self) { values values @*/ that.values = function() { - var values = {}; - self.options.form.forEach(function(section, i) { - values[section.id] = self.$forms[i].values(); - }); - return values; + if (arguments.length === 0) { + var values = {}; + self.options.form.forEach(function(section, i) { + values[section.id] = self.$forms[i].values(); + }); + return values; + } else { + var sections = arguments[0]; + + self.options.form.forEach(function(form, i) { + if (form.id in sections) { + self.$forms[i].values(sections[form.id]); + } + }); + } }; + return that; }; diff --git a/source/UI/js/List/List.js b/source/UI/js/List/List.js index b5421c02..0c0f9bb1 100644 --- a/source/UI/js/List/List.js +++ b/source/UI/js/List/List.js @@ -624,7 +624,7 @@ Ox.List = function(options, self) { } function getPageByPosition(pos) { - return Math.floor(pos / self.options.pageLength); + return Math.floor(pos / self.pageLength); } function getPageByScrollPosition(pos) { diff --git a/source/UI/js/Map/LeafletMap.js b/source/UI/js/Map/LeafletMap.js deleted file mode 100644 index d58a39ba..00000000 --- a/source/UI/js/Map/LeafletMap.js +++ /dev/null @@ -1,1627 +0,0 @@ -'use strict'; - -/*@ -Ox.Map Basic map object - # DESCRIPTION -------------------------------------------------------------- - `Ox.Map` is a wrapper around the [Google Maps - API](http://code.google.com/apis/maps/documentation/javascript/). - # ARGUMENTS ---------------------------------------------------------------- - options options - clickable If true, clicking on the map finds a place - editable If true, places are editable - find Initial query - findPlaceholder Placeholder text for the find input element - keys Additional place properties to be requested - markerColor <[n]|f|s|'auto'> Color of place markers ([r, g, b]) - markerSize Size of place markers in px - markerTooltip Format function for place marker tooltips - maxMarkers Maximum number of markers to be displayed - places <[o]|f|null> Array of, or function that returns, place objects - countryCode ISO 3166 country code - east Longitude of the eastern boundary in degrees - editable If true, the place is editable - geoname Geoname (like "Paris, Île-de-France, France") - lat Latitude in degrees - lng Longitude in degrees - name Name (like "Paris") - north Latitude of the northern boundary in degrees - south Latitude of the southern boundary in degrees - type Type (like "city" or "country") - west Longitude of the western boundary in degrees - selected Id of the selected place - showControls If true, show controls - showLabels If true, show labels on the map - showStatusbar If true, the map has a statusbar - showToolbar If true, the map has a toolbar - showZoombar If true, the map has a zoombar - zoomOnlyWhenFocused If true, scroll-zoom only when focused - self Shared private variable - # USAGE -------------------------------------------------------------------- - ([options[, self]]) -> Map object - # EVENTS --------------------------------------------------------------- - addplace Fires when a place has been added - place Place object - editplace Fires when a place has been edited - place Place object - geocode Fires when a google geocode request returns - latLng Query coordinates, or undefined - lat latitude - lng longitude - address Query string, or undefined - results <[o]> Google Maps geocode results - address_components <[o]> Address components - long_name Long name - short_name Short name - types <[s]> Types (like "country" or "political") - formatted_address Formatted address - geometry Geometry - bounds Bounds - northEast North-east corner - lat Latitude - lng Longitude - southWest South-west corner - lat Latitude - lng Longitude - location Location - lat Latitude - lng Longitude - location_type Location type (like "APPROXIMATE") - viewport Viewport - northEast North-east corner - lat Latitude - lng Longitude - southWest South-west corner - lat Latitude - lng Longitude - types <[s]> Types (like "country" or "political") - load load - select Fires when a place has been selected or deselected - place Place object - selectplace Deprecated - togglecontrols togglecontrols - togglelabels togglelabels -@*/ - -Ox.LeafletMap = function(options, self) { - - self = self || {}; - var that = Ox.Element({}, self) - .defaults({ - // fixme: isClickable? - clickable: false, - editable: false, - find: '', - findPlaceholder: 'Find', - keys: [], - markerColor: 'auto', - markerSize: 'auto', - markerTooltip: function(place) { - return place.name || 'Unnamed'; - }, - maxMarkers: 100, - places: null, - selected: '', - showControls: false, - showLabels: false, - showStatusbar: false, - showToolbar: false, - showZoombar: false, - zoomOnlyWhenFocused: false - // fixme: width, height - }) - .options(options || {}) - .update({ - find: function() { - self.$findInput - .value(self.options.find) - .triggerEvent('submit', {value: self.options.find}); - }, - height: function() { - that.css({height: self.options.height + 'px'}); - that.resizeMap(); - }, - places: function() { - if (Ox.isArray(self.options.places)) { - self.options.places.forEach(function(place) { - if (Ox.isUndefined(place.id)) { - place.id = Ox.encodeBase32(Ox.uid()); - } - }); - if (self.options.selected && !Ox.getObjectById( - self.options.places, self.options.selected - )) { - self.options.selected = ''; - selectPlace(null); - } - self.options.places = Ox.api(self.options.places, { - geo: true, - sort: '-area' - }); - } - self.loaded && getMapBounds(function(mapBounds) { - if (mapBounds) { - self.map.fitBounds(mapBounds); - } else { - self.map.setZoom(self.minZoom); - self.map.setCenter([0, 0]); - } - // fixme: the following is just a guess - self.boundsChanged = true; - mapChanged(); - self.options.selected && selectPlace(self.options.selected); - }); - }, - selected: function() { - selectPlace(self.options.selected || null); - }, - type: function() { - // ... - }, - width: function() { - that.css({width: self.options.width + 'px'}); - that.resizeMap(); - } - }) - .addClass('OxMap') - .bindEvent({ - gainfocus: function() { - self.options.zoomOnlyWhenFocused && self.map.setOptions({scrollwheel: true}); - }, - losefocus: function() { - self.options.zoomOnlyWhenFocused && self.map.setOptions({scrollwheel: false}); - }, - key_0: function() { - panToPlace() - }, - key_c: toggleControls, - key_down: function() { - pan(0, 1); - }, - key_enter: pressEnter, - key_escape: pressEscape, - key_equal: function() { - zoom(1); - }, - key_l: toggleLabels, - key_left: function() { - pan(-1, 0); - }, - 'key_meta': function() { - self.metaKey = true; - $(document).one({ - keyup: function() { - self.metaKey = false; - } - }); - }, - key_minus: function() { - zoom(-1); - }, - key_right: function() { - pan(1, 0); - }, - key_shift: function() { - self.shiftKey = true; - $(document).one({ - keyup: function() { - self.shiftKey = false; - } - }); - }, - key_shift_down: function() { - pan(0, 2); - }, - key_shift_0: function() { - zoomToPlace(); - }, - key_shift_equal: function() { - zoom(2); - }, - key_shift_left: function() { - pan(-2, 0); - }, - key_shift_minus: function() { - zoom(-2); - }, - key_shift_right: function() { - pan(2, 0); - }, - key_shift_up: function() { - pan(0, -2); - }, - key_up: function() { - pan(0, -1); - }, - key_z: undo, - mousedown: function(e) { - !$(e.target).is('input') && that.gainFocus(); - } - }); - - // HANDLE DEPRECATED OPTIONS - options && ['statusbar', 'toolbar', 'zoombar'].forEach(function(key) { - if (options[key]) { - self.options['show' + Ox.toTitleCase(key)] = options[key]; - } - }); - - //FIXME: duplicated in update - if (Ox.isArray(self.options.places)) { - self.options.places.forEach(function(place) { - if (Ox.isUndefined(place.id)) { - place.id = Ox.encodeBase32(Ox.uid()); - } - }); - self.options.places = Ox.api(self.options.places, { - geo: true, - sort: '-area' - }); - } - - self.mapHeight = getMapHeight(); - self.metaKey = false; - self.minZoom = getMinZoom(); - self.placeKeys = [ - 'id', 'name', 'alternativeNames', 'geoname', 'countryCode', 'type', - 'lat', 'lng', 'south', 'west', 'north', 'east', 'area', - 'editable' - ].concat(self.options.keys); - self.places = [], - self.resultPlace = null; - self.scaleMeters = [ - 50000000, 20000000, 10000000, - 5000000, 2000000, 1000000, - 500000, 200000, 100000, - 50000, 20000, 10000, - 5000, 2000, 1000, - 500, 200, 100, - 50, 20, 10 - ]; - self.shiftKey = false, - self.tileSize = 256; - - if (self.options.showToolbar) { - self.$toolbar = Ox.Bar({ - size: 24 - }) - .appendTo(that); - self.$menu = Ox.MenuButton({ - items: [ - { - id: 'toggleLabels', - title: self.options.showLabels - ? [Ox._('Hide Labels'), Ox._('Show Labels')] - : [Ox._('Show Labels'), Ox._('Hide Labels')], - keyboard: 'l' - }, - { - id: 'toggleControls', - title: self.options.showControls - ? [Ox._('Hide Controls'), Ox._('Show Controls')] - : [Ox._('Show Controls'), Ox._('Hide Controls')], - keyboard: 'c' - } - ], - title: 'set', - tooltip: Ox._('Map Options'), - type: 'image' - }) - .css({float: 'left', margin: '4px'}) - .bindEvent({ - click: function(data) { - if (data.id == 'toggleLabels') { - toggleLabels(); - } else if (data.id == 'toggleControls') { - toggleControls(); - } - } - }) - .appendTo(self.$toolbar); - self.$findInput = Ox.Input({ - clear: true, - placeholder: self.options.findPlaceholder, - width: 192 - }) - .css({float: 'right', margin: '4px 4px 4px 2px'}) - .bindEvent({ - submit: submitFind - }) - .appendTo(self.$toolbar); - self.$loadingIcon = Ox.LoadingIcon({ - size: 16 - }) - .css({float: 'right', margin: '4px 2px 4px 2px'}) - .appendTo(self.$toolbar); - } - - self.$map = Ox.Element() - .css({ - left: 0, - top: self.options.showToolbar * 24 + 'px', - right: 0, - bottom: self.options.showZoombar * 16 + self.options.showStatusbar * 24 + 'px' - }) - .appendTo(that); - - if (self.options.showZoombar) { - self.$zoombar = Ox.Bar({ - size: 16 - }) - .css({ - bottom: self.options.showStatusbar * 24 + 'px' - }) - .appendTo(that); - } - - if (self.options.showStatusbar) { - self.$statusbar = Ox.Bar({ - size: 24 - }) - .css({ - bottom: 0 - }) - .appendTo(that); - self.$placeFlag = Ox.$('') - .addClass('OxFlag') - .attr({ - src: Ox.PATH + 'Ox.Geo/png/icons/16/NTHH.png' - }) - .css({float: 'left', margin: '4px 2px 4px 4px'}) - .appendTo(self.$statusbar); - self.$placeNameInput = Ox.Input({ - placeholder: 'Name', - width: 96 - }) - //.css({position: 'absolute', left: 4, top: 4}) - .css({float: 'left', margin: '4px 2px 4px 2px'}) - .appendTo(self.$statusbar); - self.$placeGeonameInput = Ox.Input({ - placeholder: 'Geoname', - width: 96 - }) - //.css({position: 'absolute', left: 104, top: 4}) - .css({float: 'left', margin: '4px 2px 4px 2px'}) - .appendTo(self.$statusbar); - self.$placeButton = Ox.Button({ - title: 'New Place', - width: 96 - }) - .css({float: 'right', margin: '4px 4px 4px 2px'}) - .bindEvent({ - click: clickPlaceButton - }) - .appendTo(self.$statusbar); - } - - self.$controls = { - center: Ox.Button({ - title: 'center', - type: 'image' - }) - .addClass('OxMapControl OxMapButtonCenter') - .bindEvent({ - singleclick: function() { - panToPlace(); - }, - doubleclick: function() { - zoomToPlace(); - } - }), - east: Ox.Button({ - title: 'right', - type: 'image' - }) - .addClass('OxMapControl OxMapButtonEast') - .bindEvent({ - singleclick: function() { - pan(1, 0); - }, - doubleclick: function() { - pan(2, 0); - } - }), - north: Ox.Button({ - title: 'up', - type: 'image' - }) - .addClass('OxMapControl OxMapButtonNorth') - .bindEvent({ - singleclick: function() { - pan(0, -1); - }, - doubleclick: function() { - pan(0, -2); - } - }), - south: Ox.Button({ - title: 'down', - type: 'image' - }) - .addClass('OxMapControl OxMapButtonSouth') - .bindEvent({ - singleclick: function() { - pan(0, 1); - }, - doubleclick: function() { - pan(0, 2); - } - }), - west: Ox.Button({ - title: 'left', - type: 'image' - }) - .addClass('OxMapControl OxMapButtonWest') - .bindEvent({ - singleclick: function() { - pan(-1, 0); - }, - doubleclick: function() { - pan(-2, 0); - } - }), - scale: Ox.Label({ - textAlign: 'center' - }) - .addClass('OxMapControl OxMapScale') - }; - !self.options.showControls && Ox.forEach(self.$controls, function($control) { - $control.css({opacity: 0}).hide(); - }); - - self.$placeControls = { - flag: Ox.Element() - .addClass('OxPlaceControl OxPlaceFlag') - .bindEvent({ - anyclick: function() { - // FIXME: doesn't work for 'Georgia', use Ox.Geo data! - var country = this.data('country'); - country && getPlaceByName(country, function(place) { - place && self.map.fitBounds(place.bounds); - }); - } - }), - name: Ox.Label({ - textAlign: 'center', - tooltip: Ox._('Click to pan, doubleclick to zoom') - }) - .addClass('OxPlaceControl OxPlaceName') - .bindEvent({ - singleclick: function() { - panToPlace(); - }, - doubleclick: function() { - zoomToPlace(); - } - }), - deselectButton: Ox.Button({ - title: 'close', - tooltip: Ox._('Deselect'), - type: 'image' - }) - .addClass('OxPlaceControl OxPlaceDeselectButton') - .bindEvent({ - click: function() { - selectPlace(null); - } - }) - } - Ox.forEach(self.$placeControls, function($placeControl) { - $placeControl.css({opacity: 0}).hide(); - }); - - if (window.L) { - // timeout needed so that the map is in the DOM - setTimeout(initMap); - } else { - Ox.getStylesheet('https://unpkg.com/leaflet@1.9.4/dist/leaflet.css', () => {}) - - $.getScript( - document.location.protocol - + '//unpkg.com/leaflet@1.9.4/dist/leaflet.js', - function() { - console.log('loaded leaflet'); - console.log(window.L); - initMap(); - } - ); - } - - function addPlaceToMap(place) { - // via find, click, shift-click, or new place button - Ox.Log('Map', 'addPlaceToMap', place) - var exists = false; - if (!place) { - var bounds = self.map.getBounds(), - center = self.map.getCenter(), - southwest = new google.maps.LatLngBounds( - bounds.getSouthWest(), center - ).getCenter(), - northeast = new google.maps.LatLngBounds( - center, bounds.getNorthEast() - ).getCenter(), - place = new Ox.LeafletMapPlace({ - alternativeNames: [], - countryCode: '', - editable: true, - geoname: '', - id: '_' + Ox.encodeBase32(Ox.uid()), // fixme: stupid - map: that, - name: '', - type: 'feature', - south: southwest.lat(), - west: southwest.lng(), - north: northeast.lat(), - east: northeast.lng() - }); - } - Ox.forEach(self.places, function(p, i) { - if (place.bounds.equals(p.bounds)) { - place = p; - exists = true; - return false; // break - } - }); - if (!exists) { - self.resultPlace && self.resultPlace.remove(); - self.resultPlace = place; - place.add(); - } - selectPlace(place.id); - } - - function addPlaceToPlaces(data) { - var place = Ox.extend(getSelectedPlace() || {}, data), - country = Ox.getCountryByGeoname(place.geoname); - place.countryCode = country ? country.code : ''; - self.options.selected = place.id; - setPlaceControls(place); - place.marker.update(); - place.rectangle.update(); - self.places.push(place); - self.resultPlace = null; - that.triggerEvent('addplace', place) - } - - function boundsChanged() { - setScale(); - self.boundsChanged = true; - } - - function canContain(outerBounds, innerBounds) { - // checks if outerBounds _can_ contain innerBounds - var outerSpan = outerBounds.toSpan(), - innerSpan = innerBounds.toSpan(); - return outerSpan.lat() > innerSpan.lat() && - outerSpan.lng() > innerSpan.lng(); - } - - function centerChanged() { - var tooltip = $('.OxMapMarkerTooltip'); - tooltip.length && Ox.$elements[$(tooltip[0]).data('oxid')].hide(); - self.center = self.map.getCenter(); - self.centerChanged = true; - } - - function changeZoom(data) { - self.map.setZoom(data.value); - } - - function clickMap(event) { - var place = getSelectedPlace(); - if (self.options.clickable/* && !editing()*/) { - getPlaceByLatLng(event.latLng, self.map.getBounds(), function(place) { - if (place) { - addPlaceToMap(place); - //selectPlace(place.id); - } else { - selectPlace(null); - } - }); - } else { - pressEscape(); - } - } - - function clickPlaceButton() { - var place = getSelectedPlace(), - title = self.$placeButton.options('title'); - if (title == Ox._('New Place')) { - addPlaceToMap(); - } else if (title == Ox._('Add Place')) { - addPlaceToPlaces(); - } - } - - function constructZoomInput() { - if (self.options.showZoombar) { - self.$zoomInput && self.$zoomInput.remove(); - self.$zoomInput = Ox.Range({ - arrows: true, - changeOnDrag: true, - max: self.maxZoom, - min: self.minZoom, - size: that.width(), - thumbSize: 32, - thumbValue: true, - value: self.map.getZoom() - }) - .bindEvent({ - change: changeZoom - }) - .appendTo(self.$zoombar); - } - } - - function crossesDateline() { - var bounds = self.map.getBounds(); - return bounds.getSouthWest().lng() > bounds.getNorthEast().lng(); - } - - function editing() { - var place = getSelectedPlace(); - return place && place.editing; - } - - function getElevation(point, callback) { - // fixme: unused - if (arguments.length == 1) { - callback = point; - point = self.map.getCenter(); - } - self.elevationService.getElevationForLocations({ - locations: [point] - }, function(data) { - callback(data.elevation); - }); - } - - function getMapBounds(callback) { - // get initial map bounds - self.options.places({}, function(result) { - var area = result.data.area; - console.log('area', area); - console.log(L.latLngBounds( - [area.south, area.west], - [area.north, area.east] - )); - callback(new L.latLngBounds( - [area.south, area.west], - [area.north, area.east] - )); - }); - } - - function getMapHeight() { - return self.options.height - - self.options.showStatusbar * 24 - - self.options.showToolbar * 24 - - self.options.showZoombar * 16; - } - - function getMapType() { - return self.options.showLabels ? 'HYBRID' : 'SATELLITE' - } - - function getMaxZoom(point, callback) { - if (arguments.length == 1) { - callback = point; - point = self.map.getCenter(); - } - setTimeout(function() { - callback(18) - }); - // self.maxZoomService.getMaxZoomAtLatLng(point, function(data) { - // callback(data.status == 'OK' ? data.zoom : null); - // }); - } - - function getMetersPerPixel() { - // m/px = m/deg * deg/px - var degreesPerPixel = 360 / (self.tileSize * Math.pow(2, self.map.getZoom())); - return Ox.getMetersPerDegree(self.map.getCenter().lat) * degreesPerPixel; - } - - function getMinZoom() { - return self.mapHeight > 1024 ? 3 - : self.mapHeight > 512 ? 2 - : self.mapHeight > 256 ? 1 - : 0; - // fixme: there must be a function for this... - /* - return Math.ceil( - Ox.log(self.mapHeight / self.tileSize, 2) - ); - */ - } - - function getPlaceById(id) { - return self.resultPlace && self.resultPlace.id == id - ? self.resultPlace - : Ox.getObjectById(self.places, id); - } - - function getPlaceByLatLng(latlng, bounds, callback) { - // gets the largest place at latlng that would fit in bounds - var callback = arguments.length == 3 ? callback : bounds, - bounds = arguments.length == 3 ? bounds : null; - self.$loadingIcon && self.$loadingIcon.start(); - self.geocoder.geocode({ - latLng: latlng - }, function(results, status) { - self.$loadingIcon && self.$loadingIcon.stop(); - if (status == google.maps.GeocoderStatus.OK) { - if (bounds) { - Ox.forEach(results.reverse(), function(result, i) { - if ( - i == results.length - 1 || - canContain(bounds, result.geometry.bounds || result.geometry.viewport) - ) { - callback(new Ox.LeafletMapPlace(parseGeodata(results[i]))); - return false; // break - } - }); - } else { - callback(new Ox.LeafletMapPlace(parseGeodata(results[0]))); - } - } - if ( - status == google.maps.GeocoderStatus.OK || - status == google.maps.GeocoderStatus.ZERO_RESULTS - ) { - triggerGeocodeEvent({ - latLng: latlng, - results: results - }); - } else { - Ox.Log('Map', 'geocode failed:', status); - callback(null); - } - }); - } - - function getPlaceByName(name, callback) { - self.$loadingIcon && self.$loadingIcon.start(); - self.geocoder.geocode({ - address: name - }, function(results, status) { - self.$loadingIcon && self.$loadingIcon.stop(); - if (status == google.maps.GeocoderStatus.OK) { - callback(new Ox.LeafletMapPlace(parseGeodata(results[0]))); - } - if ( - status == google.maps.GeocoderStatus.OK - && status != google.maps.GeocoderStatus.ZERO_RESULTS - ) { - triggerGeocodeEvent({ - address: name, - results: results - }); - } else { - Ox.Log('Map', 'geocode failed:', status); - callback(null); - } - }); - } - - function getPositionByName(name) { - var position = -1; - Ox.forEach(self.options.places, function(place, i) { - if (place.name == name) { - position = i; - return false; // break - } - }); - return position; - } - - function getSelectedMarker() { - // needed in case self.options.selected - // is changed from outside - var id = null; - if (self.resultPlace && self.resultPlace.selected) { - id = self.resultPlace.id; - } else { - Ox.forEach(self.places, function(place) { - if (place.selected) { - id = place.id; - return false; // break - } - }); - } - return id; - } - - function getSelectedPlace() { - return self.options.selected - ? getPlaceById(self.options.selected) - : null; - } - - function initMap() { - getMapBounds(function(mapBounds) { - console.log('map bounds', mapBounds); - //Ox.Log('Map', 'init', mapBounds.getSouthWest(), mapBounds.getNorthEast(), mapBounds.getCenter()) - - // self.elevationService = new google.maps.ElevationService(); - // self.geocoder = new google.maps.Geocoder(); - // self.maxZoomService = new google.maps.MaxZoomService(); - - self.center = mapBounds ? mapBounds.getCenter() : new L.LatLng([0, 0]); - self.zoom = self.minZoom; - that.map = self.map = new L.Map(self.$map[0], { - center: self.center, - // disableDefaultUI: true, - // disableDoubleClickZoom: true, - // mapTypeId: google.maps.MapTypeId[getMapType()], - // noClear: true, - // scrollwheel: !self.options.zoomOnlyWhenFocused, - zoom: self.zoom - }); - console.log('that map', that.map); - L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { - maxZoom: 19, - attribution: '© OpenStreetMap' - }).addTo(that.map); - self.map.fitBounds(mapBounds); - self.map.on('moveend', boundsChanged); - self.map.on('moveend', centerChanged); - self.map.on('click', clickMap); - self.map.on('zoomend', zoomChanged); - setTimeout(function() { - mapChanged(); - }); - // google.maps.event.addListener(self.map, 'bounds_changed', boundsChanged); - // google.maps.event.addListener(self.map, 'center_changed', centerChanged); - // google.maps.event.addListener(self.map, 'click', clickMap); - // google.maps.event.addListener(self.map, 'idle', mapChanged); - // google.maps.event.addListener(self.map, 'zoom_changed', zoomChanged); - // google.maps.event.trigger(self.map, 'resize'); - - // needed to get mouse x/y coordinates on marker mouseover, - // see http://code.google.com/p/gmaps-api-issues/issues/detail?id=2342 - - // What does this OverlayView stuff do? - // that.overlayView = new google.maps.OverlayView(); - // that.overlayView.setMap(self.map); - // that.overlayView.draw = function () { - // if (!this.ready) { - // this.ready = true; - // google.maps.event.trigger(this, 'ready'); - // } - // } - // that.overlayView.draw(); - - Ox.forEach(self.$controls, function($control) { - $control.appendTo(self.$map); - }); - Ox.forEach(self.$placeControls, function($placeControl) { - $placeControl.appendTo(self.$map); - }); - - if (self.options.find) { - self.$findInput - .value(self.options.find) - .triggerEvent('submit', {value: self.options.find}); - } else { - if (self.options.selected) { - selectPlace(self.options.selected, true); - } - if (mapBounds) { - if (isEmpty(mapBounds)) { - self.map.setZoom(self.minZoom); - } else { - self.map.fitBounds(mapBounds); - } - } - if (self.map.getZoom() < self.minZoom) { - self.map.setZoom(self.minZoom); - } - } - updateFormElements(); - - self.loaded = true; - that.triggerEvent('load'); - - }); - - } - - function isEmpty(bounds) { - // Google's bounds.isEmpty() is not reliable - var southWest = bounds.getSouthWest(), - northEast = bounds.getNorthEast(); - return southWest.lat == northEast.lat - && southWest.lng == northEast.lng; - } - - function isLoaded() { - return window.google && window.google.maps && window.google.maps.LatLng; - } - - function mapChanged() { - // This is the handler that actually adds the places to the map. - // Gets called after panning or zooming, and when the map is idle. - if (self.boundsChanged) { - var bounds = self.map.getBounds() - if (!bounds) { - self.boundsChanged = false; - return - } - var southWest = bounds.getSouthWest(), - northEast = bounds.getNorthEast(), - south = southWest.lat, - west = southWest.lng, - north = northEast.lat, - east = northEast.lng; - self.options.places({ - keys: self.placeKeys, - query: { - conditions: [].concat([ - {key: 'lat', value: [south, north], operator: '='} - ], spansGlobe() ? [ - {key: 'lng', value: [-180, 180], operator: '='} - ] : crossesDateline() ? [ - {key: 'lng', value: [east, west], operator: '!='} - ] : [ - {key: 'lng', value: [west, east], operator: '='} - ]), - operator: '&' - }, - range: [0, self.options.maxMarkers], - sort: [{key: 'area', operator: '-'}] - }, function(result) { - var ids = self.options.selected ? [self.options.selected] : [], - previousIds = self.places.map(function(place) { - return place.id; - }); - // add new places - result.data.items.forEach(function(item, i) { - var place = getPlaceById(item.id); - if (!place) { - place = new Ox.LeafletMapPlace(Ox.extend({ - map: that - }, item)).add(); - self.places.push(place); - } else if (!place.visible) { - place.add(); - } - item.id != self.options.selected && ids.push(item.id); - }); - // remove old places - previousIds.forEach(function(id) { - var place = getPlaceById(id); - if (place && ids.indexOf(id) == -1) { - place.remove(); - } - }); - // update places array - self.places = self.places.filter(function(place) { - return place.visible; - }); - }); - self.boundsChanged = false; - } - if (self.centerChanged) { - getMaxZoom(function(zoom) { - if (zoom && zoom != self.maxZoom) { - self.maxZoom = zoom; - if (self.map.getZoom() > zoom) { - self.map.setZoom(zoom); - } - constructZoomInput(); - } - }); - self.centerChanged = false; - } - if (self.zoomChanged) { - self.zoomChanged = false; - } - } - - function pan(x, y) { - self.map.panBy(x * self.$map.width() / 2, y * self.$map.height() / 2); - }; - - function panToPlace() { - var place; - if (!self.loaded) { - setTimeout(function() { - panToPlace(); - }, 100); - } else { - place = getSelectedPlace(); - place && self.map.panTo(place.center); - } - } - - function parseGeodata(data) { - var bounds = data.geometry.bounds || data.geometry.viewport, - northEast = bounds.getNorthEast(), - southWest = bounds.getSouthWest(), - place = { - alternativeNames: [], - components: data.address_components, - countryCode: getCountryCode(data.address_components), - east: northEast.lng(), - editable: self.options.editable, - fullGeoname: getFullGeoname(data.address_components), - id: '_' + Ox.encodeBase32(Ox.uid()), - map: that, - north: northEast.lat(), - south: southWest.lat(), - type: getType(data.address_components[0].types), - west: southWest.lng() - }; - place.geoname = data.formatted_address || place.fullGeoname; - place.name = (place.geoname || place.fullGeoname).split(', ')[0]; - if (Math.abs(place.west) == 180 && Math.abs(place.east) == 180) { - place.west = -179.99999999; - place.east = 179.99999999; - } - place.south = Ox.limit(place.south, Ox.MIN_LATITUDE, Ox.MAX_LATITUDE - 0.00000001); - place.north = Ox.limit(place.north, Ox.MIN_LATITUDE + 0.00000001, Ox.MAX_LATITUDE); - function getCountryCode(components) { - var countryCode = ''; - Ox.forEach(components, function(component) { - if (component.types.indexOf('country') > -1) { - countryCode = component.short_name; - return false; // break - } - }); - return countryCode; - } - function getFullGeoname(components) { - var country = false; - return components.map(function(component, i) { - var name = component.long_name; - if (i && components[i - 1].types.indexOf('country') > -1) { - country = true; - } - return !country && ( - i == 0 || name != components[i - 1].long_name - ) ? name : null; - }).join(', '); - } - function getType(types) { - // see https://developers.google.com/maps/documentation/javascript/geocoding#GeocodingAddressTypes - var strings = { - 'country': ['country'], - 'region': ['administrative_area', 'colloquial_area'], - 'city': ['locality'], - 'borough': ['neighborhood', 'postal_code', 'sublocality'], - 'street': [ - 'intersection', 'route', - 'street_address', 'street_number' - ], - 'building': [ - 'airport', 'floor', 'premise', 'room', 'subpremise' - ], - 'feature': ['natural_feature', 'park'] - }, - type; - function find(type) { - var ret; - Ox.forEach(types, function(v) { - ret = Ox.startsWith(v, type); - if (ret) { - return false; // break - } - }); - return ret; - } - Ox.forEach(strings, function(values, key) { - Ox.forEach(values, function(value) { - if (find(value)) { - type = key; - return false; // break - } - }); - if (type) { - return false; // break - } - }); - return type || 'feature'; - } - return place; - } - - function pressEnter() { - var place = getSelectedPlace(); - if (place) { - if (place.editing) { - place.submit(); - } else { - place.edit(); - } - } else if (self.resultPlace) { - selectPlace(self.resultPlace.id) - } - } - - function pressEscape() { - var place = getSelectedPlace(); - if (place) { - if (place.editing) { - place.cancel(); - } else { - selectPlace(null); - } - } else if (self.resultPlace) { - self.resultPlace.remove(); - self.resultPlace = null; - } - } - - // fixme: removePlacefromMap? - function removePlace() { - var place = getSelectedPlace(); - place.id = '_' + place.id; - self.options.selected = place.id; - self.places.splice(Ox.getIndexById(self.places, place.id), 1); - self.resultPlace && self.resultPlace.remove(); - self.resultPlace = place; - place.marker.update(); - place.rectangle.update(); - } - - function reset() { - self.map.getZoom() == self.zoom - ? self.map.panTo(self.center) - : self.map.fitBounds(self.bounds); - } - - function selectPlace(id, zoom) { - // id can be null (deselect) - var place, selected; - if (!self.loaded) { - setTimeout(function() { - selectPlace(id, zoom); - }, 100); - } else { - selected = getSelectedMarker(); - Ox.Log('Map', 'Ox.Map selectPlace()', id, selected); - if (id != selected) { - place = getPlaceById(selected); - place && place.deselect(); - if (id !== null) { - place = getPlaceById(id); - if (place) { - select(); - } else { - // async && place doesn't exist yet - self.options.places({ - keys: self.placeKeys, - query: { - conditions: [ - {key: 'id', value: id, operator: '=='} - ], - operator: '&' - } - }, function(result) { - if (result.data.items.length) { - place = new Ox.LeafletMapPlace(Ox.extend({ - map: that - }, result.data.items[0])).add(); - self.places.push(place); - select(); - if (zoom) { - zoomToPlace(); - } else { - panToPlace(); - } - } - }); - } - } else { - place = null; - select(); - } - } - } - function select() { - place && place.select(); - self.options.selected = id; - setPlaceControls(place); - setStatus(); - that.triggerEvent('selectplace', place); // FIXME: deprecated, remove - that.triggerEvent('select', place); - } - }; - - function setPlaceControls(place) { - var $placeControls = that.find('.OxPlaceControl'), - country, - isVisible = self.$placeControls.name.is(':visible'); - if (place) { - country = place.geoname.indexOf(', ') > -1 - ? place.geoname.split(', ').pop() - : ''; - self.$placeControls.flag.options({ - tooltip: country ? 'Zoom to ' + country : '' - }) - .data({country: country}) - .empty() - .append( - Ox.$('').attr({ - src: Ox.getFlagByGeoname(place.geoname, 16) - }) - ) - .show(); - self.$placeControls.name.options({ - title: place.name ||'Unnamed' - }); - !isVisible && $placeControls.show().animate({opacity: 1}, 250); - } else { - isVisible && $placeControls.animate({opacity: 0}, 250, function() { - $placeControls.hide(); - }); - } - } - - function setScale() { - var metersPerPixel = getMetersPerPixel(); - Ox.forEach(self.scaleMeters, function(meters) { - var mapWidth = self.options.width || that.width(), - scaleWidth = Math.round(meters / metersPerPixel); - if (scaleWidth <= mapWidth / 2 - 4) { - self.$controls.scale - .options({ - title: '\u2190 ' + ( - meters > 1000 ? Ox.formatNumber(meters / 1000) + ' k' : meters + ' ' - ) + 'm \u2192' - }) - .css({ - width: (scaleWidth - 16) + 'px' - }); - return false; // break - } - }); - } - - function setStatus() { - //Ox.Log('Map', 'setStatus()', self.options.selected) - var code, country, disabled, place, title; - if (self.options.showStatusbar) { - place = getSelectedPlace(); - country = place ? Ox.getCountryByGeoname(place.geoname) : ''; - code = country ? country.code : 'NTHH'; - disabled = place && !place.editable; - if (place) { - title = place.id[0] == '_' ? Ox._('Add Place') : Ox._('Remove Place'); - } else { - title = Ox._('New Place'); - } - self.$placeFlag.attr({ - src: Ox.PATH + 'Ox.Geo/png/icons/16/' + code + '.png' - }); - self.$placeNameInput.options({ - disabled: disabled, - value: place ? place.name : '' - }); - self.$placeGeonameInput.options({ - disabled: disabled, - value: place ? place.geoname : '' - }); - self.$placeButton.options({ - disabled: disabled, - title: title - }); - } - //Ox.Log('Map', 'STATUS DONE'); - } - - function spansGlobe() { - // fixme: or self.options.width ?? - return self.$map.width() > self.tileSize * Math.pow(2, self.map.getZoom()); - }; - - function submitFind(data) { - self.options.find = data.value; - if (data.value === '') { - if (self.options.selected && self.options.selected[0] == '_') { - selectPlace(null); - } - } else { - that.findPlace(data.value, function(place) { - setStatus(place); - }); - } - that.triggerEvent('find', {value: data.value}); - } - - function toggleControls() { - var $controls = that.find('.OxMapControl'); - self.options.showControls = !self.options.showControls; - if (self.options.showControls) { - $controls.show().animate({opacity: 1}, 250); - } else { - $controls.animate({opacity: 0}, 250, function() { - $controls.hide(); - }); - } - that.triggerEvent('togglecontrols', { - visible: self.options.showControls - }); - } - - function toggleLabels() { - self.options.showLabels = !self.options.showLabels; - self.map.setMapTypeId(google.maps.MapTypeId[getMapType()]); - that.triggerEvent('togglelabels', { - visible: self.options.showLabels - }); - } - - function triggerGeocodeEvent(data) { - // someone may want to cache google geocode data, so we fire an event. - // google puts functions like lat or lng on the objects' prototypes, - // so we create properly named properties, for json encoding - if (data.latLng) { - data.latLng = { - lat: data.latLng.lat(), - lng: data.latLng.lng() - } - } - data.results.forEach(function(result) { - ['bounds', 'viewport'].forEach(function(key) { - if (result.geometry[key]) { - result.geometry[key] = { - northEast: { - lat: result.geometry[key].getNorthEast().lat(), - lng: result.geometry[key].getNorthEast().lng() - }, - southWest: { - lat: result.geometry[key].getSouthWest().lat(), - lng: result.geometry[key].getSouthWest().lng() - } - } - } - }); - if (result.geometry.location) { - result.geometry.location = { - lat: result.geometry.location.lat(), - lng: result.geometry.location.lng() - } - } - }); - that.triggerEvent('geocode', data); - } - - function undo() { - Ox.Log('Map', 'Map undo') - var place = getSelectedPlace(); - place.editing && place.undo(); - } - - function updateFormElements() { - var width = that.width(); - if (self.options.showZoombar) { - getMaxZoom(function(zoom) { - self.maxZoom = zoom; - constructZoomInput(); - }); - } - if (self.options.showStatusbar) { - self.$placeNameInput.options({ - width: Math.floor((width - 132) / 2) - }); - self.$placeGeonameInput.options({ - width: Math.ceil((width - 132) / 2) - }); - } - } - - function zoom(z) { - if (!self.loaded) { - setTimeout(function() { - zoom(z); - }, 100); - } else { - self.map.setZoom(self.map.getZoom() + z); - } - } - - function zoomChanged() { - var zoom = self.map.getZoom(); - if (zoom < self.minZoom) { - self.map.setZoom(self.minZoom); - } else if (self.maxZoom && zoom > self.maxZoom) { - self.map.setZoom(self.maxZoom); - } else { - self.zoomChanged = true; - self.$zoomInput && self.$zoomInput.value(zoom); - that.triggerEvent('zoom', { - value: zoom - }); - } - } - - function zoomToPlace() { - var place; - if (!self.loaded) { - setTimeout(function() { - zoomToPlace(); - }, 100); - } else { - place = getSelectedPlace(); - place && self.map.fitBounds(place.bounds); - } - } - - /*@ - addPlace addPlace - (data) -> add place to places - @*/ - that.addPlace = function(data) { - addPlaceToPlaces(data); - }; - - /*@ - getCenter Returns the map center - () -> Map center - lat Latitude - lng Longitude - @*/ - that.getCenter = function() { - var center = self.map.getCenter(); - return {lat: center.lat(), lng: center.lng()}; - }; - - /*@ - getKey getKey - () -> get key - @*/ - that.getKey = function() { - return self.shiftKey ? 'shift' - : self.metaKey ? 'meta' - : null; - }; - - /*@ - getSelectedPlace getSelectedPlace - () -> get selected place - @*/ - that.getSelectedPlace = function() { - return getSelectedPlace(); - } - - /*@ - editPlace editPlace - () -> edit selected place - @*/ - that.editPlace = function() { - getSelectedPlace().edit(); - return that; - }; - - /*@ - findPlace findPlace - (name, callback) -> find place and pass to callback - @*/ - that.findPlace = function(name, callback) { - getPlaceByName(name, function(place) { - if (place) { - addPlaceToMap(place); - self.map.fitBounds(place.bounds); - } else { - name && self.$findInput.addClass('OxError'); - } - callback(place); - }); - return that; - }; - - /*@ - newPlace newPlace - (place) -> add place to map - @*/ - that.newPlace = function(place) { - addPlaceToMap(place); - return that; - }; - - /*@ - panToPlace panToPlace - () -> pan to place - @*/ - that.panToPlace = function() { - panToPlace(); - return that; - }; - - /*@ - removePlace removePlace - () -> remove selected place from places - @*/ - that.removePlace = function() { - // fixme: removePlaceFromPlaces() ? - removePlace(); - return that; - }; - - /*@ - resizeMap resizeMap - () -> resize map - @*/ - that.resizeMap = function() { - // keep center on resize has been commented out - // var center = self.map.getCenter(); - self.options.height = that.height(); - self.options.width = that.width(); - // check if map has initialized - if (self.map) { - self.mapHeight = getMapHeight(); - self.minZoom = getMinZoom(); - if (self.minZoom > self.map.getZoom()) { - self.map.setZoom(self.minZoom); - } - self.$map.css({ - height: self.mapHeight + 'px', - width: self.options.width + 'px' - }); - self.options.$zoomInput && self.$zoomInput.options({ - size: self.options.width - }); - updateFormElements(); - Ox.Log('Map', 'triggering google maps resize event, height', self.options.height) - google.maps.event.trigger(self.map, 'resize'); - // self.map.setCenter(center); - } - return that; - } - - /*@ - setCenter Set map center - (center) -> Map - center Map center - lat Latitude - lng Longitude - @*/ - that.setCenter = function(center) { - self.map.setCenter(new google.maps.LatLng(center.lat, center.lng)); - return that; - }; - - /*@ - value value - (id, key, value) -> set id, key to value - @*/ - that.value = function(id, key, value) { - // fixme: should be like the corresponding List/TableList/etc value function - Ox.Log('Map', 'Map.value', id, key, value); - getPlaceById(id).options(key, value); - if (id == self.options.selected) { - if (key == 'name') { - self.$placeControls.name.options({title: value}); - } else if (key == 'geoname') { - self.$placeControls.flag.empty().append( - Ox.$('').attr({ - src: Ox.getFlagByGeoname(value, 16) - }) - ); - } - } - return that; - } - - /*@ - zoomToPlace zoomToPlace - () -> zoom to selected place - @*/ - that.zoomToPlace = function() { - zoomToPlace(); - return that; - }; - - /*@ - zoom zoom - (value) -> zoom to value - @*/ - that.zoom = function(value) { - zoom(value); - return that; - }; - - return that; - -}; diff --git a/source/UI/js/Map/LeafletMapMarker.js b/source/UI/js/Map/LeafletMapMarker.js deleted file mode 100644 index 96fb8803..00000000 --- a/source/UI/js/Map/LeafletMapMarker.js +++ /dev/null @@ -1,335 +0,0 @@ -'use strict'; - -/*@ -Ox.MapMarker MapMarker - (options) -> MapMarker object - options Options object - color marker color - map map - place place - size size -@*/ - -Ox.LeafletMapMarker = function(options) { - - options = Ox.extend({ - map: null, - place: null - }, options); - - var that = this, - areaSize = { - 100: 10, // 10 x 10 m - 10000: 12, // 100 x 100 m - 1000000: 14, // 1 x 1 km - 100000000: 16, // 10 x 10 km - 10000000000: 18, // 100 x 100 km - 1000000000000: 20, // 1,000 x 1,000 km - 100000000000000: 22 // 10,000 x 10,000 km - }, - themeData = Ox.Theme.getThemeData(), - typeColor = {}; - - [ - 'country', 'region', 'city', 'borough', - 'street', 'building', 'feature' - ].forEach(function(type) { - typeColor[type] = themeData[ - 'mapPlace' + Ox.toTitleCase(type) + 'Color' - ]; - }); - - Ox.forEach(options, function(val, key) { - that[key] = val; - }); - console.log('place', options.place); - that.marker = new L.Marker([options.place.center.lat, options.place.center.lng], { - // raiseOnDrag: false, - // shape: {coords: [8, 8, 8], type: 'circle'} - //title: that.place.name, - //zIndex: 1000 - }).addTo(options.map.map); - - // setOptions(); - - function click() { - var key = that.map.getKey(), - place, bounds, southWest, northEast; - if (!that.place.selected) { - if ( - that.map.options('editable') - && (key == 'meta' || key == 'shift') - ) { - place = that.map.getSelectedPlace(); - } - if (place) { - bounds = new L.LatLngBounds( - new L.LatLng(place.south, place.west), - new L.LatLng(place.north, place.east) - ); - bounds = bounds.extend(that.place.bounds); - southWest = bounds.getSouthWest(); - northEast = bounds.getNorthEast(); - that.map.newPlace(new Ox.LeafletMapPlace({ - // fixme: duplicated, see Ox.Map.js - alternativeNames: [], - countryCode: '', - editable: true, - geoname: '', - id: '_' + Ox.encodeBase32(Ox.uid()), // fixme: stupid - map: that.map, - name: '', - type: 'feature', - south: southWest.lat, - west: southWest.lng, - north: northEast.lat, - east: northEast.lng - })); - } else { - console.log('place', that.place); - that.map.options({selected: that.place.id}); - } - } else { - if (key == 'meta') { - that.map.options({selected: null}); - } else { - that.map.panToPlace(); - } - } - } - - function dblclick() { - that.place.selected && that.map.zoomToPlace(); - } - - function dragstart(e) { - Ox.$body.addClass('OxDragging'); - } - - function drag(e) { - var northSouth = (that.place.north - that.place.south) / 2, - lat = Ox.limit( - e.latLng.lat(), - Ox.MIN_LATITUDE + northSouth, - Ox.MAX_LATITUDE - northSouth - ), - lng = e.latLng.lng(), - span = Math.min( - that.place.sizeEastWest * Ox.getDegreesPerMeter(lat) / 2, 179.99999999 - ), - degreesPerMeter = Ox.getDegreesPerMeter(lat); - that.place.south += lat - that.place.lat; - that.place.north += lat - that.place.lat; - that.place.west = lng - span; - that.place.east = lng + span; - if (that.place.west < -180) { - that.place.west += 360; - } else if (that.place.east > 180) { - that.place.east -= 360; - } - Ox.Log('Map', 'west', that.place.west, 'east', that.place.east, 'span', span); - that.place.update(); - that.marker.setOptions({ - position: that.place.center - }); - that.place.rectangle.update(); - } - - function dragend(e) { - Ox.$body.removeClass('OxDragging'); - that.map.triggerEvent('changeplaceend', that.place); - } - - function getMarkerImage(options, callback) { - // fixme: unused - options = Ox.extend({ - background: [255, 0, 0], - editing: false, - result: false, - selected: false, - size: 16 - }, options); - var background = options.result ? [255, 255, 0] : [255, 0, 0], - border = options.editing ? [128, 128, 255] : - options.selected ? [255, 255, 255] : [0, 0, 0], - c = Ox.canvas(options.size, options.size), - image, - r = options.size / 2; - if (Ox.isArray(background)) { - c.context.fillStyle = 'rgba(' + background.join(', ') + ', 0.5)'; - c.context.arc(r, r, r - 2, 0, 360); - c.context.fill(); - renderImage(); - } else { - image = new Image(); - image.onload = renderImage; - image.src = background; - } - function renderImage() { - //var i; - if (Ox.isString(background)) { - c.context.drawImage(image, 1, 1, options.size - 2, options.size - 2); - /* - c.imageData = c.context.getImageData(0, 0, options.size, options.size); - c.data = c.imageData.data; - for (i = 3; i < c.data.length; i += 1) { - c.data[i] = Math.round(c.data[i] * 0.5); - } - c.context.putImageData(c.imageData, 0, 0); - */ - } - c.context.beginPath(); - c.context.lineWidth = 2; - c.context.strokeStyle = 'rgb(' + border.join(', ') + ')'; - c.context.arc(r, r, r - 1, 0, 360); - c.context.stroke(); - callback(new google.maps.MarkerImage( - c.canvas.toDataURL(), - new google.maps.Size(options.size, options.size), - new google.maps.Point(0, 0), - new google.maps.Point(r, r) - )); - } - } - - function mouseover(e) { - var offset = that.map.offset(), - xy = that.map.overlayView.getProjection() - .fromLatLngToContainerPixel(e.latLng); - that.tooltip.show( - offset.left + Math.round(xy.x) - 4, - offset.top + Math.round(xy.y) + 20 - ); - } - - function mouseout() { - that.tooltip.hide(); - } - - function setOptions() { - // workaround to prevent marker from appearing twice - // after setting draggable from true to false (google maps bug) - // var fix = that.marker.getDraggable() && !that.place.editing, - // color = that.map.options('markerColor'), - // size = that.map.options('markerSize'); - var fix = false, - color = that.map.options('markerColor'), - size = that.map.options('markerSize'); - //Ox.Log('Map', 'setOptions, that.map: ', that.map) - if (color == 'auto') { - that.color = typeColor[that.place.type] || typeColor['mapPlaceFeatureColor']; - } else if (Ox.isArray(color)) { - that.color = color; - } else { - that.color = color(that.place); - } - if (size == 'auto') { - that.size = 8; - Ox.forEach(areaSize, function(size, area) { - if (that.place.area >= area) { - that.size = size; - } else { - return false; // break - } - }); - } else if (Ox.isNumber(size)) { - that.size = size; - } else { - that.size = size(that.place); - } - // that.marker.setOptions({ - // // fixme: cursor remains pointer - // cursor: that.place.editing ? 'move' : 'pointer', - // draggable: that.place.editing, - // // icon: Ox.MapMarkerImage({ - // // color: that.color, - // // mode: that.place.editing ? 'editing' : - // // that.place.selected ? 'selected' : 'normal', - // // size: that.size, - // // type: that.place.id[0] == '_' ? 'result' : 'place' - // // }), - // position: that.place.center - // }); - if (fix) { - that.marker.setVisible(false); - setTimeout(function() { - that.marker.setVisible(true); - }, 0); - } - setTooltip(); - } - - function setTooltip() { - that.tooltip && that.tooltip.remove(); - that.tooltip = Ox.Tooltip({ - title: '' - + '
' - + that.map.options('markerTooltip')(that.place) + '
' - }) - .addClass('OxMapMarkerTooltip'); - } - - /*@ - add add to map - () -> add to map, returns MapMarker - @*/ - that.add = function() { - that.marker.addTo(that.map.map); - that.marker.on('click', click); - that.marker.on('dblclick', dblclick); - // that.marker.on('mouseover', mouseover); - // that.marker.on('mouseout', mouseout); - // google.maps.event.addListener(that.marker, 'click', click); - // google.maps.event.addListener(that.marker, 'dblclick', dblclick); - // google.maps.event.addListener(that.marker, 'mouseover', mouseover); - // google.maps.event.addListener(that.marker, 'mouseout', mouseout); - return that; - }; - - /*@ - edit edit marker - () -> edit marker, returns MapMarker - @*/ - that.edit = function() { - setOptions(); - google.maps.event.addListener(that.marker, 'dragstart', dragstart); - google.maps.event.addListener(that.marker, 'drag', drag); - google.maps.event.addListener(that.marker, 'dragend', dragend); - return that; - }; - - /*@ - remove remove marker - () -> remove marker from map, returns MapMarker - @*/ - that.remove = function() { - that.marker.setMap(null); - google.maps.event.clearListeners(that.marker); - return that; - }; - - /*@ - submit submit marker - () -> clear edit listeners, returns MapMarker - @*/ - that.submit = function() { - google.maps.event.clearListeners(that.marker, 'dragstart'); - google.maps.event.clearListeners(that.marker, 'drag'); - google.maps.event.clearListeners(that.marker, 'dragend'); - return that; - } - - /*@ - update update marker - () -> update marker, returns MapMarker - @*/ - that.update = function() { - setOptions(); - return that; - } - - return that; - -}; diff --git a/source/UI/js/Map/LeafletMapPlace.js b/source/UI/js/Map/LeafletMapPlace.js deleted file mode 100644 index a413afa8..00000000 --- a/source/UI/js/Map/LeafletMapPlace.js +++ /dev/null @@ -1,230 +0,0 @@ -'use strict'; - -/*@ -Ox.MapPlace MapPlace Object - (options) -> MapPlace Object - options Options object - east - editing - geoname - map - markerColor 0> 0]> - markerSize - name - north - selected - south - type - visible - west -@*/ - -Ox.LeafletMapPlace = function(options) { - - options = Ox.extend({ - east: 0, - editing: false, - geoname: '', - map: null, - name: '', - north: 0, - selected: false, - south: 0, - type: '', - visible: false, - west: 0 - }, options); - - var that = this; - - Ox.forEach(options, function(val, key) { - that[key] = val; - }); - - update(); - - function update(updateMarker) { - // console.log('foo', that.north, that.east, that.south, that.west); - if (that.east < that.west) { - if (that.west > 170) { - that.west -= 360 - //console.log(that.geoname, '<< west', that.west+360, '=>', that.west) - } else { - that.east += 360 - //console.log(that.geoname, '>> east', that.east-360, that.east) - } - } - that.points = { - ne: new L.LatLng(that.north, that.east), - sw: new L.LatLng(that.south, that.west) - }; - console.log('points', JSON.stringify(that.points, null, 2)); - - that.bounds = new L.latLngBounds(that.points.sw, that.points.ne); - that.center = that.bounds.getCenter(); - that.lat = that.center.lat; - that.lng = that.center.lng; - Ox.extend(that.points, { - e: new L.LatLng(that.lat, that.east), - s: new L.LatLng(that.south, that.lng), - se: new L.LatLng(that.south, that.east), - n: new L.LatLng(that.north, that.lng), - nw: new L.LatLng(that.north, that.west), - w: new L.LatLng(that.lat, that.west) - }); - // fixme: use bounds.toSpan() - that.sizeNorthSouth = (that.north - that.south) - * Ox.EARTH_CIRCUMFERENCE / 360; - that.sizeEastWest = (that.east + (that.west > that.east ? 360 : 0) - that.west) - * Ox.getMetersPerDegree(that.lat); - that.area = Ox.getArea( - {lat: that.south, lng: that.west}, - {lat: that.north, lng: that.east} - ); - if (!that.marker) { - that.marker = new Ox.LeafletMapMarker({ - map: that.map, - place: that - }); - that.rectangle = new Ox.LeafletMapRectangle({ - map: that.map, - place: that - }); - } else if (updateMarker) { - that.marker.update(); - that.rectangle.update(); - } - } - - function editable() { - return that.map.options('editable') && that.editable; - } - - /*@ - add add - @*/ - that.add = function() { - that.visible = true; - that.marker.add(); - return that; - }; - - /*@ - cancel cancel - @*/ - that.cancel = function() { - if (editable()) { - that.undo(); - that.editing = false; - that.marker.update(); - that.rectangle.deselect(); - } - return that; - }; - - /*@ - crossesDateline crossesDateline - @*/ - that.crossesDateline = function() { - return that.west > that.east; - } - - /*@ - deselect dselect - @*/ - that.deselect = function() { - that.editing && that.submit(); - that.selected = false; - that.marker.update(); - that.rectangle.remove(); - return that; - }; - - /*@ - edit edit - @*/ - that.edit = function() { - if (editable()) { - that.editing = true; - that.original = { - south: that.south, - west: that.west, - north: that.north, - east: that.east - }; - that.marker.edit(); - that.rectangle.select(); - } - return that; - }; - - // fixme: make this an Ox.Element to get options handling for free? - that.options = function(options) { - options = Ox.makeObject(arguments); - Ox.forEach(options, function(value, key) { - that[key] = value; - }); - update(true); - }; - - /*@ - remove remove - @*/ - that.remove = function() { - that.editing && that.submit(); - that.selected && that.deselect(); - that.visible = false; - that.marker.remove(); - return that; - }; - - /*@ - select select - @*/ - that.select = function() { - that.selected = true; - !that.visible && that.add(); - that.marker.update(); - that.rectangle.add(); - return that; - }; - - /*@ - submit submit - @*/ - that.submit = function() { - if (editable()) { - that.editing = false; - that.marker.update(); - that.rectangle.deselect(); - } - return that; - }; - - /*@ - update update - @*/ - that.update = function(updateMarker) { - update(updateMarker); - that.map.triggerEvent('changeplace', that); - return that; - }; - - /*@ - undo undo - @*/ - that.undo = function() { - if (editable()) { - Ox.forEach(that.original, function(v, k) { - that[k] = v; - }); - that.update(); - that.marker.update(); - that.rectangle.update(); - } - return that; - }; - - return that; - -}; diff --git a/source/UI/js/Map/LeafletMapRectangle.js b/source/UI/js/Map/LeafletMapRectangle.js deleted file mode 100644 index 99f1a19e..00000000 --- a/source/UI/js/Map/LeafletMapRectangle.js +++ /dev/null @@ -1,133 +0,0 @@ -'use strict'; - -/*@ -Ox.MapRectangle MapRectangle Object - (options) -> MapRectangle Object - options Options object - map map - place place -@*/ - -Ox.LeafletMapRectangle = function(options) { - - options = Ox.extend({ - map: null, - place: null - }, options); - - var that = this, - themeData = Ox.Theme.getThemeData(); - - Ox.forEach(options, function(val, key) { - that[key] = val; - }); - - /*@ - rectangle google.maps.Rectangle - @*/ - console.log('place bounds', that.place.bounds); - that.rectangle = new L.rectangle(that.place.bounds); - - /*@ - markers array of markers - @*/ - that.markers = Ox.map(that.place.points, function(point, position) { - return new Ox.LeafletMapRectangleMarker({ - map: that.map, - place: that.place, - position: position - }); - }); - - setOptions(); - - function click() { - if ( - that.map.options('editable') - && that.place.editable - && !that.place.editing - ) { - that.place.edit(); - } else if (that.map.getKey() == 'meta') { - that.place.submit(); - } else if (that.map.getKey() == 'shift') { - that.map.zoomToPlace(); - } else { - that.map.panToPlace(); - } - } - - function setOptions() { - var color = '#' + Ox.toHex(themeData[ - that.place.editing - ? 'mapPlaceEditingBorder' - : 'mapPlaceSelectedBorder' - ]); - // that.rectangle.setOptions({ - // bounds: that.place.bounds, - // fillColor: color, - // fillOpacity: that.place.editing ? 0.1 : 0, - // strokeColor: color, - // strokeOpacity: that.place.id[0] == '_' ? 0.5 : 1, - // strokeWeight: 2 - // }); - } - - /*@ - add add - @*/ - that.add = function() { - that.rectangle.addTo(that.map.map); - that.rectangle.on('click', click); - // google.maps.event.addListener(that.rectangle, 'click', click); - return that; - }; - - /*@ - deselect deselect - @*/ - that.deselect = function() { - setOptions(); - Ox.Log('Map', 'MARKERS', that.markers) - Ox.forEach(that.markers, function(marker) { - marker.remove(); - }); - return that; - }; - - /*@ - remove remove - @*/ - that.remove = function() { - that.rectangle.remove(); - // that.rectangle.setMap(null); - // google.maps.event.clearListeners(that.rectangle); - return that; - } - - /*@ - select select - @*/ - that.select = function() { - setOptions(); - Ox.forEach(that.markers, function(marker) { - marker.add(); - }); - return that; - }; - - /*@ - update udpate - @*/ - that.update = function() { - Ox.Log('Map', 'UPDATE...') - setOptions(); - Ox.forEach(that.markers, function(marker) { - marker.update(); - }); - return that; - } - - return that; - -}; diff --git a/source/UI/js/Map/LeafletMapRectangleMarker.js b/source/UI/js/Map/LeafletMapRectangleMarker.js deleted file mode 100644 index 71a0e72c..00000000 --- a/source/UI/js/Map/LeafletMapRectangleMarker.js +++ /dev/null @@ -1,126 +0,0 @@ -'use strict'; - -/*@ -Ox.MapRectangleMarker MapRectangleMarker Object - (options) -> MapRectangleMarker Object - options Options object - map map - place place - position -@*/ - -Ox.LeafletMapRectangleMarker = function(options) { - - options = Ox.extend({ - map: null, - place: null, - position: '' - }, options); - - var that = this; - - Ox.forEach(options, function(val, key) { - that[key] = val; - }); - console.log('position', that.place.points, that.position); - // that.markerImage = new google.maps.MarkerImage - that.marker = new L.Marker({ - - }); - // that.marker = new google.maps.Marker({ - // cursor: that.position + '-resize', - // draggable: true, - // icon: Ox.MapMarkerImage({ - // mode: 'editing', - // rectangle: true, - // type: that.place.id[0] == '_' ? 'result' : 'place' - // }), - // position: that.place.points[that.position], - // raiseOnDrag: false - // }); - - function dragstart(e) { - Ox.$body.addClass('OxDragging'); - that.drag = { - lat: e.latLng.lat(), - lng: e.latLng.lng() - }; - } - - function drag(e) { - // fixme: implement shift+drag (center stays the same) - Ox.Log('Map', e.pixel.x, e.pixel.y) - var lat = Ox.limit(e.latLng.lat(), Ox.MIN_LATITUDE, Ox.MAX_LATITUDE), - lng = e.latLng.lng(); - that.drag = { - lat: lat, - lng: lng - }; - if (that.position.indexOf('s') > -1) { - that.place.south = lat; - } - if (that.position.indexOf('n') > -1) { - that.place.north = lat; - } - if (that.position.indexOf('w') > -1) { - that.place.west = lng; - } - if (that.position.indexOf('e') > -1) { - that.place.east = lng; - } - //Ox.Log('Map', 'west', that.place.west, 'east', that.place.east); - //Ox.Log('Map', 'south', that.place.south, 'north', that.place.north); - that.place.update(); - that.place.marker.update(); - that.place.rectangle.update(); - } - - function dragend(e) { - var south; - Ox.$body.removeClass('OxDragging'); - if (that.place.south > that.place.north) { - south = that.place.south; - that.place.south = that.place.north; - that.place.north = south; - that.place.update(); - that.place.marker.update(); - that.place.rectangle.update(); - } - that.map.triggerEvent('changeplaceend', that.place); - } - - /*@ - add add - @*/ - that.add = function() { - that.marker.setMap(that.map.map); - google.maps.event.addListener(that.marker, 'dragstart', dragstart); - google.maps.event.addListener(that.marker, 'drag', drag); - google.maps.event.addListener(that.marker, 'dragend', dragend); - }; - - /*@ - remove remove - @*/ - that.remove = function() { - that.marker.setMap(null); - google.maps.event.clearListeners(that.marker); - }; - - /*@ - update update - @*/ - that.update = function() { - that.marker.setOptions({ - icon: Ox.MapMarkerImage({ - mode: 'editing', - rectangle: true, - type: that.place.id[0] == '_' ? 'result' : 'place' - }), - position: that.place.points[that.position] - }); - }; - - return that; - -}; diff --git a/source/UI/js/Map/Map.js b/source/UI/js/Map/Map.js index f12e1654..9f5c4392 100644 --- a/source/UI/js/Map/Map.js +++ b/source/UI/js/Map/Map.js @@ -832,6 +832,7 @@ Ox.Map = function(options, self) { } function initMap() { + getMapBounds(function(mapBounds) { //Ox.Log('Map', 'init', mapBounds.getSouthWest(), mapBounds.getNorthEast(), mapBounds.getCenter()) diff --git a/source/UI/js/Video/AnnotationFolder.js b/source/UI/js/Video/AnnotationFolder.js index 4b04dcd4..2284f36d 100644 --- a/source/UI/js/Video/AnnotationFolder.js +++ b/source/UI/js/Video/AnnotationFolder.js @@ -35,6 +35,7 @@ Ox.AnnotationFolder = function(options, self) { var that = Ox.Element({}, self) .defaults({ clickLink: null, + confirmDeleteDialog: null, collapsed: false, editable: false, highlight: '', @@ -281,6 +282,7 @@ Ox.AnnotationFolder = function(options, self) { } self.$annotations = Ox.ArrayEditable(Ox.extend({ clickLink: self.options.clickLink, + confirmDeleteDialog: self.options.confirmDeleteDialog, editable: self.options.editable, getSortValue: self.options.type == 'text' ? function(value) { @@ -579,26 +581,40 @@ Ox.AnnotationFolder = function(options, self) { function selectAnnotation(data) { if (self.loaded) { - var item = Ox.getObjectById(self.options.items, data.id); - self.options.selected = item ? data.id : ''; - if (self.widget) { - if (self.options.type == 'event') { - self.$calendar.options({ - selected: item && isDefined(item) ? item.event.id : '' - }) - .panToEvent(); - } else { - self.$map.options({ - selected: item && isDefined(item) ? item.place.id : '' - }) - .panToPlace(); + var extendedData; + if (Ox.isArray(data.id) && data.id.length) { + var items = data.id.map(id => { + return Ox.getObjectById(self.options.items, id); + }) + self.options.selected = data.id; + extendedData = Ox.extend(data, { + 'in': Ox.min(items.map(item => { return item["in"]; })), + out: Ox.max(items.map(item => { return item["out"]; })), + layer: self.options.id + }); + } else { + var item = Ox.getObjectById(self.options.items, data.id) + self.options.selected = item ? data.id : ''; + if (self.widget) { + if (self.options.type == 'event') { + self.$calendar.options({ + selected: item && isDefined(item) ? item.event.id : '' + }) + .panToEvent(); + } else { + self.$map.options({ + selected: item && isDefined(item) ? item.place.id : '' + }) + .panToPlace(); + } } + extendedData = Ox.extend(data, item ? { + 'in': item['in'], + out: item.out, + layer: self.options.id + } : {}); } - that.triggerEvent('select', Ox.extend(data, item ? { - 'in': item['in'], - out: item.out, - layer: self.options.id - } : {})); + that.triggerEvent('select', extendedData) } } diff --git a/source/UI/js/Video/AnnotationPanel.js b/source/UI/js/Video/AnnotationPanel.js index e93ea671..658dc9f4 100644 --- a/source/UI/js/Video/AnnotationPanel.js +++ b/source/UI/js/Video/AnnotationPanel.js @@ -48,9 +48,11 @@ Ox.AnnotationPanel = function(options, self) { .defaults({ calendarSize: 256, clickLink: null, + confirmDeleteDialog: null, editable: false, enableExport: false, enableImport: false, + enableTranscribe: false, highlight: '', highlightAnnotations: 'none', highlightLayer: '*', @@ -303,7 +305,11 @@ Ox.AnnotationPanel = function(options, self) { {}, {id: 'import', title: Ox._('Import Annotations...'), disabled: !self.options.enableImport}, {id: 'export', title: Ox._('Export Annotations...'), disabled: !self.options.enableExport}, - ] + ].concat( + self.options.enableTranscribe ? [ + {id: 'transcribeaudio', title: Ox._('Transcribe Audio...')}, + ]: [] + ) ), maxWidth: 256, style: 'square', @@ -325,9 +331,9 @@ Ox.AnnotationPanel = function(options, self) { } else if (data.id == 'export') { that.triggerEvent('exportannotations'); } else if (data.id == 'find') { - that.triggerEvent('find', {value: value}); + that.triggerEvent('find', {value: Ox.decodeHTMLEntities(value)}); } else if (data.id == 'findannotations') { - that.triggerEvent('findannotations', {key: key, value: value}); + that.triggerEvent('findannotations', {key: key, value: Ox.decodeHTMLEntities(value)}); } else if (data.id == 'import') { that.triggerEvent('importannotations'); } else if (data.id == 'insert') { @@ -351,6 +357,8 @@ Ox.AnnotationPanel = function(options, self) { // ... } else if (data.id == 'showentityinfo') { that.triggerEvent('showentityinfo', annotation.entity); + } else if (data.id == 'transcribeaudio') { + that.triggerEvent('transcribeaudio'); } else if (data.id == 'undo') { // ... } @@ -371,6 +379,7 @@ Ox.AnnotationPanel = function(options, self) { self.$folder[index] = Ox.AnnotationFolder( Ox.extend({ clickLink: self.options.clickLink, + confirmDeleteDialog: self.options.confirmDeleteDialog, collapsed: !self.options.showLayers[layer.id], editable: self.options.editable, highlight: getHighlight(layer.id), diff --git a/source/UI/js/Video/VideoAnnotationPanel.js b/source/UI/js/Video/VideoAnnotationPanel.js index 5ce19326..3d52533a 100644 --- a/source/UI/js/Video/VideoAnnotationPanel.js +++ b/source/UI/js/Video/VideoAnnotationPanel.js @@ -61,11 +61,13 @@ Ox.VideoAnnotationPanel = function(options, self) { censoredIcon: '', censoredTooltip: '', clickLink: null, + confirmDeleteDialog: null, cuts: [], duration: 0, enableDownload: false, enableImport: false, enableExport: false, + enableTranscribe: false, enableSetPosterFrame: false, enableSubtitles: false, find: '', @@ -844,9 +846,11 @@ Ox.VideoAnnotationPanel = function(options, self) { autocomplete: self.options.autocomplete, calendarSize: self.options.annotationsCalendarSize, clickLink: self.options.clickLink, + confirmDeleteDialog: self.options.confirmDeleteDialog, editable: true, enableExport: self.options.enableExport, enableImport: self.options.enableImport, + enableTranscribe: self.options.enableTranscribe, highlight: self.options.find, highlightAnnotations: self.options.annotationsHighlight, highlightLayer: self.options.findLayer, @@ -949,6 +953,9 @@ Ox.VideoAnnotationPanel = function(options, self) { that.triggerEvent('showentityinfo', data); }, submit: submitAnnotation, + transcribeaudio: function() { + that.triggerEvent('transcribeaudio'); + }, toggle: toggleAnnotations, togglecalendar: function(data) { self.options.showAnnotationsCalendar = !data.collapsed; diff --git a/source/UI/json/locale.tr.json b/source/UI/json/locale.tr.json new file mode 100644 index 00000000..7f671f86 --- /dev/null +++ b/source/UI/json/locale.tr.json @@ -0,0 +1,281 @@ +{ + ", doubleclick to edit": ", düzenlemek için çift tıkla", + "Add": "Ekle", + "Add Files": "Dosya Ekle", + "Add Place": "Yer Ekle", + "Add a condition": "koşul ekle", + "Add a group of conditions": "Bir grup koşul ekle", + "Add column after": "Sonrasına sütun ekle", + "Add column before": "Önce sütun ekle", + "Add row above": "Üste satır ekle", + "Add row below": "Altına satır ekle", + "Add {0}": "{0} ekle", + "Adding...": "Ekleniyor..", + "All": "Tüm", + "Alternative Names": "Alternatif İsimler", + "Area": "Alan", + "At Current Position": "Mevcut Konumda", + "Blockquote": "Blok halinde alıntıla", + "Bold": "Kalın", + "Borough": "Mahalle", + "Building": "Bina", + "Bullets": "Madde İşaretleri", + "By Duration": "Süreye göre", + "By Position": "Pozisyona Göre", + "By Text": "Metne gore", + "Cancel": "İptal et", + "Cancel/Deselect": "İptal et/Seçimi kaldır", + "Cancelled": "İptal edildi", + "City": "Şehir", + "Clear": "Temizle", + "Clear Event": "Etkinliği temizle", + "Clear Place": "Yeri Temizle", + "Clearing...": "Temizleniyor", + "Click to hide": "gizlemek için tıklayın", + "Click to pan, doubleclick to zoom": "Kaydırmak için tıklayın, yakınlaştırmak için çift tıklayın", + "Click to select": "Seçmek için tıklayın", + "Click to select, doubleclick to edit": "Seçmek için tıklayın, düzenlemek için çift tıklayın", + "Click to show": "Göstermek için tıklayın", + "Close": "Kapat", + "Complete": "Tamamlandı", + "Country": "Ülke", + "Date": "Tarih", + "Date Created": "Oluşturulma Tarihi", + "Date Modified": "Değiştirilme Tarihi", + "Define": "Tanımla", + "Define Event": "Etkinlik Tanımla", + "Define Place": "Yer Tanımla", + "Delete Annotation": "Ek Açıklamayı Sil", + "Deselect": "Seçimi Kaldır", + "Deselect Annotation": "Ek Açıklamanın Seçimini Kaldır", + "Don't Shuffle": "Karıştırma", + "Done": "Bitti", + "Download": "İndir", + "Download Selection...": "Seçimi İndir...", + "Download Video...": "Video İndir", + "Drag to resize": "Yeniden boyutlandırmak için sürükleyin", + "Drag to resize or click to hide": "Yeniden boyutlandırmak için sürükleyin veya gizlemek için tıklayın", + "Drag to resize or click to toggle map": "eniden boyutlandırmak için sürükleyin veya haritayı değiştirmek için tıklayın", + "Duration": "Süre", + "East": "Doğu", + "Edit": "Kurgula", + "Edit Annotation": "Ek Açıklamayı Kurgula", + "Edit/Submit": "Kurgula/Gönder", + "Editing Options": "Kurgulama Seçenekleri", + "Embed Selection...": "Seçimi Yerleştir", + "End": "Son", + "Enter Fullscreen": "Tam Ekran Gir", + "Event": "Etkinlik", + "Events": "Etkinlikler", + "Examples...": "Örnekler...", + "Exit Fullscreen": "Tam Ekrandan Çık", + "Feature": "Özellik", + "Find": "Bul", + "Find in All {0}": "Tüm {0} İçinde Bul", + "Find in List": "Listede Bul", + "Find in This {0}": "Bu {0}'da Bul", + "Find on Map": "Haritada Bul", + "Find...": "Bul...", + "Find: All": "Bul: Tümü", + "Find: Alternative Names": "Bul: Alternatif İsimler", + "Find: Geoname": "Bul: Geoisim", + "Find: Name": "Bul: İsim", + "Flag": "Bayrak", + "Font Size": "Yazı Tipi Boyutu", + "Generating Documentation...": "Dokümantasyon Oluşturuyor...", + "Geoname": "Geo isim", + "Go One Frame Back": "Bir Kare Geri Git", + "Go One Frame Forward": "Bir Kare İleri Git", + "Go One Line Down": "Bir Satır Aşağı Git", + "Go One Line Up": "Bir Satır Yukarı Git", + "Go One Second Back": "Bir Saniye Geri Git", + "Go One Second Forward": "Bir Saniye İleriye Git", + "Go to First Frame": "İlk Kareye Git", + "Go to In Point": "Giriş Noktasına Git", + "Go to Last Frame": "Son Kareye Git", + "Go to Next Annotation": "Sonraki Açıklamaya Git", + "Go to Next Cut": "Sonraki Kesime Git", + "Go to Next Result": "Sonraki Sonuca Git", + "Go to Out Point": "Çıkış Noktasına Git", + "Go to Poster Frame": "Poster Çerçevesine Git", + "Go to Previous Annotation": "Önceki Ek Açıklamaya Git", + "Go to Previous Cut": "Önceki Kesmeye Git", + "Go to Previous Result": "Önceki Sonuca Git", + "Headline": "Başlık", + "Hide": "Sakla", + "Hide Controls": "Kontrolleri Gizle", + "Hide Labels": "Etiketleri Gizle", + "Home": "Ana Sayfa", + "Home Channel": "Ana Kanal", + "Image": "İmge", + "Import Annotations...": "Ek Açıklamaları İçe Aktar...", + "In Current Selection": "Mevcut Seçimde", + "Insert": "Ekle", + "Insert HTML": "HTML Ekle", + "Insert...": "Ekle...", + "Italic": "İtalik", + "Join Clip(s) at Cuts": "Klip(ler)i Kesimlerde Birleştir", + "Keyboard Shortcuts": "Klavye Kısayolları", + "Keyboard Shortcuts...": "Klavye Kısayolları...", + "Large": "Büyük", + "Large Player": "Büyük Oynatıcı", + "Larger": "Daha Büyük", + "Latitude": "Enlem", + "Limit to": "Sınırla", + "Linebreak": "Satır Sonu", + "Link": "Link", + "List": "Liste", + "Longitude": "Boylam", + "Make Clip(s) Static": "Klip(ler)i Statik Yap", + "Map Options": "Harita Seçenekleri", + "Match": "Eşleme", + "Matches": "Eşlemeler", + "Medium": "Orta", + "Monospace": "Monospace", + "Mute": "Sessiz", + "Mute/Unmute": "Sesi Kapat/Sesi Aç", + "Name": "İsim", + "New Event": "Yeni Etkinlik", + "New Place": "Yeni Yer", + "Next": "Sıradaki", + "Next Channel": "Yeni Kanal", + "Next Result": "Bir Sonraki Sonuç", + "No file selected": "Seçili dosya yok", + "No files selected": "Seçili dosya yok", + "North": "Kuzey", + "Numbers": "Sayılar", + "Open in New Tab": "Yeni Sekmede Aç", + "Options": "Seçenekler", + "Other": "Diğer", + "Paragraph": "Paragraf", + "Pause": "Durdur", + "Paused": "Durduruldu", + "Person": "Kişi", + "Place": "Yer", + "Place or Event": "Yer ya da Etkinlik", + "Play": "Oynat", + "Play Current Track": "Seçili Parçayı Çal", + "Play In to Out": "Giriş-Çıkış Arasında Oynat", + "Play Next Track": "Bir Sonraki Parçayı Çal", + "Play/Pause": "Başlat/Durdur", + "Previous": "Önceki", + "Previous Channel": "Önceki Kanal", + "Previous Result": "Önceki Sonuç", + "Region": "Bölge", + "Reload": "Yeniden Yükle", + "Remove": "Kaldır", + "Remove Event": "Etkinliği Kaldır", + "Remove File": "Dosyayı Kaldır", + "Remove Place": "Yeri Kaldır", + "Remove this column": "Bu sütunu kaldır", + "Remove this condition": "Bu koşulu kaldır", + "Remove this group of conditions": "Bu koşul grubunu kaldır ", + "Remove this row": "Bu satırı kaldır", + "Removing...": "Kaldırıyor...", + "Repeat All": "Hepsini Tekrarla", + "Repeat None": "Hiçbirini Tekrarlama", + "Repeat One": "Birini Tekrarla", + "Reset this condition": "Bu koşulu sıfırla", + "Resolution": "Çözünürlük", + "Restart": "Yeniden Başlat", + "Restore Defaults": "Varsayılanları Geri Yükle", + "Results": "Sonuçlar", + "Resume": "Devam Et", + "Right-to-Left": "Sağdan Sola", + "Run Tests": "Testleri Çalıştır", + "Save Changes": "Değişiklikleri Kaydet", + "Save as Smart List": "Akıllı Liste olarak Kaydet", + "Scale to Fill": "Doldurmak için Ölç", + "Scale to Fit": "Sığacak Şekilde Ölç", + "Scroll to Player": "Oyuncuya Kaydır", + "Select Current Annotation": "Geçerli Ek Açılamayı Seç", + "Select Current Cut": "Geçerli Kesimi Seç", + "Select File": "Dosya Seç", + "Select Next Annotation": "Sonraki Açıklamayı Seç", + "Select Previous Annotation": "Önceki Açıklamayı Seç", + "Set ": "Berlie", + "Set In Point": "Giriş Noktası Belirle", + "Set Out Point": "Çıkış Noktası Belirle", + "Set Poster Frame": "Poster Karesi Belirle", + "Settings": "Ayarlar", + "Show Annotations": "Ek Açıklamayı Göster", + "Show Controls": "Kontrol Çubuğunu Göster", + "Show Dates": "Tarihleri Göster", + "Show Labels": "Etiketleri Göster", + "Show Other": "Diğerini Göster", + "Show People": "İnsanları Göster", + "Show Places": "Yerleri Göster", + "Show Remaining Time": "Kalan Zamanı Göster", + "Show Subtitles": "Altyazıları Göster", + "Show Users": "Kullanıcıları Göster", + "Shuffle": "Karıştır", + "Small": "Küçük", + "Small Player": "Küçük Oynatıcı", + "Smaller": "Daha Küçük", + "Sort Annotations": "Ek Açıklamayı Düzenle", + "South": "Güney", + "Split Clip(s) at Cuts": "Klip(ler)i Kesimlerde Böl", + "Start": "Başlat", + "Street": "Sokak", + "Strike": "Üstünü Çiz", + "Subscript": "Alt Simge", + "Subtitles": "Altyazılar", + "Superscript": "Üst Simge", + "Switch Theme": "Temayı Değiştir", + "Timeline": "Zaman Çizelgesi", + "Title": "Başlık", + "Turn Volume Down": "Sesi Kıs", + "Turn Volume Up": "Sesi Aç", + "Type": "Tür", + "Underline": "Altını Çiz", + "Undo Changes": "Değişiklikleri Geri Al", + "Unmute": "Sesi Aç", + "Untitled": "İsimsiz", + "User": "Kullanıcı", + "Valid": "Geçerli", + "View": "Görüntüle", + "View Live": "Canlı Görüntüle", + "View Source": "Kaynağı Görüntüle", + "View as Grid": "Izgara Olarak Görüntüle", + "View as List": "Liste Olarak Görüntüle", + "Volume": "Ses Seviyesi", + "West": "Batı", + "add": "ekle", + "all": "hepsi", + "and": "ve", + "annotations": "ek açıklamalar", + "any": "herhangi", + "ascending": "artan", + "bracket": "parantez", + "contains": "içerir", + "descending": "azalan", + "does not contain": "içermez", + "does not end with": "ile bitmiyor", + "does not start with": "ile başlamaz", + "ends with": "ile biter", + "file": "dosya", + "files": "dosyalar", + "in": "içinde", + "is": "", + "is after": "sonra", + "is before": "önce", + "is between": "arasında", + "is greater than": "'den büyüktür", + "is less than": "daha azdır", + "is not": "değil", + "is not after": "sonra değil", + "is not before": "önce değil", + "is not between": "arasında değil", + "is not greater than": "daha büyük değil", + "is not less than": "daha az değil", + "items": "öğeler", + "of the following conditions": "aşağıdaki koşullardan", + "order": "sırala", + "sorted by": "göre sırala", + "starts with": "ile başla", + "unknown": "bilinmiyor", + "{0} Century": "Yüzyıl", + "{0} Century BC": "Yüzyıl MÖ", + "{0} Millennium": "{0} Milenyum", + "{0} Millennium BC": "MÖ {0} Milenyum" +} diff --git a/tools/build/build.py b/tools/build/build.py index 8accbd3d..ec3cc568 100755 --- a/tools/build/build.py +++ b/tools/build/build.py @@ -80,13 +80,13 @@ def build_oxjs(downloads=False, geo=False): path = source_path + 'UI/svg/' for filename in [filename for filename in os.listdir(path) if not filename[0] in '._']: svg = read_text(path + filename) - svg = re.sub('\n\s*', '', svg) - svg = re.sub('', '', svg) + svg = re.sub(r'\n\s*', '', svg) + svg = re.sub(r'', '', svg) # end fix ui_images[filename[:-4]] = svg if filename.startswith('symbolLoading'): for theme in themes: - theme_svg = re.sub('#808080', format_hex(theme_data[theme]['symbolDefaultColor']), svg) + theme_svg = re.sub(r'#808080', format_hex(theme_data[theme]['symbolDefaultColor']), svg) write_file('%sUI/themes/%s/svg/%s' % (dev_path, theme, filename), theme_svg) write_file('%sUI/themes/%s/svg/%s' % (min_path, theme, filename), theme_svg) @@ -101,10 +101,10 @@ def build_oxjs(downloads=False, geo=False): and (geo or '/Geo/' not in path): # write copies in min path source = os.path.join(path, filename) - is_jquery = re.search('^jquery-[\d\.]+\.js$', filename) - is_jquery_min = re.search('^jquery-[\d\.]+\.min\.js$', filename) - is_jquery_plugin = re.search('^jquery\..*?\.js$', filename) - is_jsonc = re.search('\.jsonc$', filename) + is_jquery = re.search(r'^jquery-[\d\.]+\.js$', filename) + is_jquery_min = re.search(r'^jquery-[\d\.]+\.min\.js$', filename) + is_jquery_plugin = re.search(r'^jquery\..*?\.js$', filename) + is_jsonc = re.search(r'\.jsonc$', filename) if is_jquery or is_jquery_min: target = os.path.join(path.replace(source_path, min_path), 'jquery.js') else: @@ -113,7 +113,7 @@ def build_oxjs(downloads=False, geo=False): ui_files['dev'].append(target.replace(min_path, '')) ui_files['min'].append(target.replace(min_path, '')) if '/Ox/js/' not in source and '/UI/js/' not in source and not is_jquery: - if re.match('^Ox\..+\.js$', filename) or is_jsonc: + if re.match(r'^Ox\..+\.js$', filename) or is_jsonc: js = read_text(source) print('minifiy and write', filename, target) write_file(target, ox.js.minify(js, '' if is_jsonc else comment)) @@ -129,7 +129,7 @@ def build_oxjs(downloads=False, geo=False): if not is_jquery_min: write_link(link_source, link_target) # locales - match = re.search('/(\w+)/json/locale.(\w+).json', source) + match = re.search(r'/(\w+)/json/locale.(\w+).json', source) if match: module = match.group(1) locale = match.group(2) @@ -182,12 +182,12 @@ def build_oxjs(downloads=False, geo=False): if not js_dir + filename in sum(ox_files, []): ox_files[-1].append(js_dir + filename) js = re.sub( - 'Ox.LOCALES = \{\}', + r'Ox.LOCALES = \{\}', 'Ox.LOCALES = ' + json.dumps(locales, indent=4, sort_keys=True), js ) js = re.sub( - "Ox.VERSION = '([\d\.]+)'", + r"Ox.VERSION = '([\d\.]+)'", "Ox.VERSION = '%s'" % version, js ) @@ -238,7 +238,7 @@ def build_oxjs(downloads=False, geo=False): data = { # sum(list, []) is flatten 'documentation': sorted(sum(ox_files, [])) + sorted(list(filter( - lambda x: re.search('\.js$', x), + lambda x: re.search(r'\.js$', x), ui_files['dev'] )) + ['%s/%s.js' % (x, x) for x in ['Geo', 'Image', 'Unicode']]), 'examples': sorted(sum(map( @@ -250,7 +250,7 @@ def build_oxjs(downloads=False, geo=False): ) )), list(filter( - lambda x: not re.search('^[._]', x), + lambda x: not re.search(r'^[._]', x), os.listdir(root_path + 'examples/') )) ), [])) if os.path.exists(root_path + 'examples/') else (), @@ -264,7 +264,7 @@ def build_oxjs(downloads=False, geo=False): 'title': get_title(root_path + 'readme/' + x) }, filter( - lambda x: not re.search('^[._]', x) and re.search('\.html$', x), + lambda x: not re.search(r'^[._]', x) and re.search(r'\.html$', x), os.listdir(root_path + 'readme/') ) )) @@ -355,7 +355,7 @@ def parse_css(css, values): ) for vals in value] ) return string - return re.sub('\$(\w+)(\[\d+\])?', sub, css) + return re.sub(r'\$(\w+)(\[\d+\])?', sub, css) def read_file(file): print('reading', file)