From d70e713c92f67eae42418daebc3503909dedf14b Mon Sep 17 00:00:00 2001 From: rolux Date: Sat, 24 Jul 2010 03:32:08 +0200 Subject: [PATCH] maps --- build/css/ox.ui.css | 29 +- build/css/ox.ui.modern.css | 20 +- build/js/ox.ui.js | 758 ++++++++++++++++++++++++++++--- build/png/ox.ui/markerBlue.png | Bin 0 -> 3239 bytes build/png/ox.ui/markerGreen.png | Bin 0 -> 3234 bytes build/png/ox.ui/markerRed.png | Bin 0 -> 3233 bytes build/png/ox.ui/markerYellow.png | Bin 0 -> 3207 bytes source/psd/buttons.psd | Bin 35290 -> 40226 bytes source/psd/loading.psd | Bin 0 -> 42426 bytes source/psd/marker.psd | Bin 0 -> 59013 bytes 10 files changed, 737 insertions(+), 70 deletions(-) create mode 100644 build/png/ox.ui/markerBlue.png create mode 100644 build/png/ox.ui/markerGreen.png create mode 100644 build/png/ox.ui/markerRed.png create mode 100644 build/png/ox.ui/markerYellow.png create mode 100644 source/psd/loading.psd create mode 100644 source/psd/marker.psd diff --git a/build/css/ox.ui.css b/build/css/ox.ui.css index da9044c..d278f56 100644 --- a/build/css/ox.ui.css +++ b/build/css/ox.ui.css @@ -136,10 +136,11 @@ Dialog .OxDialog > .OxContent { top: 24px; + bottom: 24px; height: 100%; - padding: 16px; - font-size: 12px; - line-height: 16px; + //padding: 16px; + //font-size: 12px; + //line-height: 16px; } .OxDialog > .OxButtonsBar { @@ -359,7 +360,7 @@ OxButtonGroup } /* -------------------------------------------------------------------------------- -OxFormItem +OxForm -------------------------------------------------------------------------------- */ .OxFormItem { @@ -368,6 +369,13 @@ OxFormItem .OxFormItem:first-child { margin-top: 0; } +.OxFormMessage { + width: 100%; + height: 10px; + margin-top: 2px; + text-align: right; + display: none; +} /* -------------------------------------------------------------------------------- OxInput @@ -960,4 +968,17 @@ Scrollbars -webkit-border-radius: 6px; } +/* +================================================================================ +Miscellaneous +================================================================================ +*/ +.OxThemeModern .OxTooltip { + position: absolute; + padding: 2px; + opacity: 0; + z-index: 10; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; +} diff --git a/build/css/ox.ui.modern.css b/build/css/ox.ui.modern.css index 3fc7d87..fc7e1cd 100644 --- a/build/css/ox.ui.modern.css +++ b/build/css/ox.ui.modern.css @@ -35,8 +35,8 @@ Dialog */ .OxThemeModern .OxDialog { - -moz-box-shadow: 0px 0px 8px rgba(0, 0, 0, 1); - -webkit-box-shadow: 0px 0px 8px rgba(0, 0, 0, 1); + -moz-box-shadow: 0 0 8px rgba(0, 0, 0, 1); + -webkit-box-shadow: 0 0 8px rgba(0, 0, 0, 1); } .OxThemeModern .OxDialog .OxBar { @@ -90,6 +90,9 @@ Forms .OxThemeModern .OxButton.OxTab.OxSelected { border-bottom: 1px solid rgb(64, 64, 64); } +.OxThemeModern .OxFormMessage { + color: rgb(255, 64, 64); +} .OxThemeModern .OxInput, .OxThemeModern .OxTrack { background: -moz-linear-gradient(top, rgb(0, 0, 0), rgb(32, 32, 32)); @@ -238,4 +241,17 @@ Scrollbars .OxThemeModern ::-webkit-scrollbar:active, .OxThemeModern ::-webkit-scrollbar-thumb:active { background: rgb(64, 64, 64); +} + +/* +================================================================================ +Miscellaneous +================================================================================ +*/ + +.OxThemeModern .OxTooltip { + border: 1px solid rgb(255, 255, 255); + background: rgba(0, 0, 0, 0.9); + -moz-box-shadow: 2px 2px 4px rgba(0, 0, 0, 1); + -webkit-box-shadow: 2px 2px 4px rgba(0, 0, 0, 1); } \ No newline at end of file diff --git a/build/js/ox.ui.js b/build/js/ox.ui.js index a1173b6..9f6da7d 100644 --- a/build/js/ox.ui.js +++ b/build/js/ox.ui.js @@ -1131,6 +1131,66 @@ requires return that; }; + /* + ---------------------------------------------------------------------------- + Ox.Window + ---------------------------------------------------------------------------- + */ + + Ox.Window = function(options, self) { + + self = self || {}, + that = new Ox.Element("div", self) + .defaults({ + draggable: true, + fullscreenable: true, // fixme: silly name + height: 225, + resizeable: true, + scaleable: true, + width: 400 + }) + .options(options || {}) + + self.center = function() { + + }; + + self.drag = function() { + + }; + + self.fullscreen = function() { + + }; + + self.onChange = function() { + + }; + + self.reset = function() { + + }; + + self.resize = function() { + + }; + + self.scale = function() { + + }; + + that.close = function() { + + }; + + that.open = function() { + + }; + + return that; + + }; + /* ---------------------------------------------------------------------------- Ox.theme() @@ -1354,6 +1414,7 @@ requires Ox.Dialog = function(options, self) { // fixme: dialog should be derived from a generic draggable + // fixme: pass button elements directly var self = self || {}, that = new Ox.Element("div", self) .defaults({ @@ -1362,6 +1423,7 @@ requires height: 216, minHeight: 144, minWidth: 256, + padding: 16, width: 384 }) .options(options || {}) @@ -1382,8 +1444,13 @@ requires .addClass("OxTitle") .html(self.options.title) .appendTo(that.$titlebar); - that.$content = new Ox.Container() + // fixme: should the following be a container? + that.$content = new Ox.Element() .addClass("OxContent") + .css({ + padding: self.options.padding + "px", + overflow: "auto" + }) .appendTo(that); that.$buttonsbar = new Ox.Bar({}) .addClass("OxButtonsBar") @@ -1407,6 +1474,7 @@ requires $.each(self.options.buttons[1].reverse(), function(i, button) { that.$buttons[that.$buttons.length] = new Ox.Button({ disabled: button.disabled || false, + id: button.id, size: "medium", value: button.value }) @@ -1462,6 +1530,17 @@ requires }); } + function getButtonById(id) { + var ret = null + $.each(that.$buttons, function(i, button) { + if (button.options("id") == id) { + ret = button; + return false; + } + }); + return ret; + } + function mousedownLayer() { that.$layer.stop().animate({ opacity: 0.5 @@ -1476,16 +1555,15 @@ requires function reset() { that.css({ - left: Math.max(that.offset().left, 24 - self.options.width) + left: Math.max(that.offset().left, 24 - that.width()) }) .width(self.options.width) .height(self.options.height); - that.$content.height(self.options.height - 80); + that.$content.height(self.options.height - 48 - 2 * self.options.padding); // fixme: this should happen automatically } function resize(event) { - var contentHeight = that.$content.height(), - documentWidth = $document.width(), + var documentWidth = $document.width(), documentHeight = $document.height(), elementWidth = that.width(), elementHeight = that.height(), @@ -1508,7 +1586,7 @@ requires ); that.width(width); that.height(height); - that.$content.height(height - 80); + that.$content.height(height - 48 - 2 * self.options.padding); // fixme: this should happen automatically }); $window.one("mouseup", function() { $window.unbind("mousemove"); @@ -1516,7 +1594,13 @@ requires } self.onChange = function(key, value) { - if (key == "title") { + if (key == "height" || key == "width") { + that.animate({ + height: self.options.height + "px", + width: self.options.width + "px" + }, 250); + that.$content.height(self.options.height - 48 - 2 * self.options.padding); // fixme: this should happen automatically + } else if (key == "title") { that.$title.animate({ opacity: 0 }, 250, function() { @@ -1551,10 +1635,22 @@ requires return that; }; + that.disableButton = function(id) { + getButtonById(id).options({ + disabled: true + }); + }; + that.enable = function() { that.$layer.removeClass("OxFront"); return that; - } + }; + + that.enableButton = function(id) { + getButtonById(id).options({ + disabled: false + }); + }; that.open = function() { that.$layer.appendTo($body); @@ -1567,7 +1663,7 @@ requires }, 200); $window.bind("mouseup", mouseupLayer) return that; - } + }; return that; @@ -1579,6 +1675,31 @@ requires ============================================================================ */ + /* + ---------------------------------------------------------------------------- + Ox.Filter + ---------------------------------------------------------------------------- + */ + + Ox.Filter = function(options, self) { + + var self = self || {} + that = new Ox.Element() + .defaults({ + + }) + .options(options || {}); + + return that; + + }; + + /* + ---------------------------------------------------------------------------- + Ox.Form + ---------------------------------------------------------------------------- + */ + Ox.Form = function(options, self) { var self = self || {}, @@ -1586,40 +1707,79 @@ requires .defaults({ error: "", id: "", - items: [] + items: [], + submit: null }) .options(options || {}); // fixme: the || {} can be done once, in the options function $.extend(self, { + $items: [], + $messages: [], formIsValid: false, - itemIsValid: $.map(self.options.items, function(item, i) { - return false; - }) + itemIds: [], + itemIsValid: [] + }); + + // fixme: form isn't necessarily empty/invalid + $.map(self.options.items, function(item, i) { + self.itemIds[i] = item.id || item.element.options("id"); + self.itemIsValid[i] = false; }); $.each(self.options.items, function(i, item) { - item.element.change(function() { - validate(i); - }) - that.append(new Ox.FormItem(item)); + var id = item.element.options("id"); + that.append(self.$items[i] = new Ox.FormItem(item)) + .append(self.$messages[i] = new Ox.Element().addClass("OxFormMessage")); + Ox.Event.bind("validate_" + id, function(event, data) { + validate(i, data.valid); + }); + Ox.Event.bind("blur_" + id, function(event, data) { + validate(i, data.valid); + if (data.valid) { + self.$messages[i].html("").hide(); + } else { + self.$messages[i].html(data.message).show(); + } + }); + Ox.Event.bind("submit_" + id, function(event, data) { + self.formIsValid && that.submit(); + }); }); - function validate(pos) { - var item = self.options.items[pos]; - self.itemIsValid[pos] = item[item.validate ? "validate" : "regexp"](item.element.$input.val()); // fixme: Input elements should overwrite / have their own val() + function getItemPositionById(id) { + return self.itemIds.indexOf(id); + } + + function setMessage(id, message) { + self.$messages[getItemPositionById(id)].html(message)[message !== "" ? "show" : "hide"](); + } + + function submitCallback(data) { + $.each(data, function(i, v) { + setMessage(v.id, v.message); + }); + } + + function validate(pos, valid) { + Ox.print("validate", pos, valid) + self.itemIsValid[pos] = valid; if (Ox.every(self.itemIsValid) != self.formIsValid) { self.formIsValid = !self.formIsValid; - that.triggerEvent("change", { - valid: formIsValid + that.triggerEvent("validate", { + valid: self.formIsValid }); } } - that.values = function() { + that.submit = function() { + self.options.submit(that.values(), submitCallback); + }; + + that.values = function() { // fixme: can this be private? var values = {}; if (arguments.length == 0) { - $.each(self.options.items, function(i, item) { - values[item.id] = item.val(); + $.each(self.$items, function(i, $item) { + values[self.itemIds[i]] = self.$items[i].value(); }); return values; } else { @@ -1641,13 +1801,15 @@ requires .defaults({ element: null, error: "", - regexp: /.*/, - validate: null }) .options(options || {}) .addClass("OxFormItem") .append(self.options.element); + that.value = function() { + return self.options.element.$input.val(); + }; + return that; } @@ -1740,7 +1902,12 @@ requires } self.onChange = function(key, value) { //Ox.print("setOption", option, value) - if (key == "selected") { + if (key == "disabled") { + that.attr({ + disabled: value ? "disabled" : "" + }) + .toggleClass("OxDisabled"); + } else if (key == "selected") { if (value != that.hasClass("OxSelected")) { // fixme: neccessary? that.toggleClass("OxSelected"); } @@ -1848,6 +2015,7 @@ requires /* options: * autocomplete function, or array of values, or dict with array of values per label or placeholder + * autocorrect function for live correction * clear boolean, clear button, or not * highlight boolean, highlight value in autocomplete menu, or not * id @@ -1857,12 +2025,15 @@ requires * selected integer, selected label or placeholder * size "large", "medium" or "small" * type "text", "password", "textarea", etc. + * validate function vor live validation, returns { message: "", valid: false } + * value string */ var self = self || {}, that = new Ox.Element("div", self) .defaults({ autocomplete: null, + autocorrect: null, clear: false, highlight: false, id: "", @@ -1871,7 +2042,9 @@ requires placeholder: "", selected: 0, size: "medium", - type: "text" + type: "text", + validate: null, + value: "" }) .options(options || {}) .addClass("OxInput Ox" + Ox.toTitleCase(self.options.size)), @@ -1981,11 +2154,18 @@ requires key_enter: submit, }); } + + /* + if (self.options.validate) { + self.valid = self.options.validate(self.options.value); + } + */ + that.bindEvent({ key_escape: cancel }); - function autocomplete(value, callback) { + function autocomplete(value) { var value = value.toLowerCase(), items = []; if (value === "") { @@ -1997,38 +2177,26 @@ requires } }); } - callback(items); + autocompleteCallback(items); } - function blur() { - that.loseFocus(); - that.removeClass("OxFocus"); - if (self.options.placeholder && that.$input.val() === "") { - that.$input.addClass("OxPlaceholder").val(self.option); - } - if (self.options.autocomplete) { - $document.unbind("keydown", keypress); - $document.unbind("keypress", keypress); - } - } - - function call() { + function autocompleteCall() { var value = that.$input.val(); Ox.print("autocomplete call", self.option, value) if (self.options.autocomplete) { if (value !== "") { Ox.isFunction(self.options.autocomplete) ? ( self.option ? - self.options.autocomplete(self.option.id, value, callback) : - self.options.autocomplete(value, callback) - ) : autocomplete(value, callback); + self.options.autocomplete(self.option.id, value, autocompleteCallback) : + self.options.autocomplete(value, autocompleteCallback) + ) : autocomplete(value); } else { - callback(); + autocompleteCallback(); } } } - function callback(items) { + function autocompleteCallback(items) { Ox.print("autocomplete callback", items) var items = items || [], selected = items.length == 1 ? 0 : -1, @@ -2056,6 +2224,34 @@ requires } } + function autocorrect(blur) { + var blur = blur || false, + length = self.value.length; + pos = cursor(), + self.value = self.options.autocorrect(self.value, blur); + that.$input.val(self.value); + if (!blur) { + cursor(pos + self.value.length - length); + } + } + + function blur() { + that.loseFocus(); + that.removeClass("OxFocus"); + self.options.autocorrect && autocorrect(that.$input.val(), true); + self.options.validate && that.triggerEvent("blur", { // fixme: is this a good event name for validation on blur? + message: self.message, + valid: self.valid + }); + if (self.options.placeholder && that.$input.val() === "") { + that.$input.addClass("OxPlaceholder").val(self.option); + } + if (self.options.autocomplete || self.options.autocorrect || self.options.validate) { // fixme: duplicated, make a var + $document.unbind("keydown", keypress); + $document.unbind("keypress", keypress); + } + } + function cancel() { that.$input.blur(); } @@ -2071,21 +2267,30 @@ requires if (self.options.label) { that.$label.html(self.option.title); that.$input.focus(); - call(); + autocompleteCall(); } else { if (that.$input.is(".OxPlaceholder")) { that.$input.val(self.option); //that.$input.focus(); } else { that.$input.focus(); - call(); + autocompleteCall(); } } } function clear() { that.$input.val("").focus(); - //call(); + //autocompleteCall(); + } + + function cursor() { + // fixme: see selection() + if (arguments.length == 0) { + return that.$input.$element[0].selectionStart; + } else { + that.$input.$element[0].setSelectionRange(arguments[0], arguments[0]); + } } function focus() { @@ -2096,13 +2301,15 @@ requires that.$input.val("").removeClass("OxPlaceholder"); } value = that.$input.val(); - if (self.options.autocomplete) { + if (self.options.autocomplete || self.options.autocorrect || self.options.validate) { // fixme: different in webkit and firefox (?), see keyboard handler, need generic function $document.bind("keydown", keypress); $document.bind("keypress", keypress); - value !== "" && Ox.isFunction(self.options.autocomplete) ? - self.options.autocomplete(self.option.id, value, callback) : - autocomplete(value, callback); + if (self.options.autocomplete) { + value !== "" && Ox.isFunction(self.options.autocomplete) ? + self.options.autocomplete(self.option.id, value, autocompleteCallback) : + autocomplete(value); + } } } @@ -2112,7 +2319,9 @@ requires var value = that.$input.val(); if (value != self.value) { self.value = value; - call(); + self.options.autocomplete && autocompleteCall(); + self.options.autocorrect && autocorrect(); + self.options.validate && validateCall(); } }, 25); } @@ -2150,6 +2359,40 @@ requires } : that.$input.val()); } + function validate() { + var value = that.$input.val(), + valid = self.options.validate(value) != null; + validateCallback({ + valid: valid, + message: "Invalid " + self.options.label + }); + } + + function validateCall() { + var value = that.$input.val(); + Ox.print("validate call", value) + if (self.options.validate) { + if (value !== "") { + Ox.isFunction(self.options.validate) ? + self.options.validate(value, validateCallback) : + validate(value); + } else { + validateCallback({ + valid: false, + message: "" + }); + } + } + } + + function validateCallback(data) { + if (data.valid != self.valid) { + self.message = data.message; + self.valid = data.valid; + that.triggerEvent("validate", data); + } + } + that.changeLabel = function(id) { that.$label.html(Ox.getObjectById(self.options.label, id).title); self.selectMenu.checkItem(id); @@ -3405,10 +3648,13 @@ requires that.$head.$content.css({ width: (Ox.sum(self.columnWidths) + 2) + "px" }); - toggleSelected(self.options.columns[self.selectedColumn].id); - that.$titles[getColumnPositionById(self.options.columns[self.selectedColumn].id)].css({ - width: (self.options.columns[self.selectedColumn].width - 25) + "px" - }); + Ox.print("s.sC", self.selectedColumn) + if (getColumnPositionById(self.options.columns[self.selectedColumn].id) > -1) { // fixme: save in var + toggleSelected(self.options.columns[self.selectedColumn].id); + that.$titles[getColumnPositionById(self.options.columns[self.selectedColumn].id)].css({ + width: (self.options.columns[self.selectedColumn].width - 25) + "px" + }); + } that.$select = new Ox.Button({ style: "symbol", type: "image", @@ -3672,6 +3918,331 @@ requires }; + /* + ============================================================================ + Maps + ============================================================================ + */ + + Ox.Map = function(options, self) { + + var self = self || {} + that = new Ox.Element("div", self) + .defaults({ + places: [], + type: "satellite" + }) + .options(options || {}); + + init(); + + function getLocationByName(name, callback) { + self.geocoder.geocode({ + address: name + }, function(results, status) { + if (status == google.maps.GeocoderStatus.OK) { + if (status != google.maps.GeocoderStatus.ZERO_RESULTS) { + callback(new Location(results[0])) + } else { + callback(null); + } + } else { + Ox.print("geocode failed:", status); + callback(null); + } + }); + } + + function getLocationByPoint(point, area, callback) { + var callback = arguments.length == 2 ? area : callback, + area = arguments.length == 2 ? null : area, + options = $.extend({ + "latLng": new google.maps.LatLng(point[0], point[1]) + }, area ? { + "bounds": new google.maps.LatLngBounds( + new google.maps.LatLng(area[0][0], area[0][1]), + new google.maps.LatLng(area[1][0], area[1][1]) + ) + } : {}); + self.geocoder.geocode(options, function(results, status) { + var length = results.length; + if (status == google.maps.GeocoderStatus.OK) { + if (status != google.maps.GeocoderStatus.ZERO_RESULTS) { + + } + } + }); + } + + function init() { + var counter = 0, + length = self.options.places.length; + $.extend(self, { + geocoder: new google.maps.Geocoder(), + locations: [] + }); + $.each(self.options.places, function(i, place) { + if (Ox.isString(place)) { + self.options.places[i] = { + name: place + }; + } else if (Ox.isArray(place)) { + self.options.places[i] = { + name: "", + point: place + }; + } + "point" in self.options.places[i] ? + getLocationByPoint(self.options.places[i].point, callback) : + getLocationByName(self.options.places[i].name, callback); + }); + function callback(location) { + if (location) { + Ox.print("counter", counter, location) + self.locations.push(location); + self.bounds = counter == 0 ? location.rectangle.bounds : + self.bounds.union(location.rectangle.bounds); + } + if (counter++ == length - 1) { + loadMap(); + } + } + } + + function loadMap() { + Ox.print("loadMap"); + $.extend(self, { + map: new google.maps.Map(that.$element[0], { + center: self.bounds.getCenter(), + disableDefaultUI: true, + mapTypeId: google.maps.MapTypeId[self.options.type.toUpperCase()], + zoom: 0 + }) + }); + self.map.fitBounds(self.bounds) + google.maps.event.addListener(self.map, "zoom_changed", zoom); + $.each(self.locations, function(i, location) { + location.marker.add(); + }); + }; + + function zoom() { + + } + + function Location(geocode) { + Ox.print("geocode", geocode); + var bounds = geocode.geometry.bounds || geocode.geometry.viewport, + area = [ + [bounds.getSouthWest().lat(), bounds.getSouthWest().lng()], + [bounds.getNorthEast().lat(), bounds.getNorthEast().lng()] + ], + location = { + geocode: geocode, + name: { + formatted: geocode.formatted_address, + long: $.map(geocode.address_components, function(v) { + return v.long_name; + }).join(", ") + }, + rectangle: new Rectangle(area), + }; + Ox.print("area", area) + return $.extend(location, { + marker: new Marker(location), + polygon: new Polygon(location) + }); + } + + function Marker(location) { + var listeners = {}, + marker = new google.maps.Marker({ + icon: icon("blue"), + position: location.rectangle.center, + title: location.name.formatted + }); + function click() { + marker.setOptions({ + icon: icon("red") + }); + location.polygon.add(); + } + function icon(color) { + return "http://dev.pan.do:8000" + oxui.path + "png/ox.ui/marker" + Ox.toTitleCase(color) + ".png" + } + return { + add: function() { + marker.setMap(self.map); + listeners.click = google.maps.event.addListener(marker, "click", click); + }, + remove: function() { + marker.setMap(null); + google.maps.event.removeListener(listeners.click); + } + }; + } + + function Polygon(location) { + var listeners = {}, + points = [ + location.rectangle.latlng.sw, + location.rectangle.latlng.nw, + location.rectangle.latlng.ne, + location.rectangle.latlng.se, + location.rectangle.latlng.sw + ], + polygon = new google.maps.Polygon({ + paths: points + }), + selected = false; + function setOptions() { + var color = selected ? "#8080FF" : "#FFFFFF"; + polygon.setOptions({ + clickable: true, + fillColor: color, + fillOpacity: selected ? 0.1 : 0, + geodesic: true, + strokeColor: color, + strokeOpacity: 1, + strokeWeight: 2 + }); + } + return { + add: function() { + polygon.setMap(self.map); + listeners.click = google.maps.event.addListener(polygon, "click", this.select); + }, + deselect: function() { + selected = false; + setOptions(); + }, + remove: function() { + polygon.setMap(null); + google.maps.event.removeListener(listeners.click); + }, + select: function() { + selected = true; + setOptions(); + } + }; + } + + function Rectangle(area) { + var latlng = { + sw: new google.maps.LatLng(area[0][0], area[0][1]), + ne: new google.maps.LatLng(area[1][0], area[1][1]) + }, + bounds = new google.maps.LatLngBounds(latlng.sw, latlng.ne), + lat = {}, + lng = {}; + latlng.mc = bounds.getCenter(); + $.each(latlng, function(k, v) { + lat[k] = v.lat(); + lng[k] = v.lng(); + }); + $.extend(latlng, { + sc: new google.maps.LatLng(lat.sw, lng.mc), + se: new google.maps.LatLng(lat.sw, lng.mc), + mw: new google.maps.LatLng(lat.sw, lng.mc), + mw: new google.maps.LatLng(lat.sw, lng.mc), + nw: new google.maps.LatLng(lat.sw, lng.mc), + nc: new google.maps.LatLng(lat.sw, lng.mc), + }); + return { + area: area, + bounds: bounds, + canContain: function(rectangle) { + var outerSpan = this.bounds.toSpan(), + innerSpan = rectangle.bounds.toSpan(); + return outerSpan.lat() > innerSpan.lat() && + outerSpan.lng() > innerSpan.lng(); + }, + center: latlng.mc, + contains: function(rectangle) { + return this.bounds.contains(rectangle.bounds.getSouthWest()) && + this.bounds.contains(rectangle.bounds.getNorthEast()); + }, + latlng: latlng + }; + } + + self.onChange = function(key, value) { + if (key == "type") { + + } + }; + + return that; + + }; + + Ox.MapImage = function(options, self) { + + /* + options: + height image height (px) + places array of either names (""), points ([0, 0]), + or objects ({name, point, highlight}) + type map type ("hybrid", "roadmap", "satellite", "terrain") + width image width (px) + */ + + var self = self || {}, + that = new Ox.Element("img", self) + .defaults({ + height: 360, + markerColorHighlight: "yellow", + markerColorNormal: "blue", + places: [], + type: "satellite", + width: 640 + }) + .options(options || {}) + + $.extend(self, { + markers: { + highlight: [], + normal: [] + }, + src: "http://maps.google.com/maps/api/staticmap?sensor=false" + + "&size=" + self.options.width + "x" + self.options.height + + "&maptype=" + self.options.type + }); + + if (self.options.places.length) { + $.each(self.options.places, function(i, place) { + if (Ox.isString(place)) { + self.markers.normal.push(place); + } else if (Ox.isArray(place)) { + self.markers.normal.push(place.join(",")); + } else { + self.markers[place.highlight ? "highlight" : "normal"] + .push("point" in place ? place.point.join(",") : place.name) + } + }); + $.each(self.markers, function(k, markers) { + if (markers.length) { + self.src += "&markers=icon:" + "http://dev.pan.do:8000" + oxui.path + "png/ox.ui/marker" + + Ox.toTitleCase(self.options["markerColor" + Ox.toTitleCase(k)]) + ".png|" + + markers.join("|") + } + }); + } else { + self.src += "¢er=0,0&zoom=2" + } + + that.attr({ + src: self.src + }); + + self.onChange = function(key, value) { + + }; + + return that; + + }; + /* ============================================================================ Menus @@ -4541,7 +5112,8 @@ requires } else if (key == "disabled") { that.toggleClass("OxDisabled"); // fixme: this will only work if onChange is only invoked on actual change } else if (key == "title") { - + self.options.title = Ox.makeArray(value); + that.$title.html(self.options.title[0]); } } @@ -4558,9 +5130,9 @@ requires }; that.toggleTitle = function() { + Ox.print("s.o.t", self.options.title) that.options({ - title: that.$title.html() == self.options.title[0] ? - self.options.title[1] : self.options.title[0] + title: self.options.title.reverse() }); }; @@ -4895,5 +5467,63 @@ requires ---------------------------------------------------------------------------- */ + /* + ============================================================================ + Miscellaneous + ============================================================================ + */ + + /* + ---------------------------------------------------------------------------- + Ox.Tooltip + ---------------------------------------------------------------------------- + */ + + Ox.Tooltip = function(options, self) { + + var self = self || {}, + that = new Ox.Element() + .defaults({ + text: "" + }) + .options(options || {}) + .addClass("OxTooltip") + .html(self.options.text); + + self.onChange = function(key, value) { + if (key == "text") { + that.html(value); + } + }; + + that.hide = function() { + that.animate({ + opacity: 0 + }, 250, function() { + that.remove(); + }); + return that; + }; + + that.show = function(e) { + var left, top, width, height; + that.appendTo($body); + width = that.width(); + height = that.height(); + left = Ox.limit(e.clientX - width / 2, 0, $document.width() - width); + top = e.clientY > $document.height() - height - 16 ? e.clientY - 32 : e.clientY + 16; + that.css({ + left: left + "px", + top: top + "px" + }) + .animate({ + opacity: 1 + }, 250); + return that; + }; + + return that; + + }; })(); \ No newline at end of file diff --git a/build/png/ox.ui/markerBlue.png b/build/png/ox.ui/markerBlue.png new file mode 100644 index 0000000000000000000000000000000000000000..27873e77caa90f8ea28af081d01eb637782634a0 GIT binary patch literal 3239 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 literal 0 HcmV?d00001 diff --git a/build/png/ox.ui/markerGreen.png b/build/png/ox.ui/markerGreen.png new file mode 100644 index 0000000000000000000000000000000000000000..5d614b64f8cc4a5690854e8be12b498cc54daa36 GIT binary patch literal 3234 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 U!EEZbu>b%707*qoM6N<$g7&Kb*Z=?k literal 0 HcmV?d00001 diff --git a/build/png/ox.ui/markerRed.png b/build/png/ox.ui/markerRed.png new file mode 100644 index 0000000000000000000000000000000000000000..dac823049871451b53e8ae7f9088fe745c0d8e80 GIT binary patch literal 3233 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 F8UR3!pJM<3 diff --git a/source/psd/loading.psd b/source/psd/loading.psd new file mode 100644 index 0000000000000000000000000000000000000000..10b5f7fc55e749422989e04d540c16567442c831 GIT binary patch literal 42426 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 literal 0 HcmV?d00001 diff --git a/source/psd/marker.psd b/source/psd/marker.psd new file mode 100644 index 0000000000000000000000000000000000000000..46bcef83780f8652d71742ac03f9210172d67c7c GIT binary patch literal 59013 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