HTML5 Geolocation - Detect location within a specific area - html

I haven't had much of an opportunity to look at HTML5 Geolocation yet, but I'm curious: Is it possible to build a web app that can detect when a user enters a certain area (perimeter) and then return a message or something like that?

You can use watchPosition to get periodic updates of the browser's location, and then in your callback, test to see if the new position is within your area of interest. So if you've defined a function isInArea that checks a position to see if it's in your area of interest, you could do something like:
function positionCallback(position) {
if (isInArea(position)) {
alert("Honey, I'm home!");
}
}
function handleError(error) {
alert("Error!")
}
// Request repeated updates.
var watchId = navigator.geolocation.watchPosition(positionCallback, handleError);
Based on Example of requesting repeated position updates from w3c.

Related

Load new page using d3

I have an SVG map of the U.S., and I would like to make it so that when you click on a state, a new page loads with information about that state.
Here is my code that fills the states (the paths are already created); it's a choropleth so the color is based on murder rates.
d3.selectAll("path")
.attr("fill", function(d) {
return color(murderrates[codes.indexOf(this.id)])
})
.on("click", **load(new page, this.id)**)
The pseudo code between the asterisks is what I'd like to accomplish: when the state is clicked, open a new page and tell it which state was clicked so it knows what information to display. In other words, the new page should be able to "accept an argument" - the state - so it knows what to display.
Edit: I do not have a different page to load for each state. Instead, it is one page that could display 50 different things depending on which state caused it to load. So let's say I had a variable called origin in my new page. I would like the value of origin to be set to this.id upon loading.
Building off of #StephenThomas's comment, you can define a function loadPage that uses this.id to change the window.location:
function loadPage(){
window.location = URL + "?origin=" + this.id;
}
This will open a new page where the query parameter "origin" will contain this.id. You can then parse the query param, e.g. like this.
Then pass that function as the callback to the onclick, as D3 will automatically set the value of this to the appropriate element:
.on("click", loadPage)

Posting a status message to Facebook?

There's so many questions regarding Facebook's sharer.php, but they're all out of date. At first Facebook depreciated it, but according to FB's dev documentation it's now back. (Edit: And now it's going again...?)
You used to be able to use it like this:
http://www.facebook.com/sharer/sharer.php?u=<url to share>&t=<message text>
But the documentation now only mentions this:
https://www.facebook.com/sharer/sharer.php?u=<url to share>
Is it possible to set some pre-entered text into the dialogue box that appears when sharing a link on Facebook?
Thanks.
The Share dialog takes only the URL to share as parameter, nothing else (title, description, picture, …) any more. It fetches this data from the URL itself, from the Open Graph meta elements embedded into the document, or it takes a “guess” from the content if those are not present.
And even the “older” version of the Share dialog has not been taking a pre-set message parameter for a long time now – because you are not supposed to pre-fill the message in any way when sharing something, not matter what way the share actually happens. (“Not supposed to” actually meaning, Platform Policies explicitly forbid you from doing so.)
You can of course also share links via API (rather called “posting” a link then) – and because that happens in the background, the message is a parameter you specify while doing so. But the same rules apply – the message is supposed to be created by the user themselves beforehand, which effectively means they should have typed it in somewhere before. And even there it should not have been pre-filled so that they just have to press enter or click a button.
And since they announced API v2.0, all new apps will have to go through “login review” before they will be able to ask for any advanced permission (and posting a link requires one) – and with a pre-filled message in your app’s posting flow, you will definitively not get approval. Of course, you could try to “cheat” on that, and implement the pre-filling of the message only afterwards … but again, doing so is a clear violation of Platform Policies, and will get your app blocked when you are caught doing so.
And if you are planning to do this for multiple users with the same or largely similar messages, you can assume that Facebook’s algorithms will catch that quite easily.
Just one small comment - while it is not possible to edit the text as the other comments say - it is possible to edit everything going on in that page if you can install a browser extension on your client's machines (you did not specify your use case so I am mentioning this just in case you are developing something that you are able to influence in the client machine level).
For example, with a chrome extension, you can inject scripts into facebook.com domain. in the extension manifest.json:
"content_scripts": [
{
"matches": ["https://*.facebook.com/*",
And then this might be your contnet script, where you can play around with the text by hooking up to the markeup. This example sends out analytics (facebook sharer conversion rate) and changes some text (from "share" to "upload" to facebook):
sharer = (function () {
var _ref = qs('ref') ? qs('ref') : 'unknown';
function qs(name) {
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
function isSharer() {
return location.pathname === '/sharer/sharer.php';
}
function bindEvents() {
$('button[name="share"]').click(function() {
analytics.send('fb_sharer', 'share', _ref);
});
$('#u_0_0').click(function() {
analytics.send('fb_sharer', 'cancel', _ref);
});
}
function changeText() {
console.log($('.fcw').length);
$('.fcw').text('Upload to Facebook');
}
function load() {
if (!isSharer()) return;
changeText();
analytics.send('fb_sharer', 'view', _ref);
bindEvents();
}
return {
load: load
}
})();

Accessing <iframe> upon an event in the iframe - with a chrome extension

Using an extension, I'd like to measure the offset of an iframe (relative to the top window) when a specific event happens in it.
This includes iframes of different origins.
It seems to require two things:
catching the event in the iframe's own content-document
finding the iframe's corresponding DOM element (<iframe>) in its parent window and measuring its offset
I can run a content-script in all iframes which would catch the specific event, but I fail to identify an iframe's corresponding DOM element in iframes with different origins, since in those cases I'm denied access to 'window.frameElement'.
Any ideas?
I could perhaps look for an element with an 'src' attribute corresponding to 'window.location.href' as seen in the context of the iframe's content-script, but 'window.location.href' wouldn't be a unique identifier... or would it?
You could take the following approach:
Use the "all_frames":true flag of "content_scripts" in the manifest file to execute the content script in all frames.
Bind a message event listener which performs the logic.
Bind an event listener for the trigger in question.
Whenever the event in step 3 is fired, use if (top === window) to determine whether the we're inside the top window.
If yes, we're done.
If not, use parent.postMessage({currentTotal: ... }, '*'); to pass data to the parent frame. The message event listener from step two should detect this event, process it, and repeat step three.
I've explained how to approach the problem. One more useful code snippet: You need to identify the source frame. To achieve that, we use the contentWindow property of an <iframe> object for comparison with the source property of the event object:
window.addEventListener('message', function(event) {
if (top === window) {
// do something with e.data
} else {
var iframes = document.getElementsByTagName('iframe');
for (var i=0; i<iframes.length; i++) {
if (iframes[i].contentWindow === event.source) {
// Found frame; measure offset, and pass data to parent frame
var data = e.data;
e.data += iframes[i].getBoundingClientRect().top; // example
parent.postMessage({currentTotal: data}, '*');
break;
}
}
}
});
With these hints you should be able to write the full code yourself. To measure offsets, use the getBoundingClientRect method. For completeness, I also include links to other relevant documentation: window.postMessage, Content scripts (manifest).

HTML5 geolocation: logic to get initial position as well as watchLocation?

I'm using HTML geolocation and I'd like to achieve the following:
1. User arrives at page
2. User is asked to share location
3. When user says yes, Google Maps initialises and centres on their position
4. We add marker to map showing their position
5. (ongoing) As the user moves, the marker continues to move with them
I've implemented this as follows:
// Add a marker
function addMarker(loc) { // adds marker }
function setupMap(loc) { // initialise map and centre on user's position };
setUpMap(???????);
// Start watching user's position
var watchID = navigator.geolocation.watchPosition(addMarker);
So my question is: how can I get the initial position in order to set up the map?
I can see two options, both of which have flaws:
Call setUpMap from within addMarker, but then the map gets re-initialised each time the user moves, which is obviously inefficient.
Call navigator.geolocation.getCurrentPosition before calling watchLocation - but then the user seems to get prompted twice for their location, which looks clunky.
Any better ideas?
Thanks everyone.
UPDATE
OK, it seems I haven't explained this well. My question is really: how do I get the user's location from watchPosition, as a one-off, so that I can initialise the map once?
Call this:
navigator.geolocation.watchPosition
instead of this:
navigator.geolocation.getCurrentPosition
watchPosition function also initializes positions.
3. Call watchLocation in step two, i.e. to get initial location (the user therefore will only get prompted once)

How do I access the popup page DOM from bg page in Chrome extension?

In Google Chrome's extension developer section, it says
The HTML pages inside an extension
have complete access to each other's
DOMs, and they can invoke functions on
each other. ... The popup's contents
are a web page defined by an HTML file
(popup.html). The popup doesn't need
to duplicate code that's in the
background page (background.html)
because the popup can invoke functions
on the background page
I've loaded and tested jQuery, and can access DOM elements in background.html with jQuery, but I cannot figure out how to get access to DOM elements in popup.html from background.html.
can you discuss why you would want to do that? A background page is a page that lives forever for the life time of your extension. While the popup page only lives when you click on the popup.
In my opinion, it should be refactored the other way around, your popup should request something from the background page. You just do this in the popup to access the background page:
chrome.extension.getBackgroundPage()
But if you insist, you can use simple communication with extension pages with sendRequest() and onRequest. Perhaps you can use chrome.extension.getViews
I understand why you want to do this as I have run into the problem myself.
The easiest thing I could think of was using Google's method of a callback - the sendRequest and onRequest methods work as well, but I find them to be clunky and less straightforward.
Popup.js
chrome.extension.getBackgroundPage().doMethod(function(params)
{
// Work with modified params
// Use local variables
});
Background.html
function doMethod(callback)
{
if(callback)
{
// Create/modify params if needed
var params;
// Invoke the callback
callback(params);
}
}
As other answers mention, you can call background.js functions from popup.js like so:
var _background = chrome.extension.getBackgroundPage();
_background.backgroundJsFunction();
But to access popup.js or popup.html from background.js, you're supposed to use the messages architecture like so:
// in background.js
chrome.runtime.sendMessage( { property: value } );
// in popup.js
chrome.runtime.onMessage.addListener(handleBackgroundMessages);
function handleBackgroundMessages(message)
{
if (message.property === value)
// do stuff
}
However, it seems that you can synchronously access popup.js from background.js, just like you can synchronously access the other way around. chrome.extension.getViews can get you the popup window object, and you can use that to call functions, access variables, and access the DOM.
var _popup = chrome.extension.getViews( { type: 'popup' } )[0];
_popup.popupJsFunction();
_popup.document.getElementById('element');
_popup.document.title = 'poop'
Note that getViews() will return [] if the popup is not open, so you have to handle that.
I'm not sure why no one else mentioned this. Perhaps there's some pitfalls or bad practices to this that I've overlooked? But in my limited testing in my own extension, it seems to work.