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

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




//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?