Archive for the ‘Tipps und Tricks’ category

Websvn mit Auth unter Debian

January 16th, 2010

Dazu gibts ein gutes Tutorial in Deutsch
zum Tutorial

Extjs: RowEditor. Remove Event an die Datenbank weitergeben.

January 7th, 2010

Die Doku zu dem Thema ist umfangreich. Leider wird überall nur die clientseitige Methode beschrieben die Gridrow zu löschen.
Wie man die Zeile auch der DB löscht ist ein wenig Tricky..(Massive Attack ftw), wenn man localstores verwendet.

Hierzu muss man wie beschrieben einen Deletebutton in eine tbar hängen und als Handler eine function() registrieren.
Anschliessend holt man sich über das Selectionmodel des Gridpanels die Selection, welche die markierte Row darstellt.
Das Ganze ist ein Array. Ueber den 0ten Index kommt man an das Dataobjekt ran, über das man dann auf die einzelnen Cells zugreifen kann. (z.B um die id des zu löschenden Datensatzen über eine Ext.data.connection zu submitten)

Hier ist der Code welcher in die tbar des GridPanels eingehangen wird

{
            ref: '../removeBtn',
            iconCls: 'icon-user-delete',
            text: '{$this->removeButton}',
            disabled: true,
            handler: function(){
                roweditor{$this->gridid}.stopEditing();
                var selections = editorgrid{$this->gridid}.getSelectionModel().getSelections();
                if (selections[0] != null) {
                        var conn = new Ext.data.Connection();
                        conn.request({
                                    url : '{$this->saveController}',
                                    params : {
                                        userID:selections[0].data.userID,
                                        delete:'true',
                                    },
                                    failure : function(resp, opt) {
                                        Ext.MessageBox.alert('Error', response.responseText);
                                    }
                                });
                }
}

Extjs combo listeners onchange vs. select

January 2nd, 2010

Nach 1 Stunde Sucherrei nach dem richtigen Event, um onchange Verhalten auf Comboboxen umzusetzen bin ich auf select gestossen.

Das changeverhalten wird erst ausgeführt wenn das Combofeld den focus verliert. Das ist lästig, weil der User ein echte Onchangeverhalten erwartet.

Hier die Lösung. Statt change einfach select

{listeners:{select:function(){alert("test")}}

Das feuert auf Klick auf die Combo Option

Extjs: Checkboxvalues unchecked übertragen

December 30th, 2009

Das leidige Thema checkboxen im Submit macht auch in Extjs keine Ausnahme.
Checkboxen und Radiobuttons werden beim Submit nicht übertragen wenn sie nicht gesetzt sind. In HTML ist das ganze recht einfach.

In Extjs habe ich die einfachste Lösung gefunden. Man überschreibt das Defaultverhalten und setzt seinen eigenen unchecked-Value.

Hier iist der Code dazu.

Ext.lib.Ajax.serializeForm = function(F){
	if(typeof F==\"string\"){
		F=(document.getElementById(F)||document.forms[F])
	}
	var G,E,H,J,K=\"\",M=false;
	for(var L=0;L<F.elements.length;L++){
		G=F.elements[L];
		J=F.elements[L].disabled;
		E=F.elements[L].name;
		H=F.elements[L].value;
		if(!J&&E){
			switch(G.type){
				case\"select-one\":
				case\"select-multiple\":
					for(var I=0;I<G.options.length;I++){
						if(G.options[I].selected){
							if(Ext.isIE){
								K+=encodeURIComponent(E)+\"=\"+encodeURIComponent(G.options[I].attributes[\"value\"].specified?G.options[I].value:G.options[I].text)+\"&\"
							}else{
								K+=encodeURIComponent(E)+\"=\"+encodeURIComponent(G.options[I].hasAttribute(\"value\")?G.options[I].value:G.options[I].text)+\"&\"
							}
						}
					}
					break;
				case\"radio\":
				case\"checkbox\":
					if(G.checked){
						K+=encodeURIComponent(E)+\"=\"+encodeURIComponent(H)+\"&\"
					} else {
						K+=encodeURIComponent(E)+\"=\"+encodeURIComponent('false')+\"&\"
					}
					break;
				case\"file\":
				case undefined:
				case\"reset\":
				case\"button\":
					break;
				case\"submit\":
					if(M==false){
						K+=encodeURIComponent(E)+\"=\"+encodeURIComponent(H)+\"&\";M=true
					}
					break;
				default:
					K+=encodeURIComponent(E)+\"=\"+encodeURIComponent(H)+\"&\";
					break
			}
		}
	}
	K=K.substr(0,K.length-1);
	return K
}

zend Framework 1.9.6 Autoloader für modulare Projekte leicht gemacht.

December 28th, 2009

Um sich die lästige Angewohnheit require_once() in meinen Projekten abzugewöhnen habe ich meine schnellen Hacks im Zend Projekt versucht durch ein simples Autoloading der Sourcen zu ersetzen.

Am Anfang steht dem Vorhaben die Tatsache im Weg, dass man dadurch auf einiges verzichten muss.
1) Ist Schluss mit einfachen Klassennamen wie “Customers{}” oder “Users”. Die Bindung des Auf SPL basierendem Autoloader ans Filesystem verlangt, das die Klassennamen den Zend Regeln entsprechen müssen.
Eine Modelklasse eines Modules Admin heist nun nicht mehr Admins in Admins.php sondern Admin_Model_Admins in Admins.php

Weil sie ja in “modules/admin/models/” liegt. Dass dabei die Klasse nicht Admin_Models-Admins heisen muss ist damit zu begründen, dass Zend den Ordner für die Models zwar “models” nennt, die harte Verdrahtung auf den Ordner aber “model” benennt.

Die Ordnerstruktur sieht folglich so aus
-application
  -modules
    - admin
    - models
      - Admins.php
    - forms
      - AdminForm.php
    - controller
    - forms

Eine Klasse im Ordner “foms” heist folglich “Admin_Form_AdminForm”. Die Datei heist also AdminForm.php

Das ist zwar kein 100% ges Abbild des Filesystems, aber man weis was gemeint ist.

Man würde die Klasse über $AdminForm = new Admin_Form_AdminForm() instatiieren.

Um den Autoloader zu aktivieren reicht es schon in die Bootstrap folgenden Code zu platzieren. Er aktiviert den Modulautoloader und mapt die Pfade aufs Filesystems.

index.php (oder alternativ: Bootstrap.php in der methode _initAutoload())

$admin_loader = new Zend_Application_Module_Autoloader(array(
       'namespace' => 'Admin', //Admin_Form_DeinForm
       'basePath'  => APPLICATION_PATH . '/modules/admin'  //modulepfad an den Autoloader übergeben
));

Die 3 Zeilen muss man für jedes Modul wiederholen.

Uhrzeit unter debian. mal eben schnell einstellen

December 27th, 2009

Ich hab heute als linuxnewbie versucht die Systemzeit zu stellen. Debian verwendete die zurückgesetze Systemzeit von Windows :-)

Das setzen über Gnome war einfach nicht möglich. Und ntp liess sich nicht installieren, weil abhängigkeiten nicht aufgelöst werden konnten.

Selbst chrony läuft zwar. lies sich aber nicht dazu bringen die Zeit zu setzen.

ein einfaches
date -s “2009-12-23 19:34:30″ hats dann gebracht.

*uff*

Windows :1 Punkt
Debian: 0 Punkte

KISS sag ich da nur

Extjs- Propertygrid. Daten submitten

December 24th, 2009

Leider verhalten sich die Propertygrids nicht wie normale Extjs Formulare obwohl sie eigentlich nur eine spezielle Form davon sein sollten.

Eine Möglichkeit über this.getForm().submit() die Daten zu senden gibts leider nicht.

Hier ist es am einfachsten, einen Button zu adden und einen Event zu registrieren, der einen Jsonstring generiert und überträgt.
Hier ist dieser Event. Einfach an die Propertygrid anhängen.
Wichtig ist zu wissen, dass die Propertygrid die Daten in einer “source” Property vorhält. Die kann man aber schlecht iterieren um die Variablen zu ermitteln.
Die Jsonencodierung dieser Source liefert jedoch einen verwendbaren “Pseudo”-Jsonstring in dem die ” mit \ escaped sind. Die muss man nach dem Request einfach entfernen. Dann kann man mit json_decode() sauber die Vars extrahieren.

buttons:
                [{
                    text: 'speichern',
                    handler: function(){
                    var values = Ext.util.JSON.encode(ID_der_Propertygrid.source)  ;
                    Ext.Ajax.request({
                                url       : 'index.jsp',
                                method    : 'POST',
                                params    : {
                                        values : values
                                },
                                scope     : this,
                                callback  : function(options, success, response) {
                                        if (success) {
                                                this.el.unmask();
                                                Ext.MessageBox.alert('Success!', response.responseText);
                                        }else
                                        {
                                            Ext.MessageBox.alert('Failsure!', 'Suxx');
                                        }
                                }
                        })

                    }
                }]

Extjs “Combo -Boxen” und der geliebte “selected” status auf die aktive Option.

December 22nd, 2009

Manche Dinge, die in Standard – HTML so gewohnt einfach und selbstverständlich daherkommen, dass die Erstellung für einen Programmierer ein paar Sekunden dauern, können einen Einsteiger in DOM und speziell in Extjs 3.1 Tage abverlangen.
Ein Selectfield in HTML ist schnell geschrieben. Die selected-Option auf ein bestimmtes Value noch schneller gesetzt.

in HTML sag ich einfach

<select  id ="" name="" >
<option value="id" selected>ein optionvalue</option>
</select>

fertig. Das Value ist voreingestellt.

In Extjs gibts die Komponente “combo” dafür. Sieht echt toll aus und man hat viele Ajaxoptions dafür.
Sie ist auch leicht erstellt.

{
            xtype: 'combo',
            id: 'username',
            fieldLabel: 'Username',
            hiddenName: 'userID',
            emptyText: 'Select a username...',
            store:
              new Ext.data.SimpleStore({
                fields: ['userID','username'],
                data: [['1','cocomin'],['2','testuser']]

            }), // end of Ext.data.SimpleStore
            displayField: 'username',
            valueField: 'userID',
            selectOnFocus: true,
            mode: 'local',
            typeAhead: true,
            editable: false,
            triggerAction: 'all',
            valueField: 'userID',
            value: '1',
          }

Ja, ist doch easy. Klar. Leicht und verständlich.
Ja. Wenn man folgendes berücksichtigt schon.

1) Wenn man weis, dass man für die Options einen Datastore erstellen muss

2) das forceSelection auf true stehen muss

3) das der hiddenvalue (zb userid). der variablenname im request ist

4) das man den Diplayvalue explizit setzen muss
(in diesem Fall displayField: ‘,valueField: ‘username’,)

5) Das die Verwendung eines lokalen Datastores immer mode:local benötigt. (mode:remote versucht einen jsonstring vom server in den Store zu laden)

6) und das ist das wichtigste in Bezug auf vorselectierte Options
value:’Herr Kannengiesser’ setzt einerseits einfach einen Direktvalue. Tut man das so wird jedoch nur der Value übertragen (”Herr Kannengiesser”), weil er ja keine dazugehörige ID kennt. Klar soweit.
Verwendet man jedoch eine ID (z.B.valueField: ‘userID’, value=’1′) aus dem Datastore zeigt er nicht etwa die ID an. Nein, gut erkannt, er sucht im Datastore zuerst eine ID zum Value=’1′. Exsitiert diese ID im Datastorte zeigt er statt “1″ (value:’1′) den value unter “value:’1′” an. Hierzu muss man den Valuefield auf den Key im Store setzen (valueField: ‘userID’),
Dieser ist dann auch fein selected. Im Request kommt dann brav unter $_REQUEST[userID] (hiddenvalue:’userID’) die “1″ als userID an.
Die Doku und das Forum dazu dazu ist so umfangreich, dass ich von Hacks bis zum dynamischen Nachladen bis über eingeharkte HTML Selectfields in Panelkonstrukten alles gefunden und ausprobiert habe.

Ein “selectedValueInStore” wäre eine feine Sache gewesen.. Nunja. Ich freue ich mich nun über die gefundene Lösung und dass ich vielleicht jemandem die 2 Tage Suche sparen kann.

KISS. Keep it short and simple………..

Zend_View_Helper einrichten und returnvalues als Objekte in einem Layouttemplate nutzen

December 19th, 2009

Ich stand vor dem Problem, in meinem Headerlayout einen Helper für jedes Modul contextbezogen aufrufen zu wollen, um jeder seite einen entsprechenden header zu präsentieren. Dabei wollte ich in meinem Actioncontroller einfach eine variable $headline setzen, die dann vom viewhelper ins layout geschrieben wird.

Wer sich einen Viewhelper einrichten will und in diesem auf die Viewvariablen zugreifen möchte sollte 2 Dinge beachten.
1) Der Viewhelper muss von Zend_View_helper_Abstract abgeleitet sein oder das Zend_View_Helper_Interface implementieren
2) Es wird empfohlen. das Viewobject explizit zu setzen und setView zu überschreiben.

ist ganz einfach.
1) Ihr legt den Viewhelper im Ordner “views/helpers” ab. Ich habe einen Helper “getMyViewHelper.php” verwendet.

2) Ihr definiert die Helperklasse. Sie heist demnach Zend_View_Helper_getMyViewHelper

<?php
/**
 * Description of getMyViewHelper
 *
 * @author peter
 */
class Zend_View_Helper_getMyViewHelper  extends Zend_View_Helper_Abstract {
protected $returnObject=NULL; // soll in einen ViewScript (siehe unten) ausgegeben werden.
    function  __construct() {
                //do some stuff
    }
        //den aktuellen view setzen
        public function setView(Zend_View_Interface $view)
        {
           $this->view = $view;
        }
        //diese methode wird aufegrufen, wenn ihr im layout $this->getMyViewHelper() einbindet. Beispiel siehe "headerlayout"
        function getViewPortItems()
    {
       $this->returnObject=(object)$empty; //wir wollen kein array oder eine einzelne variable , wir wollen ein object
       $this->returnObject->eintest="erster Test";
       $this->returnObject->nocheintest="noch ein Test";
       //hier werden die Variablen aus dem ActionController verwendet
       $this->returnObject->headline=$this->view->eindrittertest;

       return $this->returnObject;
    }
}
?>

Das layouttemplate “header.phtml”

<h1><?php echo this->getMyViewHelper()->eintest?></h1> //variable aus dem helper
<h2><?php echo this->getMyViewHelper()->nocheintest?></h2> //variable aus dem helper
<h3><?php echo this->getMyViewHelper()->headline?></h3> // und da ist die headline aus dem view

im controller cann man dann einfach die headline setzen.

<?php
class Admin_IndexController extends Zend_Controller_Action {
    public function init() {
        $this->translate=Zend_Registry::get("translate_mod");
    }
    /**
     * @desc generates and populates the Adminpanelform
     */
    public function indexAction() {

        $this->view->headline  = $this->translate->_("modHeadline");

    }
}

Zend_Form_Element_Textarea. HTML content wird in setValue() entfernt

December 15th, 2009

Wer FCK oder Tiny einsetzt wird merken, dass der HTML Content, den man versucht mit setValue() auf de Textarea setzen möchte entfernt wird.

Die Viewhelperklasse Zend_View_Helper_Textarea macht ein escape() auf den Value und stript die Tags sauber raus. Es gibt imo keine Möglichkeit über den Decorator den _escape bool dafür  zu setzen.

Daher ist es nötig sich einen Helper zu schreiben, der das escape() nicht macht.

Den Helper speichert man im Modul unter “views/helpers”. Es wird eine Klasse Zend_View_Helper_Deinname gesucht. Also nennen wir die Klasse

Zend_View_Helper_CustomFormTextarea {} und speichern ihn unter CustomFormTextarea.php im obigen Ordner (application/modules/deinmodul/views/helpers).

Wichtig ist auch, dass die Methode die aufgerufen wird, heist wie der letzte Suffix des Klassennamens also “CustomFormTextarea

Hier der Code des Helpers. Wie man sieht ist nicht viel geändert worden.

<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_View
 * @subpackage Helper
 * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: FormTextarea.php 16541 2009-07-07 06:59:03Z bkarwin $
 */

/**
 * Abstract class for extension
 */
require_once 'Zend/View/Helper/FormElement.php';

/**
 * HelperPlugin  to generate a custom "textarea" element without escaping the values
 *
 * @category   Zend
 * @package    Zend_View
 * @subpackage Helper
 * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */

class Zend_View_Helper_CustomFormTextarea extends Zend_View_Helper_FormElement {
/**
 * The default number of rows for a textarea.
 *
 * @access public
 *
 * @var int
 */
    public $rows = 24;

    /**
     * The default number of columns for a textarea.
     *
     * @access public
     *
     * @var int
     */
    public $cols = 80;

    /**
     * Generates a 'textarea' element.
     *
     * @access public
     *
     * @param string|array $name If a string, the element name.  If an
     * array, all other parameters are ignored, and the array elements
     * are extracted in place of added parameters.
     *
     * @param mixed $value The element value.
     *
     * @param array $attribs Attributes for the element tag.
     *
     * @return string The element XHTML.
     */
    public function CustomFormTextarea($name, $value = null, $attribs = null) {

        $info = $this->_getInfo($name, $value, $attribs);
        extract($info); // name, value, attribs, options, listsep, disable

        // is it disabled?
        $disabled = '';
        if ($disable) {
        // disabled.

            $disabled = ' disabled="disabled"';
        }

        // Make sure that there are 'rows' and 'cols' values
        // as required by the spec.  noted by Orjan Persson.
        if (empty($attribs['rows'])) {

            $attribs['rows'] = (int) $this->rows;
        }
        if (empty($attribs['cols'])) {
            $attribs['cols'] = (int) $this->cols;
        }

        // build the element
        $xhtml = '<textarea name="' . $this->view->escape($name) . '"'
            . ' id="' . $this->view->escape($id) . '"'
            . $disabled
            . $this->_htmlAttribs($attribs) . '>'
            . htmlspecialchars($value) . '</textarea>'; //thx to robo47 for the top with htmlspecialchars
        return $xhtml;
    }

}