📜 ⬆️ ⬇️

Ubiquity: just another map plug-in

Ubiquity Logo

On Habré already was an article about the wonderful plugin for Firefox - Ubiquity . Very experimental plugin. I advise you to at least look at it.

So, I really liked it and I wrote my extension - address search on maps mapia.ua . What and wrote an article.
')

Preview


What is remarkable about this Ubiquity?

Here is the introductory video from the author of the plugin.

All the action takes place on the command line , right in the browser. Just press Ctrl + Space. As they say, all lovers of POSIX is dedicated. But everything is so simple and clear that the monkey will master: you do not need to enter commands completely (suggestions), you have learned the parameters once or twice. By default, the first argument to the command is what is selected with the mouse on the page. Actually, this is a huge plus, say, when translating articles from German (by pressing Enter, by the way, the selected piece of text is translated directly on the page). Or to throw the text to a friend on the soap. In general, Aza did his best.

Bicycle


In order to create your own miracle service, we will need, in fact, Firefox with Ubiquity installed. There is? Let's get started

Maps, maps, how I miss you


Mapia Logo

Ubiquity already has pre-installed Google Maps. But I, as a resident of the glorious city of Kiev, got used to using others - http://mapia.ua And as an example, it will come down :-)
Yes, especially for those who do not like a lot of books - here is a link to a ready-made plug-in .

To start editing, click "Edit." Thanks, Cap!


So, press Ctrl + Space , type help , go to the Ubiquity settings page, find and click “Hack Ubiquity”. We are in the editor. If it's not very convenient to code in textarea , then you can connect any external editor and work in it (I prefer notepad ++ , for example).

The first steps


CmdUtils.CreateCommand({
names: [ "mapia" , "mpi" ],
icon: "http://mapia.ua/favicon.ico" ,
description: _( "Kiev map powered by mapia.ua" ),
author: {name: "Kottenator" , email: "kottenator@gmail.com" },
license: "MIT"
});


* This source code was highlighted with Source Code Highlighter .

It's all very simple:

And we can already run and see our team:
Ctrl + Space -> type "mapia" or "mpi" -> see this:

Screenshot 1

Direct pride takes for their deeds! :) But let's continue:
CmdUtils.CreateCommand({
names: [ "mapia" , "mpi" ],
icon: "http://mapia.ua/favicon.ico" ,
description: _( "Kiev map powered by mapia.ua" ),
author: {name: "Kottenator" , email: "kottenator@gmail.com" },
license: "MIT" ,

arguments: [
{role: 'object' , nountype: noun_arb_text, label: _( 'address' )}
],

preview: function preview(pblock, args) {
var msg = "You'd just typed \"${text}\"" ;
pblock.innerHTML = _(msg, { text: args. object .text });
},

execute: function execute(args) {
var msg = "You choose address: \"${text}\"" ;
displayMessage(_(msg, { text: args. object .text }));
}
});


* This source code was highlighted with Source Code Highlighter .

What have we done?

Saved, played, beauty:

Screenshot 2

Actually, where are the cards? Let's start with the Mapia Static API - it's just a picture of a map section. We continue our code:
arguments: [
{role: 'object' , nountype: noun_arb_text, label: _( 'address' )},
{role: 'goal' , nountype: noun_arb_text, label: _( 'zoom' )},
{role: 'source' , nountype: noun_arb_text, label: _( 'map size' )}
],

previewDelay: 800,

getStaticURL: function (address, zoom, size) {
var mapUrl = "http://mapia.ua/static?" ;

address = address || '' ;
zoom = parseInt(zoom, 10) || 15;
zoom = Math.min(18, Math.max(zoom, 6));
size = size || '400x300' ;

var params = {
address: address,
zoom: zoom,
size: size
};

return mapUrl + jQuery.param( params );
},

preview: function preview(pblock, args) {
var img = '<img src="${url}" />' ;
var url = this .getStaticURL(args. object .text, args.goal.text, args.source.text);
pblock.innerHTML = _(img, { url: url });
},

* This source code was highlighted with Source Code Highlighter .


Here is the result:

Screenshot 3

Well, that could be the end of it, but I personally wanted to create a really handy thing. Static drawing is not enough for my needs. And that's what I did ...

Second steps


Actually, the preface. Mapia does not provide an open web service to search by street address. But it works on their website! And I thought - after all, there is nothing criminal in that I will use their search through XSS? In the end, this is not a vulnerability, and I don’t do any harm, do not steal anything, but only create additional advertising for these guys ;-)

Add this method:
loadDetails: function (pblock, args, page_num) {
var baseUrl = "http://mapia.ua/search" ;
var params = {city: "%u041A%u0438%u0435%u0432" , "search[query]" : args. object .text};
var self = this ;

jQuery.ajax({
type: "GET" ,
url: baseUrl,
data: params ,
dataType: 'html' ,
error: function () { },
success: function (html) {
$( '#content' , pblock).html(html);
}
});
},

preview: function preview(pblock, args) {
var img = '<img src="${url}" /><div id="content"></div>' ;
var url = this .getStaticURL(args. object .text, args.goal.text, args.source.text);
pblock.innerHTML = _(img, { url: url });

this .loadDetails(pblock, args);
}


* This source code was highlighted with Source Code Highlighter .

As you can see, Ubiquity supports jQuery. This is good!
And here is the same search by mapia - mapia.ua/search?city=Kiev&search [query] = Entered address”
What does the loadDetails(...) method loadDetails(...) ? It simply loads search results into our preview. I think that the code is clear and can not be explained.

Screenshot 4

Before us are the search results. But for some reason we can not go anywhere. Links do not work, everything is bad. In fact, this is normal :) As I said above, this mechanism is not intended for us at all, but only for the site mapia.ua itself. But Ubiquity allows you to do cross-domain requests, which we did.

So you have to work with a file (RegExp pre-fix + jQuery post-fix):
mapiaURL: "http://mapia.ua/#popup_class=${cat}&popup_id=${sid}" ,

clearSearchResultsCode: function (html) {
html = html.replace(/<div id="search_bar_title">((?:.|\s)*?)<\/div>/i, '<h3 class="search_bar_title">$1</h3>')
.replace(/<p>.*?<\/p>/i, '<p><small>( mapia.ua)</small></p>')
.replace(/(<div class="buildings_info")[^>]*>/gi, '$1>')
.replace(/<a href="\/center\/street\/(\d+)[^>]*>/i, '<a href="' + _(this.mapiaURL, {cat: 'Street', sid: "$1"}) + '">')
.replace(/<a[^<>]+onclick="\$\('street_\d+_buildings'\).*?<\/a>/i, '')
.replace(/<a href="\/center\/address\/(\d+)[^>]*>/gi, '<a href="' + _(this.mapiaURL, {cat: 'Address', sid: "$1"}) + '">')
.replace(/<a href="\/center\/feature\/(\d+)[^>]*>/gi, '<a href="' + _(this.mapiaURL, {cat: 'Feature', sid: "$1"}) + '">')
.replace(/<a href="\/center\/station\/(\d+)[^>]*>/gi, '<a href="' + _(this.mapiaURL, {cat: 'Station', sid: "$1"}) + '">')
.replace(/<a href="\/center\/city\/(\d+)[^>]*>/gi, '<a href="' + _(this.mapiaURL, {cat: 'City', sid: "$1"}) + '">')
.replace(/(<div id="search_bar_title"(?:.|\s)*?)<span(?:.|\s)*?<\/span>/i, '$1')
.replace(/(<div id="search_bar_title"(?:.|\s)*?)<span(?:.|\s)*?<\/span>/i, '$1') /* not a duplicate */
.replace(/href="\/search?[^"]*pages_feature=(\d+)[^"]*"/gi, 'page_num="$1"')
.replace(/<p><a[^<>]*onclick="load_content(?:.|\s)*?<\/p>/i, '')
.replace(/<script>(?:.|\s)*?<\/script>/i, '');
return html;
},

loadDetails: function (pblock, args, page_num) {
var baseUrl = "http://mapia.ua/search" ;
var params = {city: "%u041A%u0438%u0435%u0432" , "search[query]" : args. object .text};
if (page_num)
params.pages_feature = page_num;
var self = this ;

jQuery.ajax({
type: "GET" ,
url: baseUrl,
data: params,
dataType: 'html' ,
error: function () {},
success: function (html) {
// Pre-fixes via RegExp
html = self.clearSearchResultsCode(html);

$( '#content' , pblock).html(html);

// After-fixes via jQuery
$( 'div.pagination a' , pblock).click( function (e){
self.loadDetails(pblock, args, $( this ).attr( 'page_num' ));
e.preventDefault();
return false ;
})
}
});
}

* This source code was highlighted with Source Code Highlighter .

It’s a long time to explain how it works :) Let me just say that it clears html from too much and makes the links clickable.

Here’s how it should look:

Screenshot 5

Done!


Well, that's all, the patient is healthy and can be discharged. I am glad that someone has finished reading these lines :)

Here you can download the collected code .

Source: https://habr.com/ru/post/74514/


All Articles