Autor wpisu: batman, dodany: 26.08.2010 08:00, tagi: zend_framework
Jednym z najczęstszych problemów związanych z Zend_Form jest brak możliwości dodawania kodu HTML między elementami formularza. Na szczęście Zend_Form jest na tyle rozbudowany, iż przy odrobinie pomysłowości wspomniany problem można dosyć łatwo obejść. Rozwiązań jest co najmniej kilka. Dzisiaj przedstawię dwa najprostsze.
Pierwszym rozwiązaniem jest zastosowanie opisu (description) w elemencie, po którym chcemy dodać kod HTML.
class Application_Form_Example1 extends Zend_Form
{
public function init()
{
$this->setName('form-example1');
$name = new Zend_Form_Element_Text('name');
$name->setLabel('Nazwa');
$email = new Zend_Form_Element_Text('email');
$email->setLabel('E-mail')
->setDescription('<div id="some-id">lorem ippsum</div>');
$phone = new Zend_Form_Element_Text('phone');
$phone->setLabel('Telefon');
$submit = new Zend_Form_Element_Submit('btn_save');
$submit->setLabel('Zapisz');
$this->addElement($name);
$this->addElement($email);
$this->addElement($phone);
$this->addElement($submit);
}
}
Kluczowym elementem powyższego kodu jest metoda setDescription, wywołana na obiekcie $email. Dzięki niej, do kodu formularza zostanie dodany kod HTML. Niestety kod zostanie wyświetlony w takiej formie, w jakiej został dodany – na stronie wyświetli się tekst
<div id="some-id">lorem ippsum</div>
Dzieje się tak dlatego, ponieważ kod HTML jest zamieniany na encje. Rozwiązaniem tego problemu jest ustawienie opcji escape dekoratora Description na false.
$email->addDecorator('Description', array('escape' => false));
Drugi sposób polega na zastosowaniu ukrytego elementu, w którym kod HTML wyświetlany jest w etykiecie.
class Application_Form_Example2 extends Zend_Form
{
public function init()
{
$this->setName('form-example2');
$name = new Zend_Form_Element_Text('name');
$name->setLabel('Nazwa');
$email = new Zend_Form_Element_Text('email');
$email->setLabel('E-mail');
$html = new Zend_Form_Element_Hidden('html');
$html->setLabel('<div id="some-id">lorem ippsum</div>')
->setIgnore(true)
->addDecorator('Label', array('escape' => false));
$phone = new Zend_Form_Element_Text('phone');
$phone->setLabel('Telefon');
$submit = new Zend_Form_Element_Submit('btn_save');
$submit->setLabel('Zapisz');
$this->addElement($name);
$this->addElement($email);
$this->addElement($html);
$this->addElement($phone);
$this->addElement($submit);
}
}
Podobnie jak w przypadku opisu, etykieta również wymaga ustawienia opcji escape na false. Oczywistym jest, że podczas wysyłania formularza dodatkowe pole jest zbędne. Dzięki użyciu metody setIgnore, nadmiarowy element nie będzie występował w tablicy wartości przesłanych przez formularz. Autor wpisu: sokzzuka, dodany: 25.08.2010 16:04, tagi: php
W niedawnym wpisie na liście php.internals, Pierrick Charron poinformował o stworzeniu patch’a dodającego obsługę adnotacji do php. Patch ten jest napisany zgodnie z odpowiednim RFC. Rozszerza on składnie języka, dodaje obsługę do refleksji i dwie nowe klasy ‘ReflectionAnnotation’ i ‘Inherited’ – pierwsza umożliwia tworzenie własnych adnotacji, natomiast druga umożliwia dziedziczenie adnotacji przez klasy dziedziczące z jakiejś klasy.
Jak dla mnie to ciekawy dodatek do języka, natomiast ja chętnie bym również widział jakąś implementacje Pythonowych dekoratorów o których już wcześniej wspominałem. A wy co o tym sądzicie ?
Autor wpisu: m1chu, dodany: 24.08.2010 22:38, tagi: css, javascript
Sieć została ogarnięta szałem najnowszej, piątej wersji języka HTML. Jak to zazwyczaj bywa słabo z jej obsługą radzi sobie Internet Explorer. We wszystkich wydanych wersjach pojawia się problem z parsowaniem elementów języka HTML 5, a co za tym idzie nie ma domyślnie możliwości ich poprawnego ostylowania. Podobny problem w przeszłości występował w Firefoksie 2.
Zarys problemu
Załóżmy więc, że tworzymy nowy projekt i jesteśmy na etapie dodawania nagłówka oraz stopki dokumentu.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Obsługa HTML 5 z CSS</title>
<style>
body { text-align: center; margin: 0; padding: 0; font-family: Tahoma, Verdana, Arial; font-size: 11px; }
header { font-style: italic; width: 770px; height: 70px; padding: 15px; margin: 5px auto; background-color: #FC0; text-align: left; }
footer { font-weight: bold; clear: both; width: 770px; height: 15px; padding: 15px; margin: 5px auto; background-color: #FC0; text-align: left; }
</style>
</head>
<body>
<header>Nagłówek</header>
<footer>Stopka</footer>
</body>
</html>
Nadaliśmy powyżej kilka atrybutów stylów pozycjonujących elementy oraz nadających im odpowiedni wygląd. Po przetestowaniu w Internet Explorerze i alternatywnych przeglądarkach zobaczymy jednak różne wyniki.
Wynik w Firefoksie 4.
Wynik w Internet Explorerze 8.
Internet Explorer – rozwiązanie pierwsze
Aby pozbyć się tego problemu należy do sekcji head wstawić:
<script>
document.createElement('header');
document.createElement('footer');
</script>
Internet Explorer – rozwiązanie drugie
Dla każdej wersji Internet Explorera można także dodać do dokumentu HTML (w sekcję head) zewnętrzny kod JavaScript, dzięki któremu osiągniemy wyżej opisany skutek.
<!--[if IE lt 9]> <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]-->
Firefox 2
Niespełna jeden procent internautów nadal używa drugiej odsłony popularnego lisa. Zarówno on, jak i wszystkie przeglądarki oparte na silniku Gecko pre 1.9b5 (np. Camino 1.x) posiadają błąd parsowania dzięki któremu w przypadku otwarcia nowego znacznika każdy nieznany, wcześniej otwarty zostanie automatycznie zamknięty.
Autor wpisu: batman, dodany: 24.08.2010 08:00, tagi: javascript
Katalogi raczej nie wymagają wyjaśnienia – są przeznaczone do przechowywania obrazków, skryptów Javascript oraz plików CSS. Z kolei pliki to manifest (gadget.xml), główny dokument gadżetu (Main.html – nazwa definiowana w manifeście) oraz pozostałe dokumenty .W tym przypadku jest to tylko Settings.html, ale nic nie stoi na przeszkodzie, aby tych dokumentów było więcej. W dalszej części dzisiejszego przewodnika dojdzie jeszcze jeden plik – Flyout.html
W przykładach wykorzystałem bibliotekę jQuery, dzięki której wiele czynności zostało uproszczonych, przez co kod jest bardziej czytelny. Nie jest to wymóg. Jeśli nie znacie/nie lubicie jQuery możecie skorzystać z innej biblioteki lub nie korzystać wcale.
Settings
Settings to nic innego jak okno ustawień. Jest ono reprezentowane przez osobny dokukent HTML, w którym powinny znaleźć się elementy formularza (pola tekstowe, checkboxy, radiobuttony itp). Nie ma konieczności stosowania przycisków, ponieważ są one dodawane automatycznie.
Jeśli chcemy wykorzystać okno ustawień wystarczy, że do właściwości settingsUI obiektu System.Gadget przypisana zostanie ścieska wskazująca na plik HTML. Ścieżka może być relatywna lub bezwzględna. Przypisanie powinno nastąpić w głównym dokumencie.
System.Gadget.settingsUI = "/Settings.html";Dodanie powyższego kodu do gadżetu spowoduje pojawienie się ikonki klucza (wyróżniona na czerwono),
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link type="text/css" rel="stylesheet" href="/styles/reset.css" />
<link type="text/css" rel="stylesheet" href="/styles/global.css" />
<script type="text/javascript" src="/scripts/jquery-1.4.2.min.js"></script>
</head>
<body class="settings">
<label>Your name:</label>
<input type="text" name="your-name" id="your-name" />
</body>
</html>Samo dodanie formularza oraz wskazanie go jako okno ustawień na nic się zda, jeśli chcemy przechowywać i odczytywać wprowadzone przez użytkownika dane. Na szzęście mamy do dyspozycji obiekt System.Gadget.Settings, który pozwala na zapisywanie i odczytywanie ustawień. Służą do tego cztery metody, przez ten obiekt udostępnione. Są to:
- write
- writeString
- read
- readString
// przechwycenie zdarzenia zamykania okna ustawień
System.Gadget.onSettingsClosing = SettingsClosing;
// obsługa zdarzenia
function SettingsClosing(event)
{
// czy zamknięcie nastąpiło na skutek kliknięcia w przycisk "OK"
if(event.closeAction == event.Action.commit) {
// zapisanie wprowadzonych danych
System.Gadget.Settings.writeString("name", $("#your-name").val());
}
}Jeśli chcemy od razu po zamknięciu okna ustawień mieć dostęp do danych, musimy obsłużyć kolejne zdarzenie związane z ustawieniami – onSettingsClosed. Przy czym należy pamiętać, że obsługa tego zdarzenia musi – w przeciwieństwie do zdarzenia onSettingsClosing – odbyć się w głównym oknie gadżetu.
// przechwycenie zdarzenia zamknięcia okna ostawień
System.Gadget.onSettingsClosed = SettingsClosed;
// obsługa zdarzenia
function SettingsClosed(event)
{
// odczytanie wprowadzonych danych
var name = System.Gadget.Settings.readString("name");
$("#entered-name").text(name);
}Flyout
Flyout jest specjalnym typem okna, które stosuje się do zaprezentowania dodatkowych informacji. Podobnie jak w przypadku okna ustawień, Flyout ma swój własny dokument HTML.
Flyout jest wyświetlany w momencie ustawienia właściwości show obiektu System.Gadget.Flyout na true, a ukrywany po ustawieniu jej wartości na false.
// wskazanie pliku Flyout
System.Gadget.Flyout.file = "/Flyout.html";
$(document).ready(function() {
$("#show-flyout a").click(function() {
// wyświetlenie Flyout
System.Gadget.Flyout.show = true;
return false;
});
});Zamknięcie flyout odbywa się na tej samej zasadzie, przy czym kod odpowiedzialny za zamknięcie musi się znaleźć w pliku z flyout.
Autor wpisu: batman, dodany: 22.08.2010 17:35, tagi: javascript, jquery
Cel wybiera się w taki sam sposób jak źródło. Po określeniu celu, należy wybrać rodzaj animacji oraz ustalić jej parametry. Np dla animacji przeźroczystości należy wybrać wartość początkową oraz końcową. Oprócz samej animacji mamy możliwość ustalenia dodatkowych parametrów, takich jak czas trwania oraz efekt przejścia. Co więcej, można wskazać animację jaka ma się wykonać po zakończeniu bieżącej.
//Microsoft.Glimmer.OneWay
//<AnimationCollection FilePath="C:\test.html.glimmer.js" xmlns="clr-namespace:GlimmerLib;assembly=GlimmerLib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><Animation Name="ActionName1" EventType="click" Trigger="#link"><Animation.Targets><Target Name="#div" Duration="1000" Easing="linear" Callback="ActionName2"><Target.Effects><ColorEffect CSSName="color" DisplayName="Color Animation" MaxValue="1" MinValue="0" From="0" To=""darkred"" IsStartValue="False" IsActive="True" IsAnimatable="True" IsExpression="False" FormatString="" RequiresJQueryPlugin="True" JQueryPluginURI="effects.core.js" /></Target.Effects></Target></Animation.Targets></Animation><Animation Name="ActionName2" EventType="[none]" Trigger="{x:Null}"><Animation.Targets><Target Name="#div" Duration="1000" Easing="linear" Callback="null"><Target.Effects><RemoveHTMLEffect CSSName="#link" DisplayName="Remove HTML Effect" MaxValue="0" MinValue="0" From="0" To="0" IsStartValue="False" IsActive="True" IsAnimatable="False" IsExpression="False" FormatString="$({1}).remove();
" RequiresJQueryPlugin="False" JQueryPluginURI="" /></Target.Effects></Target></Animation.Targets></Animation></AnimationCollection>
jQuery(function($) {
var timer;
function ActionName1(event)
{
$("#div").animate({"color":"blue"},1000, "linear", ActionName2);
}
function ActionName2(event)
{
$("#link").remove();
}
$('#link').bind('click', ActionName1);
});Więcej informacji na temat Glimmera oraz przykładowe animacje znajdziecie na oficjalnej stronie projektu.Autor wpisu: batman, dodany: 21.08.2010 08:00, tagi: php
Na pytanie jak wysłać POST’a bez submitowania formularza, padają dwie odpowiedzi – AJAX lub cURL. Okazuje się, że jest jeszcze trzecia odpowiedź. Można skorzystać z kontekstu oraz standardowej funkcji operującej na plikach, np file_get_contents.
Kontekst umożliwia zmianę… kontekstu requesta. Najprościej będzie to wyjaśnić na przykładzie:
// przygotowanie zmiennych do wysłania
$post = http_build_query(array(
'zmienna1' => 'wartosc 1',
'zmienna2' => 'wartosc2'
));
// wysyłane nagłówki
$headers = array(
'Content-type: application/x-www-form-urlencoded'
);
// utworzenie kontekstu
$context = stream_context_create(array(
'http' => array(
'method' => 'POST',
'header' => implode("\r\n", $headers),
'content' => $post
)
));
// wysłanie POST-a i zapisanie odpowiedzi do zmiennej
$content = file_get_contents('http://example.com/file.php', false, $context);
Kluczowym elementem powyższego kodu jest funkcja stream_context_create. To ona odpowiada za modyfikację standardowego zachowania funkcji file_get_contents. Stream_context_create przyjmuje dwa parametry. Pierwszym jest tablica zawierająca konfigurację kontekstu, drugim tablica zawierająca dodatkowe parametry.
Dlaczego warto korzystać z kontekstów zamiast cURL-a? Przede wszystkim nie wymaga instalacji. Wiem, że cURL jest zazwyczaj dostęny, ale… Ponadto użycie kontekstu jest prostsze i wymaga mniej kodu oraz umożliwia skorzystanie z funkcji zwrotnej. Oto przykład takiej funkcji zaczerpnięty z maunala.
function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) {
switch($notification_code) {
case STREAM_NOTIFY_RESOLVE:
case STREAM_NOTIFY_AUTH_REQUIRED:
case STREAM_NOTIFY_COMPLETED:
case STREAM_NOTIFY_FAILURE:
case STREAM_NOTIFY_AUTH_RESULT:
var_dump($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max);
/* Ignore */
break;
case STREAM_NOTIFY_REDIRECTED:
echo "Being redirected to: ", $message;
break;
case STREAM_NOTIFY_CONNECT:
echo "Connected...";
break;
case STREAM_NOTIFY_FILE_SIZE_IS:
echo "Got the filesize: ", $bytes_max;
break;
case STREAM_NOTIFY_MIME_TYPE_IS:
echo "Found the mime-type: ", $message;
break;
case STREAM_NOTIFY_PROGRESS:
echo "Made some progress, downloaded ", $bytes_transferred, " so far";
break;
}
echo "\n";
}
Dodanie funkcji zwrotnej do kontekstu jest niezwykle proste i sprowadza się do wskazania jej nazwy w drugim parametrze funkcji stream_context_create.
$context = stream_context_create(
array(
'http' => array(
'method' => 'POST',
'header' => implode("\r\n", $headers),
'content' => $post
)
),
array(
'notification' => 'stream_notification_callback'
)
);
Wywołaniu funkcji file_get_contenst z kontekstem zawierającym funkcję zwrotną spowoduje wyświetlenie:
Connected... Found the mime-type: text/html Made some progress, downloaded 0 so far Made some progress, downloaded 8192 so far Made some progress, downloaded 16384 so far Made some progress, downloaded 24216 so far
Prawda, że proste?
Kanał ATOM
