Přidat článek mezi oblíbenéZasílat nové komentáře e-mailem Naučte HTML novým trikům

Registrovaný Pavel Stříbrný rádce, , Internet, 13 komentářů (12488 zobrazení)

V tomto článku se naučíme jak upravit HTML tag přesně podle našich požadavků. Vysvětlení provedu na příkladu vypsání binární hodnoty (0 – 255, byte) po jednotlivých bitech v řádku tabulky. Cílem je upravit tag <tr></tr> přidáním nového atributu tr-byte tak, aby dokázal vytvořit kompletní řádek tabulky <tr><td></td>…</tr> s osmi buňkami včetně hodnot v jednotlivých buňkách tabulky. Použijeme ho např. takhle: <tr tr-byte value=“27“></tr>

HTML, tag, atribut

Jazyk HTML prošel vývojem od svých počátků až po současnou verzi HTML5. Popisuje webovou stránku pomocí značek, tzv. tagů. Tagy mohou obsahovat atributy, které zpřesňují či doplňují jejich význam.

Angular

AngularJS je javascriptová knihovna, která implementuje MVC architekturu. Pomocí Angularu lze snadno programovat webové či mobilní aplikace, viz můj článek Naprogramujte si vlastní android aplikaci (bez znalosti Javy)

Upravený HTML tag <tr></tr>

V terminologii Angularu tvoříme direktivu, v terminologii HTML tvoříme nový atribut. Kód budeme psát do dvou souborů: index.html (sem přijde HTML kód, tj. tagy) a app.js (sem přijde práce s Angularem a definice vlastní directivy).

A) soubor app.js

1) Definujeme proměnnou a modul

var app = angular.module('app', []);

2) Definujeme direktivu "trByte" (v HTML se bude jako atribut zapisovat v tagu <tr tr-byte></tr>

app.directive('trByte', function(){
    return {
      restrict: "A",
      replace: true,
      scope: {
          value: "="
      },
      template: "<tr><td>{{Byte[7]}}</td><td>{{Byte[6]}}</td><td>{ {Byte[5]}}</td><td>{{Byte[4]}}</td><td>{{Byte[3]}} </td><td>{{Byte[2]}}</td><td>{{Byte[1]}}</td><td>{ {Byte[0]}}</td></tr>",
      controller: function($scope){
        var Byte = [];
        if (!($scope.value === parseInt($scope.value)) || ($scope.value < 0) || ($scope.value > 255) ) {$scope.Byte = ["-", "-", "-", "-", "-", "-", "-", "-"]; return;};
        
        for (var i = 7; i>-1; i--) {if ($scope.value >= Math.pow(2, i)) {Byte[i] = 1; $scope.value = $scope.value - Math.pow(2, i);} else {Byte[i] = 0;};};
        $scope.Byte = Byte;
        }
    };
});

3) A to je v souboru app.js všechno.Kdo nepotřebuje popis, jak to celé funguje, může pokračovat na bod B)

Na řádku 1 definujeme direktivu s názvem "trByte", přičemž v HTML kódu ji použijeme jako atribut <tr tr-byte></tr>
Na řádku 2 až 7 vracíme objekt, jehož vlastnost restrict říká, že direktiva se definuje jako atribut tagu (A = atribut). Vlastnost replace říká, že se direktiva nahradí HTML kódem z vlastnosti template.
Na řádku 5 až 7 určujeme, že použijeme další atribut value; tj. skutečné použití našeho upraveného tagu bude např.: <tr tr-byte value=“27“></t>
Na dalších řádcích je vlastnost template, což je HTML kód, kterým se nahradí náš upravený tag <tr tr-byte></tr>. Je to vlastně řádek tabulky s osmi buňkami. V každé buňce je jeden prvek pole Byte. Jeho hodnotu získáme z controlleru.

Nejprve se zkontroluje, zda atribut value obsahuje celé číslo (1. část podmínky) a zda je toto číslo v rozsahu od 0 do 255 (2. a 3. část podmínky). Pokud to není splněno, do všech prvků pole Byte se zapíše znak mínus ("-").
Je-li v atributu value celé číslo v rozsahu od 0 do 255, pak se do prvků pole zapíše jeho osmibitová binární hodnota – do jednoho prvku pole vždy jeden bit.

Ve vlastnosti template máme osm jednotlivých tagů <td></td>, do kterých zapisujeme prvky pole Byte, např. <td>{{Byte[7]}}</td> - a to je právě prvek pole Byte, jehož hodnota je vypočítána v controlleru.

B) soubor index.html

Nový atribut (direktivu) máme hotovou, teď ji vyzkoušíme na HTML stránce. Aby vše fungovalo, musíme načíst knihovnu AngularJS a náš vlastní soubor app.js (pozor na správný zápis včetně cesty k souboru).

Zapíšeme HTML tabulku, ale místo <tr><td>obsah</td>…</tr> použijeme náš nový atribut <tr tr-byte></tr> společně atributem value, do kterého vložíme hodnotu v rozsahu od 0 do 255.
Věřím, že příklad použití je dostatačně srozumitelný:

<html ng-app="app">
<head>
	<title>Byte v tabulce jako osmibitová hodnota</title>
	<style>
		table {border-width:1px; border-color: #666; border-style: solid; font-size:18px; border-spacing:0; border-collapse:collapse; width: 100%;}
		thead {background-color: white; color: black; font-weight:bold;}
		th {padding:3px; text-align:center; background-color: lightblue;}
		td {padding: 3px; border: 1px #ddd dotted; text-align: center; color: black;}
	</style>
</head>
<body>
	<table>
		<thead>
			<tr><th colspan='8'>Byte</th></tr>
		</thead>
		<tbody>
			<tr><td colspan="8">hodnoty</td></tr>
			<tr tr-byte value='140'></tr>
			<tr tr-byte value='77'></tr>
			<tr tr-byte value=''></tr>
		</tbody>
	</table>

	<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js"></script>
	<script src="js/app.js"></script>
</body>
</html>

Tabulka obsahuje jednořádkovou hlavičku a tělo se čtyřmi řádky, přičemž 2., 3. a 4. řádek používá náš upravený tag s novým atributem (v posledním řádku je záměrně vynechána hodnota atributu value).

Přikládám zdrojové soubory...

Předmět Autor Datum
Pokud se v direktivě používá replace: true, tak se obvykle používá elementová a ne atributová direkt…
Wikan 03.01.2015 13:56
Wikan
Jo, direktiva mohla být typu element a ne atribut, to je pravda. Každopádně je moje řešení funkční.…
Pavel 03.01.2015 14:08
Pavel
var value = $scope.value; for (var i = 7; i > -1; i--) { Byte[i] = value & 1; value = value >> 1; }…
Wikan 03.01.2015 14:29
Wikan
Jo, to vypadá jako rozumný řešení, souhlasím. OK, .toString(2), pak zjstit délku a zleva to doplnit…
Pavel 03.01.2015 14:43
Pavel
Však jen piš dál, já si to vždycky rád přečtu. Jenom doufám, že nejsem sám.
Wikan 03.01.2015 15:21
Wikan
To já taky, i když tedy stíhám jenom něco. :-)
Zarniwúp 03.01.2015 19:36
Zarniwúp
Nejsi... :-)
host 04.01.2015 12:31
host
Tato problematika mě zaujala, testuju zde uvedené záležitosti a výše uvedený kód bez Math.pow() má d…
JoDiK 05.01.2015 09:58
JoDiK
restrict: "E" S tím otočením máš pravdu. V samotném poli je to správně, ale v HTML se to vypisuje o…
Wikan 05.01.2015 10:02
Wikan
restrict: "E" asi nestačí, vyhodí to ty trbyte řádky před tabulku. <table> <thead> <tr><th colspan…
JoDiK 05.01.2015 15:25
JoDiK
Vypisuje to nějakou chybu do konzole?
Wikan 05.01.2015 16:11
Wikan
Tak po chvilce googlení jsem zjstil, že zrovna v nahrazování <tr> je v Angularu bug a asi ho není zr…
Wikan 05.01.2015 19:08
Wikan
http://www.zdrojak.cz/clanky/proc-se-vyhnout-angul aru/?utm_source=feedly&utm_reader=feedly&utm_medi… poslední
MaSo 21.01.2015 08:29
MaSo

Pokud se v direktivě používá replace: true, tak se obvykle používá elementová a ne atributová direktiva, takže:

<tr-byte value="123">

A používat v tomhle případě Math.pow() je dost zbytečné a zpomalující.

Jo, direktiva mohla být typu element a ne atribut, to je pravda. Každopádně je moje řešení funkční.
Jak to teda zařídít bez Math.pow()?

var value = $scope.value;
for (var i = 7; i > -1; i--) {
    Byte[i] = value & 1;
    value = value >> 1;
}

Ale úplně nejjednodušší by bylo trochu si pohrát s tímhle:

Byte = $scope.value.toString(2);

Jo, to vypadá jako rozumný řešení, souhlasím.
OK, .toString(2), pak zjstit délku a zleva to doplnit o chybějící nuly.

No co, pořád se učím :-)

Díky!

Tato problematika mě zaujala, testuju zde uvedené záležitosti a výše uvedený kód bez Math.pow() má drobnou chybu, výsledek je zrcadlově otočený.
Správně má být:

var value = $scope.value;
for (var i = 0; i < 8; i++) {
    Byte[i] = value & 1;
    value = value >> 1;
}

Bohužel netuším, jak to upravit na tu o něco výše uvedenou variantu s

<tr-byte value="123">
restrict: "E"

asi nestačí, vyhodí to ty trbyte řádky před tabulku.

<table>
	<thead>
		<tr><th colspan='9'>Byte</th></tr>
	</thead>
	<tbody>
	<tr><td >zadání</td><td colspan="8">hodnoty</td></tr>
	<tr-byte value='255'></tr-byte>
	<tr-byte value='1'></tr-byte>
	<tr-byte value='8'></tr-byte>
	<tr-byte value='254'></tr-byte>
	<tr-byte value='2424'></tr-byte>
	</tbody>
</table>

Takhle:
[http://pc.poradna.net/file/view/21150-e-gif]

Má to vypadat takhle:
[http://pc.poradna.net/file/view/21149-a-gif]

Tak po chvilce googlení jsem zjstil, že zrovna v nahrazování <tr> je v Angularu bug a asi ho není zrovna snadné obejít. Takže v tomhle případě je jednodušší použit atributovou direktivu.
Atributové a elementové direktivy jsou v zásadě rovnocenné, že se používají různě je spíše konvence, než nutnost.
Elementy: musí se nahrazovat, představují složitější samostatné komponenty s vlastní logikou
Atributy: nemusí (ale mohou) se nahrazovat, nejde většinou o samostatné komponenty, ale slouží k přidání logiky do stávajícího elementu

Zpět na články Přidat komentář k článku