Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM

Autor wpisu: Diabl0, dodany: 20.03.2012 17:22, tagi: javascript, php

Użytkownicy pracujący w serwisach intranetowych wielokrotnie stoją przed koniecznością wydrukowania jakiegoś dokumentu czy formularza celem zachowania papierowej dokumentacji czy wydania papierowej wersji klientowi. Dotychczas realizowałem to tworząc i otwierając w nowym oknie dokument PDF gdzie użytkownik musiał ręcznie wybrać opcję Drukuj. Teoretycznie to działa, aczkolwiek jest troszkę upierdliwe. Jednakże ostatnio  przypadkowo trafiłem na informację że PDF może zawierać swój kod JS więc postanowiłem troszkę poeksperymentować.

Sytuacja z życia wzięta – pielęgniarka pobiera próbki do badań laboratoryjnych. Na stronie ma listę zleconych testów oraz informacje jakie i ile próbek pobrać. Na każdą próbkę powinna wydrukować naklejkę z unikalnym kodem kreskowym. Problemem jest to drukowanie: naklejki są małe, kod długi i mało czytelny bez czytnika – przy drukowaniu „masowym” po pobraniu wszystkich próbek łatwo o pomyłkę. Drukowanie każdego kodu w miarę dodawania jest znowu bardzo niewygodne – kliknięcie „dodaj próbkę”, czekanie aż otworzy się okienko z plikiem PDF, kliknięcie drukuj, potwierdzenie ustawień drukowania (wybrać drukarkę do etykiet) i druk, zamknięcie okienka z plikiem PDF. Na szczęście jest na to sposób.

Tym sposobem jest właśnie Acrobat JavaScript.

Dla zainteresowanych dokumentacja znajduje się tutaj: http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/javascript/AcroJS.pdf

Co prawda AJS nie daje nam pełnych możliwości w zakresie drukowania dokumentu, ale już to co jest może nam znacznie ułatwić życie. Dzięki temu udało mi się zredukować cały proces do kliknięcia „dodaj próbówkę” i kliknięcia OK w komunikacie że PDF chce coś wydrukować.

Zaczynamy od naszego dokumentu PDF. Jako kreatora używam znakomitej biblioteki TCPDF, w której można znaleźć metodę IncludeJS(). Mój kod JS wygląda następująco:


// Ustawieniadrukowania
var pp = this.getPrintParams();

// Wybieramy drukarkę (Nazwa drukarki widoczna w systemie)
pp.printerName = "DYMO LabelWriter 450 Turbo";

// Ustawiamy automatyczny wybór rozmiaru papieru
pp.flags |= pp.constants.flagValues.setPageSize;

// Dodatkowe skalowanie aby dopasować dokument do papieru
pp.pageHandling = pp.constants.handling.fit;

// Drukujemy tylko treść bez żadnych dodatków
pp.printContent = pp.constants.printContents.doc;

// tryb "cichego" drukowania - pomijamy okno z preferencjami drukowania
pp.interactive = pp.constants.interactionLevel.silent;

// Wymuszenie drukowania
this.print(pp);

Taki JS  należy „zapisać” w dokumencie PDF. W TCPDF jak wspomniałem odpowiada za to metoda IncludeJS

$pdf = $this->_prepareStickerPDF( $stickerData );

if ( $this->getRequest()->getParam('print', 'false') != 'false' ) {
    // KOD Adobe PDF JS do wymuszenia drukowania i ustawienia podstawowych parametrów
    $js = '
        var pp = this.getPrintParams();
        pp.printerName = "DYMO LabelWriter 450 Turbo";
        pp.flags |= pp.constants.flagValues.setPageSize;

        pp.pageHandling = pp.constants.handling.fit;
        pp.printContent = pp.constants.printContents.doc;
    ';

    if ( $this->getRequest()->getParam('print', 'false') == 'silent' ) {
        $js .= 'pp.interactive = pp.constants.interactionLevel.silent;';
    }

    $js .= ' this.print(pp); ';

    $pdf->IncludeJS($js);
}

$pdf->Output('Sticker.pdf', 'I');

Ok. Mamy spreparowany dokument PDF który automatycznie przy otworzeniu chce się drukować na ustawionej drukarce. Teraz trzeba coś zrobić aby pozbyć się popupów z PDF’em. Z pomocą przyjdzie nam możliwość osadzania obiektów PDF w HTML’u. Możemy to zrobić przez znaczniki HTML lub z poziomu JS (więcej info: http://blogs.adobe.com/pdfdevjunkie/web_designers_guide). Z poziomu JS wykorzystuję do tego PDFObject. W pliku HTML mam placeholder o zerowych rozmiarach i do niego wczytuję dokumenty PDF.

 

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: Marek, dodany: 17.03.2012 08:58, tagi: zend_framework

Ostatnio miałem przyjemność zapoznać się z niedocenianym wcześniej przeze mnie tematem używania kodów kreskowych w aplikacji. Czytnik bez żadnych problemów działał  na Ubuntu 10.04, na którym go testowałem. Kody kreskowe służyły tu do szybszego wyszukiwania uczestników konferencji. Pod względem implementacyjnym dzięki Zend_Barcode wygenerowanie takiego kodu nie stanowi żadnego problemu.

Najprostszy przykład:

$barcodeOptions = array('text' => 'Hekima Blog');
Zend_Barcode::render('code128', 'image', $barcodeOptions);

Tworzy obrazek z kodem kreskowym, w którym zaszyty jest napis „Hekima Blog”. Do renderowania kodu użyłem obiektu klasy Zend_Barcode_Object_Code128, który obsługuje wszystkie znaki ASCII.

Wynik:

Bardziej przydatna wydaje się jednak możliwość dołączenia takiego obrazka do pdfa (np. z zaproszeniem dla danego uczestnika konferencji). Tu mamy dwie możliwości:

  • zapisanie wcześniej wygenerowanego obrazka do katalogu tymczasowego i ręczne dołączenie go do pliku pdf (przydatne jeśli korzystamy np. z TCPDF)
  • dołączenie kodu kreskowego do pliku PDF w locie:
// tworzymy pdfa i jego pierwszą stronę
$pdf = new Zend_Pdf();
$pdf->pages[0] =  new Zend_Pdf_Page('A4');

// i ustawiamy jako źródło obiektu renderującego kod do pdf
$renderer = new Zend_Barcode_Renderer_Pdf();
$renderer->setResource($pdf);

// ustawiamy tekst i font do generowania kodu
    $barcodeOptions = array(
       'text' => 'Hekima Blog',
       'font' => APPLICATION_PATH . '/../data/fonts/Radley-Italic.ttf'
);

// renderujemy kod kreskowy
Zend_Barcode::render('code128', $renderer, $barcodeOptions);

W opcjach kodu kreskowego musimy podać font, który posłuży do wpisania kodu do pdfa. Czcionkę ściągnąłem z Google Web Fonts i umieściłem ją w katalogu data/fonts/.

Poniżej krótki przykład użycia:

/**
 * Klasa służy do generowania kodów kreskowych
 * @author Marek Pietrzak
 */
class BarcodeController extends Zend_Controller_Action {

    /**
     * Generowanie kodu kreskowego do obrazka
     */
    public function indexAction() {
        // wyłączenie generowania layoutu i widoku
        $this->_helper->layout->disableLayout();
        $this->_helper->viewRenderer->setNoRender();

        // ustawiamy tekst
        $barcodeOptions = array('text' => 'Hekima Blog');

        // renderujemy kod do obrazka
        Zend_Barcode::render('code128', 'image', $barcodeOptions);
    }

    /**
     * Generowanie kodu kreskowego do pliku PDF
     */
    public function pdfAction() {
        // wyłączamy generowanie layoutu i widoku
        $this->_helper->layout->disableLayout();
        $this->_helper->viewRenderer->setNoRender();

        // tworzymy pdfa i jego pierwszą stronę
        $pdf = new Zend_Pdf();
        $pdf->pages[0] =  new Zend_Pdf_Page('A4');

        // i ustawiamy jako źródło obiektu renderującego kod do pdf
        $renderer = new Zend_Barcode_Renderer_Pdf();
        $renderer->setResource($pdf);

        // ustawiamy tekst i font do generowania kodu
        $barcodeOptions = array(
           'text' => 'Hekima Blog',
           'font' => APPLICATION_PATH . '/../data/fonts/Radley-Italic.ttf'
        );

        // renderujemy kod kreskowy
        Zend_Barcode::render('code128', $renderer, $barcodeOptions);
    }

}

Jeśli kogoś bardziej interesuje to zagadnienie to polecam dokumentację

Autor wpisu: Śpiechu, dodany: 16.03.2012 16:06, tagi: php

Pomysł na wpis dał mi kilka dni temu Facebook, a dokładniej ich totalnie niekonsekwentne oznaczenia co się kiedy wydarzyło na naszej tablicy. Raz jest to 23 minut(y) temu, raz 7 godz. temu, jeszcze inaczej około godziny temu. Być może różne ekipy robią osobno opisy czasu i stąd różnice. Postanowiłem dla sportu zmierzyć się z problemem. Powstało takie coś jak Timespan Smarty Modifier.

Opis jak to zainstalować, wymagania i sposób użycia możecie sobie przeczytać w moim kaleczonym angielskim w GitHubie. Tutaj chciałbym się skupić jak to działa. Najwygodniejszym sposobem korzystania z biblioteki jest poprzez modyfikator w szablonach Smarty, a więc {$jakaśZmienna|naszModyfikator}.

Przede wszystkim sama nazwa pliku musi nazywać się modifier.nazwa.php, za to funkcja smarty_modifier_nazwa($argument). Pierwszy argument automatycznie dostaje wartość zmiennej, dla której wywołujemy modyfikator. Jeśli chcemy, następne podajemy po dwukropku. Drobna uwaga: nigdy niczego nie „echujemy”, tylko zwracamy poprzez return. Chodzi o łańcuchowe łączenie modyfikatorów.

Z uwagi na to, że całość rozrosła się do ponad 400 linii kodu, nie ma sensu wszystkiego tutaj przytaczać. Skupię się na najważniejszych rzeczach.

Całość ma formę klasy abstrakcyjnej rozszerzanej przez poszczególne języki. Na podstawie zadeklarowanego języka skrypt próbuje znaleźć sobie właściwą klasę (fragm. modifier.timespan.php):

$className = 'Spiechu\TimeSpan\TimeSpan' . strtoupper($lang);
   if (class_exists($className)) {
      $timeSpan = new $className();
 
      // sprawdz czy klasa rozszerza AbstractTimeSpan
      if (!($timeSpan instanceof Spiechu\TimeSpan\AbstractTimeSpan)) {
         $timeSpan = new Spiechu\TimeSpan\TimeSpanEN();
      }
   } else {
 
      // jesli nie ma takiego jezyka lub klasa niewlasciwa uzywam angielskiego
      $timeSpan = new Spiechu\TimeSpan\TimeSpanEN();
   }

Potem tylko konfigurujemy klasę i zwracamy wynik:

$timeSpan->setStartDate($date)->showSuffix($suffix);
return $timeSpan->getTimeSpan();

W klasie AbstractTimeSpan z kolei mamy trochę logiki związanej z obliczaniem interwału:

$curDate = new \DateTime('now');
$diff = $curDate->diff($this->_startDate); //otrzymujemt obiekt DateInterval

Począwszy od największej jednostki (rok) odpytujemy $diff która z jego zmiennych publicznych jest większa od 0 oraz za pomocą metod isHalfUnit($actualUnit, $fullUnit), almostFullUnit($actualUnit, $fullUnit) sprawdzamy czy może przekroczyliśmy połowę obecnej jednostki, większej jednostki oraz czy nie można jej zaokrąglić do następnej całej.

Klasy rozszerzające implementują m.in. metodę getUnit($howMany, $unitSymbol, $half). Liczebniki angielskie są tak trudne, że potrzeba na nie aż 1 linijki:

if ($howMany > 1) $howMany = 2;
return $this->_units[$howMany][$unitSymbol];

Jeśli mowa o $this->_units to wygląda to tak:

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: d3ut3r, dodany: 14.03.2012 02:27, tagi: javascript, jquery

Podczas realizacji jednego z ostatnich projektów, używałem selektora :contains jak się okazało selektor ten nie jest wrażliwy na wielkość znaków czyli dla niego kot i KOT to to samo niestety nie o to chodziło mojemu klientowi :)

W internecie natknąłem się na ciekawe rozwiązanie definiujące własny selektor :Contains dzięki czemu mogłem używać standardowego :contains jak i nowego :Contains. Poniżej znalezione rozwiązanie:

jQuery.expr[':'].Contains = function(a,i,m){
    return jQuery(a).text().toUpperCase().indexOf(m[3].toUpperCase())>=0;
};

Autor wpisu: singles, dodany: 12.03.2012 21:25, tagi: internet

Dokładnie rok temu, 12 marca 2011 w sieci pojawił się blog o nazwie „Works for me”, która wzieła się od ulubionej odpowiedzi szanującego się programisty na zgłoszenie o błędzie aplikacji – mianowicie „u mnie działa” (zwana też Standardową Odpowiedzią Administratora #1).

Minął rok, czas na podsumowanie tego, co działo się z blogiem jak i wokół niego.

Liczby

W momencie pisania tego wpisów liczik postów wskazuje 41. Czy to dużo, czy mało? Średnio wychodzi prawie jeden post tygodniowo, czego nie uważam za wynik zły. Starałem się, aby moje artykuły były wartościowe, pisane w momencie, kiedy czułem, że mam coś ciekawego do przekazania – czy mi się udało? Ocena należy do Was.

Do tego dochodzą 273 komentarze (no i 2436 komentarze wyfiltrowane przez antyspam, ale to raczej nie jest powód do dumy). Niektóre posty były bardzo obszerne w komentarze (zwłaszcza te z serii „Oddam książkę za darmo” ;), inne mniej, aczkolwiek nie mogę narzekać na ich poziom, co także uważam za plus. No i prawie w ogóle nie ma w nich flame’u ;]

Analytics

Najpopularniejsze wpisy wg Google Analytics z ostatniego roku to:

Z ciekawszych rzeczy – z jakich haseł wyszukiwania ludzie trafiali do mnie na bloga? Pomijam milczeniem fakt, że „php” pojawia się po raz pierwszy w haśle na pozycji czwartej;) Jednakże, moi faworyci to:

  • oddam ksiażki za darmo 2011 (+ kilkanaście różnych odmian tego hasła) – widać „popularna” akcja się z tego zrobiła dzięki Batmanowi :)
  • kim jest tantek celik
  • jak zostać programistą php i jak nie zostać programistą php – ex aequo
  • jeden by wszystkimi rządzić – współczuje fanom Tolkiena zetknęcia z tematem o CASSISisie

A, no i oczywiście:

  • mój pierwszy raz – no dobra, tutaj współczuje jeszcze bardziej niż w poprzednim punkcie :]

No dobra, ale wyjdźmy do ludzi

Ci, którzy czytają mojego bloga regularnie, zauważyli pewnie zmniejszenie częstotliwości publikowania przeze mnie wpisów. Przyznaje się bez bicia. Jednakże, wydaje mi się, że mam usprawiedliwienie. I nie chodzi wcale o sprawy prywante. Nie chodzi o zmianę pracy. Nie chodzi o inne aspekty. Głównym powodem takiego stanu rzeczy jest meet.php.

Coś, o czym myślałem od dawna, coś co dzięki współpracy z Danielem oraz pomocy wszystkich zaangażowanych (prelegentów oraz ludzi którzy pomagają z własnej, nieprzymuszonej woli) udało się wprowadzić w życie. Coś, z czego – jeśli chodzi o „developerską” część mojego życia – jestem do tej pory najbardziej dumny. Dziękuję Danielowi, dziekuję prelegentom, dziękuję ludziom, którzy pomagają nam za każdym razem, dziękuję uczestnikom!

2012?

Co będzie w 2012? Bloga nie porzucam, troche się za nim stęskniłem – postaram się napisać coś na dniach. Ogólnie plany na 2012 są. A co z tego wyjdzie, czas pokaże :)

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: bigzbig, dodany: 12.03.2012 18:32, tagi: javascript

Facebook to dla developera wieczne utrapienie. Ciągłe zmiany w interfejsie, w API, dodawanie coraz to nowych funkcjonalności czy choćby permanentny redesign zmuszają do bezustannego poprawiania napisanych aplikacji. Pisząc aplikacje na facebook średnio raz na pół roku muszę być przygotowany na to, że połowę rzeczy, które nauczyłem się ostatnio implementować teraz będę musiał zrobić w zupełnie [...]

Autor wpisu: bastard13, dodany: 12.03.2012 12:20, tagi: oop, php

na wstępie słów kilka

Znowu dłuższa przerwa w publikowaniu czegokolwiek. Na szczęście dobiegła końca i mam nadzieję, że w ciągu najbliższych kilku-kilkunastu tygodni uda mi się dokończyć wszystkie zaległe wpisy, na które pomysły dojrzewały, lecz z braku czasu nie mogły się doczekać realizacji:(O czym dzisiaj? O stałych. A czym są te stałe? Kiedy ich używać, a kiedy nie? O tym dalej:)Czytaj więcej »
Wszystkie wpisy należą do ich twórców. PHP.pl nie ponosi odpowiedzialności za treść wpisów.