diff options
-rw-r--r-- | actions/login.php | 2 | ||||
-rw-r--r-- | actions/newnotice.php | 9 | ||||
-rw-r--r-- | js/geometa.js | 216 | ||||
-rw-r--r-- | js/util.js | 14 | ||||
-rw-r--r-- | lib/action.php | 1 | ||||
-rw-r--r-- | lib/noticeform.php | 19 |
6 files changed, 257 insertions, 4 deletions
diff --git a/actions/login.php b/actions/login.php index 63955e3f5..cee29fd09 100644 --- a/actions/login.php +++ b/actions/login.php @@ -164,7 +164,7 @@ class LoginAction extends Action } else { $url = common_local_url('all', array('nickname' => - $nickname)); + $user->nickname)); } common_redirect($url, 303); diff --git a/actions/newnotice.php b/actions/newnotice.php index fbd7ab6bc..dd6da0b01 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -164,6 +164,11 @@ class NewnoticeAction extends Action $replyto = 'false'; } + $lat = $this->trimmed('lat'); + $lon = $this->trimmed('lon'); + $location_id = $this->trimmed('location_id'); + $location_ns = $this->trimmed('location_ns'); + $upload = null; $upload = MediaFile::fromUpload('attach'); @@ -183,7 +188,9 @@ class NewnoticeAction extends Action } $notice = Notice::saveNew($user->id, $content_shortened, 'web', 1, - ($replyto == 'false') ? null : $replyto); + ($replyto == 'false') ? null : $replyto, + null, null, + $lat, $lon, $location_id, $location_ns); if (isset($upload)) { $upload->attachToNotice($notice); diff --git a/js/geometa.js b/js/geometa.js new file mode 100644 index 000000000..ced5be060 --- /dev/null +++ b/js/geometa.js @@ -0,0 +1,216 @@ +// A shim to implement the W3C Geolocation API Specification using Gears or the Ajax API +if ( typeof navigator.geolocation == "undefined" || navigator.geolocation.shim ) (function(){ + +// -- BEGIN GEARS_INIT +(function() { + // We are already defined. Hooray! + if (window.google && google.gears) { + return; + } + + var factory = null; + + // Firefox + if (typeof GearsFactory != 'undefined') { + factory = new GearsFactory(); + } else { + // IE + try { + factory = new ActiveXObject('Gears.Factory'); + // privateSetGlobalObject is only required and supported on WinCE. + if (factory.getBuildInfo().indexOf('ie_mobile') != -1) { + factory.privateSetGlobalObject(this); + } + } catch (e) { + // Safari + if ((typeof navigator.mimeTypes != 'undefined') + && navigator.mimeTypes["application/x-googlegears"]) { + factory = document.createElement("object"); + factory.style.display = "none"; + factory.width = 0; + factory.height = 0; + factory.type = "application/x-googlegears"; + document.documentElement.appendChild(factory); + } + } + } + + // *Do not* define any objects if Gears is not installed. This mimics the + // behavior of Gears defining the objects in the future. + if (!factory) { + return; + } + + // Now set up the objects, being careful not to overwrite anything. + // + // Note: In Internet Explorer for Windows Mobile, you can't add properties to + // the window object. However, global objects are automatically added as + // properties of the window object in all browsers. + if (!window.google) { + google = {}; + } + + if (!google.gears) { + google.gears = {factory: factory}; + } +})(); +// -- END GEARS_INIT + +var GearsGeoLocation = (function() { + // -- PRIVATE + var geo = google.gears.factory.create('beta.geolocation'); + + var wrapSuccess = function(callback, self) { // wrap it for lastPosition love + return function(position) { + callback(position); + self.lastPosition = position; + } + } + + // -- PUBLIC + return { + shim: true, + + type: "Gears", + + lastPosition: null, + + getCurrentPosition: function(successCallback, errorCallback, options) { + var self = this; + var sc = wrapSuccess(successCallback, self); + geo.getCurrentPosition(sc, errorCallback, options); + }, + + watchPosition: function(successCallback, errorCallback, options) { + geo.watchPosition(successCallback, errorCallback, options); + }, + + clearWatch: function(watchId) { + geo.clearWatch(watchId); + }, + + getPermission: function(siteName, imageUrl, extraMessage) { + geo.getPermission(siteName, imageUrl, extraMessage); + } + + }; +})(); + +var AjaxGeoLocation = (function() { + // -- PRIVATE + var loading = false; + var loadGoogleLoader = function() { + if (!hasGoogleLoader() && !loading) { + loading = true; + var s = document.createElement('script'); + s.src = 'http://www.google.com/jsapi?callback=_google_loader_apiLoaded'; + s.type = "text/javascript"; + document.getElementsByTagName('body')[0].appendChild(s); + } + }; + + var queue = []; + var addLocationQueue = function(callback) { + queue.push(callback); + } + + var runLocationQueue = function() { + if (hasGoogleLoader()) { + while (queue.length > 0) { + var call = queue.pop(); + call(); + } + } + } + + window['_google_loader_apiLoaded'] = function() { + runLocationQueue(); + } + + var hasGoogleLoader = function() { + return (window['google'] && google['loader']); + } + + var checkGoogleLoader = function(callback) { + if (hasGoogleLoader()) return true; + + addLocationQueue(callback); + + loadGoogleLoader(); + + return false; + }; + + loadGoogleLoader(); // start to load as soon as possible just in case + + // -- PUBLIC + return { + shim: true, + + type: "ClientLocation", + + lastPosition: null, + + getCurrentPosition: function(successCallback, errorCallback, options) { + var self = this; + if (!checkGoogleLoader(function() { + self.getCurrentPosition(successCallback, errorCallback, options); + })) return; + + if (google.loader.ClientLocation) { + var cl = google.loader.ClientLocation; + + var position = { + latitude: cl.latitude, + longitude: cl.longitude, + altitude: null, + accuracy: 43000, // same as Gears accuracy over wifi? + altitudeAccuracy: null, + heading: null, + velocity: null, + timestamp: new Date(), + + // extra info that is outside of the bounds of the core API + address: { + city: cl.address.city, + country: cl.address.country, + country_code: cl.address.country_code, + region: cl.address.region + } + }; + + successCallback(position); + + this.lastPosition = position; + } else if (errorCallback === "function") { + errorCallback({ code: 3, message: "Using the Google ClientLocation API and it is not able to calculate a location."}); + } + }, + + watchPosition: function(successCallback, errorCallback, options) { + this.getCurrentPosition(successCallback, errorCallback, options); + + var self = this; + var watchId = setInterval(function() { + self.getCurrentPosition(successCallback, errorCallback, options); + }, 10000); + + return watchId; + }, + + clearWatch: function(watchId) { + clearInterval(watchId); + }, + + getPermission: function(siteName, imageUrl, extraMessage) { + // for now just say yes :) + return true; + } + + }; +})(); + +// If you have Gears installed use that, else use Ajax ClientLocation +navigator.geolocation = (window.google && google.gears) ? GearsGeoLocation : AjaxGeoLocation; + +})(); diff --git a/js/util.js b/js/util.js index c59c63910..9c79f837f 100644 --- a/js/util.js +++ b/js/util.js @@ -46,7 +46,11 @@ var SN = { // StatusNet NoticeInReplyTo: 'notice_in-reply-to', NoticeDataAttach: 'notice_data-attach', NoticeDataAttachSelected: 'notice_data-attach_selected', - NoticeActionSubmit: 'notice_action-submit' + NoticeActionSubmit: 'notice_action-submit', + NoticeLat: 'notice_data-lat', + NoticeLon: 'notice_data-lon', + NoticeLocationId: 'notice_data-location_id', + NoticeLocationNs: 'notice_data-location_ns' } }, @@ -351,6 +355,13 @@ var SN = { // StatusNet }); }, + NoticeLocationAttach: function() { + if(navigator.geolocation) navigator.geolocation.watchPosition(function(position) { + $('#'+SN.C.S.NoticeLat).val(position.coords.latitude); + $('#'+SN.C.S.NoticeLon).val(position.coords.longitude); + }); + }, + NewDirectMessage: function() { NDM = $('.entity_send-a-message a'); NDM.attr({'href':NDM.attr('href')+'&ajax=1'}); @@ -387,6 +398,7 @@ var SN = { // StatusNet }); SN.U.NoticeDataAttach(); + SN.U.NoticeLocationAttach(); } }, diff --git a/lib/action.php b/lib/action.php index 9c7060bba..8ad391755 100644 --- a/lib/action.php +++ b/lib/action.php @@ -259,6 +259,7 @@ class Action extends HTMLOutputter // lawsuit Event::handle('StartShowLaconicaScripts', array($this))) { $this->script('js/xbImportNode.js'); $this->script('js/util.js'); + $this->script('js/geometa.js'); // Frame-busting code to avoid clickjacking attacks. $this->element('script', array('type' => 'text/javascript'), 'if (window.top !== window.self) { window.top.location.href = window.self.location.href; }'); diff --git a/lib/noticeform.php b/lib/noticeform.php index 1be011c18..ec8624597 100644 --- a/lib/noticeform.php +++ b/lib/noticeform.php @@ -76,6 +76,15 @@ class NoticeForm extends Form var $inreplyto = null; /** + * Pre-filled location content of the form + */ + + var $lat; + var $lon; + var $location_id; + var $location_ns; + + /** * Constructor * * @param HTMLOutputter $out output channel @@ -83,13 +92,17 @@ class NoticeForm extends Form * @param string $content content to pre-fill */ - function __construct($out=null, $action=null, $content=null, $user=null, $inreplyto=null) + function __construct($out=null, $action=null, $content=null, $user=null, $inreplyto=null, $lat=null, $lon=null, $location_id=null, $location_ns=null) { parent::__construct($out); $this->action = $action; $this->content = $content; $this->inreplyto = $inreplyto; + $this->lat = $lat; + $this->lon = $lon; + $this->location_id = $location_id; + $this->location_ns = $location_ns; if ($user) { $this->user = $user; @@ -188,6 +201,10 @@ class NoticeForm extends Form $this->out->hidden('notice_return-to', $this->action, 'returnto'); } $this->out->hidden('notice_in-reply-to', $this->inreplyto, 'inreplyto'); + $this->out->hidden('notice_data-lat', empty($this->lat) ? null : $this->lat, 'lat'); + $this->out->hidden('notice_data-lon', empty($this->lon) ? null : $this->lon, 'lon'); + $this->out->hidden('notice_data-location_id', empty($this->location_id) ? null : $this->location_id, 'location_id'); + $this->out->hidden('notice_data-location_ns', empty($this->location_ns) ? null : $this->location_ns, 'location_ns'); Event::handle('StartShowNoticeFormData', array($this)); } |