Přejít k navigační liště

Zdroják » JavaScript » Příkazy pro Ubiquity používající argumenty

Příkazy pro Ubiquity používající argumenty

Ubiquity je revoluční rozšíření Firefoxu. Vytvářet pro něj jednoduché příkazy byste již z minulých dílů měli umět. V tomto dílu se naučíte vytvářet příkazy, které používají argumenty. Naučíte se také používat v příkazech TinyURL a posílat zprávy na Twitter.

Tento článek je překladem anglického originálu na Mozilla Wiki. Autory původního textu jsou: Aza Raskin, Blair McBride, Abimanyu Raja, Jono DiCarlo a Atul Varma.

V minulých dílech jste se naučili vytvářet jednoduché příkazy a přidávat k nim metadata. Dnes navážeme již třetím dílem. Budeme vytvářet příkazy používající argumenty.

Příkazy s argumenty

Echo

Blížíme se k tvorbě zábavných a užitečných příkazů, ale začněme tvorbou velmi jednoduchého příkazu, který zopakuje vše, co mu napíšeme:

CmdUtils.CreateCommand({
  name: "echo",
  takes: {"your shout": noun_arb_text},
  preview: function( pblock, theShout ) {
    pblock.innerHTML = "Vypíše: " + theShout.text;
  },
  execute: function( theShout ) {
    var msg = theShout.text + "... " + theShout.text + "......";
    displayMessage( msg );
  }
}) 

Příkaz „echo“ používá jeden argument obsahující jakýkoliv text (noun_arb_text, arbitray = jakýkoliv). Ať uživatel zadá jakýkoliv text, bude ze vstupu načten, vložen do objektu se vstupem a předán funkcím preview a execute.

Ubiquity se postará o načtení a parsování uživatelova vstupu, nemusíte se proto zatěžovat žádnými substitucemi. Zkuste si vybrat na stránce nějaký text a spustit „echo this“. Ubiquity jako argument použije vybraný text.

Co je Ubiquity?

Ubiquity je experimentální rozšíření prohlížeče Firefox přidávající rozhraní, jaké webové prohlížeče dosud neměly, totiž příkazovou řádku. Jedná se o nový koncept vznikající v rámci projektů Mozilla Labs. Zatímco koncept příkazů je poměrně jasný, uživatelské rozhraní je velkým experimentem a nikdo, ani Mozilla Labs, v tuto chvíli neví, kam až tento experiment zajde. Je možné, že se jedná o slepou uličku, ale možná se jedná o opravdovou revoluci.

O Ubiquity se více dočtete v článku Ubiquity – největší revoluce prohlížečů od dob Greasemonkey.

TIP: Ubiquity si můžete rozšířit o další příkazy, včetně příkazů pro české weby jako je IDOS.

Objekt se vstupem

Objekt s uživatelským vstupem, který obdrží funkce execute a preview, obsahuje následující atributy:

  inputObject.text  // řetězec obsahující vstup jako čistý text bez formátování
  inputObject.html  // řetězec obsahující vstup v podobě formátovaného HTML včetně značek
  inputObject.data  // pro netextová vstupní data, libovolný objekt
  inputObject.summary // pro velmi dlouhé vstupy, obsahuje zkrácený řetězec pro zobrazení 

Náš příklad pracoval pouze s vlastností .text, protože požadoval prostý text. V mnoha případech, kdy uživatel zadá krátký jenoduchý text, budou mít atributy .text, .html a .summary stejnou hodnotu a .data bude null. Většina příkazů, které vytvoříte, budou používat pouze atribut .text. Nicméně máte k dispozici i zbylé atributy.

Představení datových typů

Všimněte si, že typ očekávaného argumentu jsme specifikovali pomocí objektu, v tomto případě předdefinovaného objektu noun_arb_text, který prohlašuje jakýkoliv vstupní text za validní argument. Pokud bychom chtěli vstup našeho příkazu více omezit, použili bychom specifičtější typ objektu („noun_type*“ objektu), např: noun_type_date, který akceptuje pouze platné datum (např. pro příkaz „check-calendar“) nebo noun_type_lan­guage, který akceptuje pouze názvy jazyků (např. pro volby příkazu „translate“).

Výhoda použití omezujících datových typů spočívá v tom, že Ubiquity parser dokáže uživateli lépe napovídat při zadávání vstupu. Když bude mít uživatel vybrané datum, tak příkazy, které pracují s datem, budou ve výběru upřednostněny a zobrazí se jako první v pořadí.

Existuje celá řada datových typů, které by příkazy mohly teoreticky používat např.: lidé, místa, panely prohlížeče atd. Řada z nich dosud nebyla implementována. Jedná se o oblast, ve které můžete být vývoji Ubiquity nápomocni. Datové typy dokáží zlepšit použitelnost s minimálním množstvím kódu. A mohou být použity napříč řadou příkazů.

Pokud již umíte psát příkazy pro Ubiquity, můžete se podívat do souboru nountypes.js, který obsahuje implementaci většiny datových typů. Zjistíte, které všechny datové typy jsou aktuálně dostupné, které dosud nebyly vytvořeny, a které chtějí vylepšit. I vy nám s nimi můžete pomoct.

Vkládání emailu: příkazy s argumenty se specifikovaným ty­pem

Podívejme se na typ noun_type_contact, který na vstupu očekává osobu (buď její jméno nebo e-mailovou adresu). Pokud použijete tento typ, Ubiquity může doplňovat známé kontakty uživateli během psaní. Tímto způsobem funguje příkaz „email“.

Aktuálně Ubiquity zjišťuje seznam lidí, které znáte, čtením kontaktů vašeho účtu na Gmailu. V prototypu našeho příkazu budeme používat Gmail a uživatel musí být do něj přihlášen, aby Ubiquity dokázalo zjistit, s kým se znáte. Rádi bychom časem měli rozhraní i pro další významné webmaily a podobně pro desktopové klienty jak je Thunderbird.

Ale konec otálení, začněme s dalším příkazem. Opakovaně se mi stává, že hledám e-mailovou adresu, kterou si nepamatuji. Následující příkaz mi v tom pomůže, protože obsahuje doplňování e-mailových adres.

CmdUtils.CreateCommand({
  name: "insert-email",
  takes: {"person": noun_type_contact},
  preview: "Vloží emailovou adresu podle zadaného jména.",
  execute: function( email ) {
    CmdUtils.setSelection( email.text );
  }
}) 

Na tomto příkazu můžete vidět, proč mám tak rád Ubiquity. S pouhými 8 řádky kódu jsem schopen výrazně vylepšit chování prohlížeče. Pokud bychom totéž měli dělat pomocí klasického rozšíření Firefoxu, museli bychom vytvořit několik stran kódu a vytvoření uživatelského rozhraní by zabralo mnohem víc práce. Pokud bychom totéž dělali pomocí bookmarkletu, potřebovali bychom i komponentu na serverové straně (abychom obešli omezení AJAXu na jednu doménu) a už ani nemluvím o tom, že bychom museli přimět uživatele ke sdělení hesla.

Ubiquity mnohonásobně zvyšuje prostor pro inovace webových prohlížečů tím, že umožní komukoliv, kdo dokáže napsat jednoduchý JavaScript, vylepšit používání webu.

TinyURL: používáme síť a jQuery

Když píšu e-maily, často vkládám příliš dlouhou URL. Rád bych ji snadno pomocí služby TinyURL zkrátil, ale přímé použití TinyURL je zdlouhavé. I zde Ubiquity pomůže.

Součástí Ubiquity je framework jQuery. Vytvořit AJAXové volání je proto snadné. TinyUrl.com nabízí jednoduché REST API, kterému pokud zašlete URL, vrátí její zkrácenou verzi. V následujícím příkazu toto API použijeme.

CmdUtils.CreateCommand({
  name: "tinyurl",
  takes: {"url to shorten": noun_arb_text},
  preview: "Zkrátí URL pomocí TinyUrl.",
  execute: function( urlToShorten ) {
    var baseUrl = "http://tinyurl.com/api-create.php";
    var params = {url: urlToShorten.text};
    jQuery.get( baseUrl, params, function( tinyUrl ) {
      CmdUtils.setSelection( tinyUrl );
    })
  }
}) 

Použil jsem typ noun_arb_text, ale mohl bych použít typ noun_type_url, pokud by tedy takový typ existoval. Zatím ještě neexistuje.

jQuery je silný nástroj. Můžete s ním jednoduše vzít data z RSS, XML a dalších formátů. Můžeme jej použít i k animacím během náhledu příkazu.

Barvy: vytváříme nové datové typy

Předpokládejme, že píšete sadu příkazů pro umělce a webdesignery a máte několik příkazů, které pracují s barvami. Chtěli byste, aby některé z těchto příkazů akceptovali v argumentech jen názvy barev. Jelikož názvů barev je omezené množství, můžete si vytvořit váš vlastní datový typ pomocí pole řetězců, např. takto:

noun_type_color = new CmdUtils.NounType( "Color",
  ["red", "orange", "yellow", "green", "blue", "violet", "black", "white",
   "grey", "brown", "beige", "magenta", "cerulean", "puce"] // atd.
  ); 

Všimněte si, že vytváříme novému objektu název začínající na „ noun_“. Ubiquity automaticky načte všechny objekty začínající na „ noun_“ mezi uživatelské datové typy.

Jakmile jste definovali vlastní datový typ, můžete jej používat v kolika příkazech chcete, např.:

CmdUtils.CreateCommand({
  name: "get-color-code",
  takes: {"color": noun_type_color},
  preview: "Vloží hexadecimální kód dané barvy.",
  // etc... 

Jednou z výhod vytvoření takového datového typu je, když uživatel zadá např. „get-color bl“, Ubiquity bude schopno nabídnout „black“ a „blue“ jako dva možné dokončení vstupu.

Ne každý datový typ budete chtít vytvořit pomocí výčtu všech hodnot. Pokud chcete vybírat hodnoty na základě algoritmu, můžete tak učinit vytvořením vašeho vlastního typu namísto vytváření instance CmdUtils.NounType. Příklad takového použití si ukážeme příště.

Nahrazování: příkazy s více argumenty

Příkazy mohou mít i více argumentů (někdy volitelných), např. příkaz translate. Ubiquity se postará o jejich správné rozpoznání, proto se nemusíte zabývat tím, v jakém pořadí je uživatel zapsal, obdržíte slovník s požadovanými hodnotami.

Abychom si to ukázali, vytvořme si jednoduchý příkaz „replace“ postavený na regulárních výrazech. Obdrží tři argumenty: předpis pro náhradu, nahrazovaný text a text, ve kterém se má náhrada provést. Zde je zmíněný příkaz:

CmdUtils.CreateCommand({
  name: "replace",
  takes: {"what": noun_arb_text},
  modifiers: {"with": noun_arb_text, "in": noun_arb_text},

  preview: function( pblock, what, mods ) {
    // argumenty obsahují .with a .in, obojí jsou input objekty.
    var msg = 'Nahradí "${whatText}" za ${withText} uvnitř ${inText}.';
    var subs = {whatText: what.text, withText: mods["with"].text, inText: mods["in"].text};

    pblock.innerHTML = CmdUtils.renderTemplate( msg, subs );
  },

  execute: function( what, mods ) {
    // Pokud není text, ve kterém se má náhrada provést, určen, použije se aktuální výběr.
    var text = mods["in"].text || CmdUtils.getSelection();
    var newText = text.replace( what.text, mods["with"].text, "i");
    CmdUtils.setSelection( newText );
  }
}); 

Argument mods (modifiers) obsahuje slovník, ve kterém je klíčem název argumentu a hodnotou je datový typ argumentu. V dalších verzích nabídneme více možností, např. možnost určit argument jako volitelný apod.

Z kódu příkazu translate se můžete naučit víc o modifikátorech a datovém typu noun_type_lan­guage.

Twitter: použijte, co už umíte

Nyní toho umíte dost, abyste mohli vytvořit jednoduchý příkaz, který vám dovolí psát na Twitter z Ubiquity. Autorem příkazu je Blair McBride, kterému děkujeme.Příkaz je plně funkční: prohlížeč obslouží zvláštní případy, např. pokud nejste přihlášeni.

// doporučuje se maximálně 140 znaků, ale ve skutečno je povoleno 160
const TWITTER_STATUS_MAXLEN = 160;

CmdUtils.CreateCommand({
  name: "twitter",
  takes: {status: noun_arb_text},

  homepage: "http://theunfocused.net/moz/ubiquity/verbs/",
  author: {name: "Blair McBride", homepage: "http://theunfocused.net/"},
  license: "MPL",

  preview: function(previewBlock, statusText) {
    var previewTemplate = "Updates your Twitter status to: <br/>" +
                          "<b>${status}</b><br /><br />" +
                          "Characters remaining: <b>${chars}</b>";
    var truncateTemplate = "<br />The last <b>${truncate}</b> " +
                           "characters will be truncated!";
    var previewData = {
      status: statusText.text,
      chars: TWITTER_STATUS_MAXLEN - statusText.text.length
    };

    var previewHTML = CmdUtils.renderTemplate(previewTemplate,
                                                    previewData);

    if(previewData.chars < 0) {
      var truncateData = {
        truncate: 0 - previewData.chars
      };

      previewHTML += CmdUtils.renderTemplate(truncateTemplate,
                                                   truncateData);
    }

    previewBlock.innerHTML = previewHTML;
  },

  execute: function(statusText) {
    if(statusText.text.length < 1) {
      displayMessage("Twitter requires a status to be entered");
      return;
    }

    var updateUrl = "https://twitter.com/statuses/update.json";
    var updateParams = {
      source: "ubiquity",
      status: statusText.text
    };

    jQuery.ajax({
      type: "POST",
      url: updateUrl,
      data: updateParams,
      dataType: "json",
      error: function() {
        displayMessage("Twitter error - status not updated");
      },
      success: function() {
        displayMessage("Twitter status updated");
      }
    });
  }
}); 

Pokračování příště

Seriál ještě nekončí. Příště se naučíte vytvářet příkazy, které umí pracovat s panely prohlížeče a mnohem víc.

Článek, který jste právě dočetli, je překladem anglického originálu a je zde publikován s laskavým svolením Mozilla Corporation.

Komentáře

Subscribe
Upozornit na
guest
11 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
Martin

Zobrazuje se mi to špatně:

CmdUtils.CreateCommand({ name: "hello", execute: function() { displayMessage("Vypíše: Ahoj světe!"); }})

>>> hello
Executes the hello program

Ubiquity Notification
Vy?%u0161e: Ahoj sv%u11Bte!

Mozilla/5.0 (X11; U; Linux i686; cs-CZ; rv:1.9.0.6) Gecko/2009020911 Ubuntu/8.04 (hardy) Firefox/3.0.6 Ubiquity/0.1.5

Martin

Díky. Takdy mě to mohlo napadnout. native2ascii je součástí java runtime, což se mi kvůli tomu nechtělo instalovat. Tak tady je pro případné zájemce skriptík, který dělá to samé. Stačí uložit do /usr/local/bin/nat2ascii

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Usage: nat2ascii Ahoj světe!
import sys
for t in sys.argv[1:]:
    print repr(t.decode(sys.stdin.encoding))[2:-1],
print
Cuba

Ahoj, potreboval jsem rychle whois – na webu mam IP adresy spam stroju a stroju, ktere se pokousely utocit na muj web. Tak jsem si napsal kratke rychle ubiq:

CmdUtils.CreateCommand({
name: "who",
preview: "Displays a <i>WHO-IS</i> lookup.",
execute: function() {
var ip = new String();
var server = "http://whois.smartweb.cz/en/object/";
var url = new String();
ip = CmdUtils.getSelection();
url = server + ip;
displayMessage( "Whois " + url +" via smartweb.cz" );
Utils.openUrlInBrowser(url);
}
})

oznacim IP adresu, vyvolam Ubiquity (Ctrl-Enter) a napisu "who" Enter ;-)

Cuba

Jen nevim, jak donutit Ubiq, aby prikaz who byl k dispozici pravym tlacitkem mysi. tj.:
1) oznacim IP adresu
2) kliknu pravym tl. -> Ubiquity -> who

to nevim jak udelat :(

Cuba

Aha to bylo slozity ;-)

CmdUtils.CreateCommand({
name: „who“,
preview: „Displays a WHO-IS lookup.“,
takes: {„IP to resolve“: noun_arb_text},
execute: function() {
var ip = new String();
var server = „http://whois.smartweb.cz/en/object/“;
var url = new String();
ip = CmdUtils.getSelection();
url = server + ip;
displayMessage( „Whois “ + url +“ via smartweb.cz“ );
Utils.openUrlInBrowser(url);
}
})

:-)

Cuba

sorry, smazte to nekdo ;-) Pravy tl. funguje (to jsem chtel) , ale zadavani z cmd ne. Sorry, opravim to pozdeji…

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.