Join MDN and developers like you at Mozilla's View Source conference, 12-14 September in Berlin, Germany. Learn more at https://viewsourceconf.org

Polecenia

Polecenia to rodzaj operacji, która może być przywoływana.

Elementy polecenia

Element command jest stosowany w celu stworzenia poleceń, które będą służyły przeprowadzaniu operacji. Nie potrzebujemy używać poleceń, od kiedy można je zastąpić wywołaniem skryptu obsługującego pewne zdarzenia. Jednak, polecenia posiadają pewną przewagę. Mowa tu o ich zdolności do automatycznej dezaktywacji, kiedy zajdzie taka potrzeba oraz mogą być wywoływane zewnętrznie bez znajomości szczegółów implementacji samego polecenia. Zapewniają one możliwość stworzenia pewnego abstraktu oddzielającego operacje od samego kodu. Polecenia są przydatne szczególnie w większych aplikacjach. Przykładem jest implementacja poleceń menu związanych ze schowkiem, takich jak; <tt>wytnij</tt>, <tt>kopiuj</tt>, <tt>wklej</tt>. Jeśli nie korzystaliśmy z poleceń, będziemy potrzebowali określić, które pola posiadają skupienie, a następnie upewnić się, że operacja jest odpowiednia dla danego elementu. Dodatkowo, polecenia menu, potrzebują opcji aktywacji oraz dezaktywacji w zależności od tego czy element posiadający skupienie, zawiera zaznaczony teksy, czy też nie. Również do operacji wklejenia, w zależności, czy w schowku znajduje się odpowiednia do wklejenia zawartość. Jak można zauważyć, zaczyna się to komplikować. Wykorzystanie poleceń oszczędza w tym przypadku wiele pracy.

Można używać poleceń dla każdej operacji. Mozilla wykorzystuje je do niemal każdego polecenia menu. Dodatkowo, pola tekstowe oraz inne elementy posiadają pewną liczbę wspierających je i gotowych do wywołania poleceń. Powinno się je używać w przypadku operacji zależnych od tego, na którym elemencie występuje skupienie.

Polecenie jest identyfikowane poprzez jej atrybut id. Mozilla używa konwencji, w której jej id rozpoczyna się przedrostkiem '<tt>cmd_</tt>'. W celu zapobiegnięcia konfliktom w nazwach poleceń, można umieszczać nazwę aplikacji w wewnątrz id polecenia. Przykład poniżej:

Przykład: Proste polecenie command

Przykład 1 : Źródła Podgląd

<command id="cmd_openhelp" oncommand="alert('Pomoc!');"/>
<button label="Pomoc" command="cmd_openhelp"/>

W tym przykładzie, zamiast umieszczania atrybutu oncommand w elemencie button, wstawiamy element command. Są one połączone za pomocą atrybutu command, który posiada wartość id polecenia. W rezultacie w chwili wciśnięcia przycisku, polecenie zostaje wywoływane.

Istnieją dwie zalety używania tego podejścia:

  • Pierwsza, to przesunięcie wszystkich naszych operacji do poleceń, które mogą być pogrupowane razem w sekcje w plikach XUL. Znaczy to, że ów kod, jest skupiony w jednym miejscu, nie natomiast rozproszony po kodzie całego interfejsu użytkownika,
  • Inną zaletą jest fakt, że kilka przycisków i innych elementów UI (interfejs użytkownika), może być "podpiętych" do tego samego polecenia. Przykładowo, możemy posiadać pewną pozycję menu, przycisk paska narzędzi i skrót klawiaturowy podłączony do tego samego polecenia. Dużo wygodniejszym rozwiązaniem, niż powtarzanie tego samego kodu dla każdego z tych trzech elementów, jest wspomniane "podpięcie" ich pod to samo polecenie. Zazwyczaj, podłączane są tylko elementy, które wysyłają zdarzenie polecenia.

Dodatkowo:

  • Jeśli ustalimy także atrybut disabled dla polecenia, będzie ono dezaktywowane i nie będzie możliwości jego wywołania,
  • Każdy przycisk oraz pozycja menu "podpięte" do niego, będą również automatycznie dezaktywowane,
  • Jeśli ponownie aktywujesz polecenie to przyciski i inne elementy ponownie staną się aktywne.

Przykład: Przełączenie wyłączenia command

Przykład 2 : Źródła Podgląd

<command id="cmd_openhelp" oncommand="alert('Pomoc');"/>
<button label="Pomoc" command="cmd_openhelp"/>
<button label="Więcej pomocy" command="cmd_openhelp"/>

<button label="Wyłącz"
        oncommand="document.getElementById('cmd_openhelp').setAttribute('disabled','true');"/>
<button label="Włącz"
        oncommand="document.getElementById('cmd_openhelp').removeAttribute('disabled');"/>

W tym przykładzie oba przyciski używają tego samego polecenia. Kiedy przycisk "Wyłącz" zostanie naciśnięty, polecenie zostaje dezaktywowane poprzez ustalenie jego atrybutu disabled. W tym przypadku oba przyciski zostaną dezaktywowane.

Szeroko stosowanym zabiegiem jest grupowanie poleceń w elementy o nazwie commandset. Znajdują się one zazwyczaj na początku pliku XUL. Przykład poniżej:

<commandset>
  <command id="cmd_open" oncommand="alert('Otwórz!');"/>
  <command id="cmd_help" oncommand="alert('Pomoc!');"/>
</commandset>

Polecenie jest wywoływane, kiedy użytkownik aktywuje (włączy) przycisk lub inny element połączony z tą metodą. Możemy, także wywoływać polecenia poprzez zastosowanie metody doCommand dla samego elementu command lub dla elementu, który jest bezpośrednio połączony z tym poleceniem, takiego jak np. przycisk.

Dyspozytor poleceń

Możemy także używać poleceń bez korzystania z elementów command lub przynajmniej, bez dodawania atrybutu oncommand dla danego polecenia. W tym przypadku, polecenie nie będzie wywoływało bezpośrednio skryptu, ale w zamian, będzie wyszukiwało element lub funkcję, która obsłuży polecenie. Funkcja ta może być oddzielona od języka XUL oraz może być obsługiwane wewnętrznie. W celu znalezienia czegoś do obsługi poleceń, XUL używa obiektu o nazwie dyspozytor poleceń ( ang. command dispatcher ). Obiekt ten lokalizuje obsługę dla poleceń. Polecenie obsługiwane jest przez tzw. kontroler ( ang. controller ). Tak więc, kiedy wywoływane jest polecenie, dyspozytor poleceń lokalizuje kontroler, który obsłuży dane polecenie. Możemy wyobrazić sobie element command, jako pewien typ kontrolera dla polecenia.

Dyspozytor poleceń lokalizuje kontroler, przeszukując element posiadający aktualnie skupienie, pod kątem wspomnianego kontrolera, który jest w stanie obsłużyć zadane polecenie. Elementy XUL posiadają własność controllers, która służy do ich sprawdzania. Możemy wykorzystać własność controllers w celu dodania własnych kontrolerów. Przykładowo, możemy wykorzystać to w celu obsługi odpowiedzi pola list na polecenia <tt>wytnij</tt>, <tt>kopiuj</tt> i <tt>wklej</tt>. W dalszej części artykułu będziemy analizować przykład obrazujący powyższą czynność. Domyślnie, tylko pola tekstowe posiadają robiący to wszystko kontroler. Obsługuje on operacje schowka, selekcji, cofania, przywracania oraz pewne operacje edycji. Warto zauważyć, że element może także posiadać wiele kontrolerów, które będą sprawdzane.

Jeśli element posiadający aktualnie skupienie nie posiada odpowiedniego kontrolera, okno jest sprawdzane w następnej kolejności. Okno także posiada własność controllers, którą możemy modyfikować wedle uznania. Jeśli skupienie znajduje się wewnątrz ramki, każda z nich prowadzi do okna znajdującego się na wyższym poziomie, które także jest sprawdzane. Oznacza to, że polecenia będą działać nawet, jeśli skupienie znajduje się wewnątrz ramki. Powyższa teza jest również prawdziwa dla przeglądarki, ze względu na mówiący o tym, że polecenia edycji wywoływane z głównego menu, będą działać wewnątrz obszaru z zawartością. Warto zaznaczyć, że HTML także posiada system poleceń i kontrolerów, chociaż nie można go wykorzystywać na nieuprzywilejowanych stronach, ale można użyć dla np. rozszerzeń przeglądarki. Jeśli okno nie zapewnia kontrolera zdolnego do obsługi poleceń, nic się nie stanie.

Możemy także sprawić, aby dyspozytor poleceń, używał własności dokumentu o nazwie commandDispatcher. Jesteśmy również w stanie go odzyskiwać z listy kontrolerów dla elementu lub okna. Dyspozytor poleceń zawiera metody służące pobieraniu kontrolerów dla poleceń oraz służące pobieraniu oraz modyfikacji skupienia.

Dodawanie kontrolerów

Możemy również zaimplementować własne kontrolery odpowiadające na polecenia. Możemy nawet zmienić domyślną obsługę polecenia, poprzez umiejętne umieszczenie kontrolera. Kontroler powinien implementować cztery metody, przedstawione poniżej:

supportsCommand (command) 
Ta metoda powinna zwracać wartość true, jeśli kontroler wspiera polecenie. Jeśli natomiast zwraca false, znaczy to, że polecenie nie jest obsługiwane i dyspozytor poleceń będzie szukał innego kontrolera. Pojedynczy kontroler może wspierać wiele poleceń.
isCommandEnabled (command) 
Ta metoda powinna zwracać wartość true, kiedy polecenie jest aktywne lub false w przeciwnym przypadku. Korespondujące przyciski będą dezaktywowane automatycznie.
doCommand (command) 
Uruchamia polecenia. W tym miejscu umieszczamy kod obsługujący polecenie.
onEvent (event) 
Ta metoda obsługuje zdarzenia.

Przykład: Implementacja kontrolera

Przyjmijmy, że chcemy zaimplementować pole listy, które będzie obsługiwało polecenie <tt>usuń</tt>. Kiedy użytkownik wybierze <tt>usuń</tt> z menu, pole listy skasuje zaznaczony wiersz. W tym przypadku, wystarczy tylko dołączyć kontroler do pola wyboru, który wykona metoda doCommand.

Spróbujmy otworzyć poniższy przykład (Źródła Podgląd) w oknie przeglądarki i wybrać pewne elementy z listy. Zauważmy, że polecenie Usuń w menu Edycja przeglądarki jest aktywne i jej wybór usunie wiersz.

<window id="controller-example" title="Przykład kontrolera" onload="init();"
        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

<script>
function init()
{
  var list = document.getElementById("theList");

  var listController = {
    supportsCommand : function(cmd){ return (cmd == "cmd_delete"); },
    isCommandEnabled : function(cmd){
      if (cmd == "cmd_delete") return (list.selectedItem != null);
      return false;
    },
    doCommand : function(cmd){
      list.removeItemAt(list.selectedIndex);
    },
    onEvent : function(evt){ }
  };

  list.controllers.appendController(listController);
}
</script>

<listbox id="theList">
  <listitem label="Ocean"/>
  <listitem label="Desert"/>
  <listitem label="Jungle"/>
  <listitem label="Swamp"/>
</listbox>

</window>

Kontroler (listControler) implementuje cztery metody opisane wyżej. Metoda supportsCommand zwraca true dla polecenia cmd_delete, które jest zastosowane w chwili wyboru opcji <tt>Usuń</tt> z menu. Dla innych poleceń, zwracany jest false. Dzieje się tak dlatego, że kontrolery nie obsługują żadnego innego polecenia.

Metoda isCommandEnabled zwraca wartość true, kiedy polecenie powinno być aktywne. W tym przypadku sprawdzamy czy w polu listy istnieje zaznaczony element i jeśli istnieje zwraca wartość true. W przeciwnym przypadku zwraca false. Jeśli usuniemy wszystkie wiersze, opcja <tt>Usuń</tt> stanie się nieaktywna. W naszym prostym przykładzie może zajść możliwość kliknięcia na polu listy w celu jego uaktualnienia. Metoda doCommand będzie wywoływana, w chwili wyboru opcji <tt>Usuń</tt> z menu. Spowoduje to, że zaznaczony wiersz pola listy zostanie usunięty. Natomiast metoda onEvent nie musi powodować żadnych efektów, więc nie dodajemy do niej żadnego kodu.

Przesłanianie domyślnego kontrolera

Dodajmy ten kontroler do pola listy, poprzez wywołanie metody appendController dla controllers pola listy. Obiekt kontrolera posiada pewną liczbę metod, które mogą być używane do manipulowania kontrolerami. Przykładowo, istnieje także metoda insertControllerAt, która "wkłada" kontroler do elementu przed inne kontrolery. Może to być użyteczne w celu utworzenia komendy nadrzędnej. Poniższy przykład wyłącza opcję wklejenia dla danego pola tekstowego.

var tboxController = {
  supportsCommand : function(cmd){ return (cmd == "cmd_paste"); },
  isCommandEnabled : function(cmd){ return false; },
  doCommand : function(cmd){ },
  onEvent : function(evt){ }
};

document.getElementById("tbox").controllers.insertControllerAt(0,tboxController);

W tym przykładzie, wkładamy kontroler ma pozycję o numerze 0, co oznacza, że będzie on się znajdował przed wszystkimi innymi. Nowy kontroler wspiera polecenie 'cmd_paste' i zawsze wskazuje, że polecenie jest wyłączone, dezaktywowane. Domyślny kontroler pola tekstowego, nigdy nie zostanie wywołany ponieważ, dyspozytor poleceń znajdzie w pierwszej kolejności inny kontroler do obsługi, znajdujący się wyżej.

Następnie, dowiemy się jak aktualizować polecenia.

Autorzy i etykiety dokumentu

Etykiety: 
 Autorzy tej strony: fscholz, teoli, Mgjbot, Ptak82, Sadek
 Ostatnia aktualizacja: fscholz,