get the solution

Blog

Seite: 1


Simon Simon
19.09.2011 22:33

Bilderupload: auf dem Client Bilder verkleinern


Schon seit einigen Jahren ist es relativ einfach mit der gd Bibliothek für php hochgeladene Bilder automatisch zu verkleinern. Das funktioniert bis zu einer gewissen Menge ganz gut, doch wenn man z.B.: 10 Bilder hochladen will kommt php schon bald an das Zeitlimit des Servers ran und der Benutzer denkt sich bis dahin schon: Ist da noch alles in Ordnung?

Abhilfe schaffen sollen Plugins für den Browser, die das Bild lokal verkleinern und dann hochladen. So spart man Serverresourcen und auch Traffic. Dafür kann man beispielsweise plUpload [1] verwenden. Gestern habe ich plupload genauer unter die Lupe genommen und festgestellt, dass es eine sehr spezielle Technik verwendet. Es unterstützt zwar viele Plugins (Silverlight, Flash, HTML5), jedoch ist die Implementierung meiner Meinung nach sehr unzuverlässig. Die Dokumentation ist spärlich. Nach einiger Zeit habe ich herausgefunden warum bei mir einfach nichts passierte:

Man kann der plUpload Bibliothek einen Button übergeben, der zum Upload-Button werden soll. plUpload legt dann einfach absolut positioniert das entsprechende Plugin darüber (z.B.: Flash). Die Positionsberechnung war bei mir falsch und ließ sich auch nicht korrigieren. Mehr Erfolg hatte ich dann mit manuellen Positionierungs-hacks. Da das aber keine Lösung sein konnte habe ich mich entschieden, auf agileUpload [2] umzusteigen.

Inzwischen habe ich es schon zum Laufen gebracht. Es ist zuverlässiger als plUpload, weil es relativ einfach gehalten ist. Die aber auf der Webseite versprochene Anpassungsfähigkeit fand ich nicht. Viele Optionen musste ich von Hand nachtragen.

Mein Fazit: Für einfache Anwendungen sind wahrscheinlich beide Uploader geeignet doch in meinem Fall kann ich für unser TemplateSystemCore CMS nur agileUpload mit vielen Modifikationen verwenden.

[1] http://www.plupload.com/
[2] http://www.shift8creative.com/projects/agile-uploader/index.html


Schlüsselwörter: agileUpload, plUpload
zuletzt geändert: 19. September 2011 22:33
Link zu diesem Artikel: (in die Zwischenablage)
Kommentare: Anzeigen





Simon Simon
31.03.2011 18:25

Tetris Spiel mit Javascript


Seit diesem Jahr habe ich in der Schule das Wahlpflichtfach Informatik. Mein Professor Puntigam hat mich damit beauftragt, ein kleines Tetris-Spiel in Javascript zu schreiben.

Ziel ist es, ein einfaches Tetrisspiel zu schreiben, dessen Code leicht verständlich sein soll und vor allem kurz. Für das Tutorial ist es zu empfehlen, den Quelltext herunterzuladen, am Ende des Artikels. Grundvorraussetzung ist die Kenntnis der Javascript-Bibliothek jquery und Grundkenntnisse in Javascript.

Der Grundalgorithmus ist simpel gehalten. Ein Tetris-Objekt wird erzeugt, welches den derzeitigen Tetrisblock repräsentiert. Dieser wird durch die Hauptroutine, die sich zu einer bestimmten Zeit wieder selbst aufruft, immer um eine Zeile nach unten verschoben, bis das nicht mehr möglich ist. In diesem Fall wird ein zufälliger Block geladen und wieder fängt das ganze von vorne an.

Beginnen wir mit dem TetrisObjekt (tetris.prototype.js)

Es besitzt die Eigenschaften:

  • X, Y gibt die derzeitige Position an

  • Form soll eine kurze Bezeichnung für den Block sein, die später wichtig ist, um die referenzierte CSS Klasse aufzurufen

  • rotate gibt den Drehmodus an. Werte von 0 bis 3 sind möglich. 0 ist nicht gedreht, 3 entspräche 270°, 2 wäre 180° und 1 wäre 90°.

  • Matrix speichert das Aussehen des Blocks. Dazu werden 3 in einander verschachtelte Arrays verwendet. Für jeden Drehmodus gibt es ein eigenes Aussehen.

 

Die vordefinierten Blöcke befinden sich in der Datei tetris.blocks.js.

Nun zur Darstellung des Spiels. Hier gibt es verschiedene Techniken. Am besten wäre die fortschrittliche Darstellung mittels eines <Canvas> Elements. Doch dieses wird vom Internet Explorer noch nicht unterstützt und wäre auch schwieriger zu realisieren.

Deshalb wurde die Darstellung mit einer einfachen Tabelle realisiert, die als Matrix behandelt wird. Als Ursprung wird der Punkt links oben verwendet. Das gesamte Interface wurde mittels eines prototypen realisiert, damit man noch später ein Canvas Interface schreiben könnte (tetris.prototype.js, tetris.interfaces.js)

Hauptroutine

[MoveBlock-Funktion tetris.js]

Diese Funktion wird gleich nachdem die Seite geladen ist gestartet. Sie überprüft am Anfang, ob das Spiel im Moment pausiert ist oder nicht. Wenn nicht, dann verschiebt sie den derzeitigen Block nach unten, falls es möglich ist. Das ist allgemein möglich mit der CheckDraw Methode, die Teil der TetrisBlock Klasse ist. Man kann ihr als Argument eine X undY Koordinate geben und überprüfen, ob der Block dort zeichenbar ist (tetris.prototype.js).

Auch muss überprüft werden, ob der Block schon ganz unten ist oder nicht, denn das kann mit der CheckDraw Methode nicht überprüft werden. Falls nun der Block nicht mehr nach unten bewegt werden kann wird ein neuer erzeugt und überprüft, ob eine Zeile nun voll ist. Das heißt also, dass die TetrisBlock Objekte nicht gespeichert werden. Zur Überprüfung wird immer die Matrix verwendet. Das ist einfacher und brauch dann natürlich weniger Speicher, setzt aber einen schnellen Zugriff auf die Matrix vorraus.

Überprüfen, ob die Zeile voll ist

[CheckForLines Methode tetris.js]

Um zu überprüfen, ob die gegebene Zeile y voll mit Elementen ist, wird die Zahl der Tabellenzellen dieser Zeile abgefragt, die eine CSS-Klasse zugeordnet haben. Dazu kann man einen jquery Selector verwenden. Wenn also die Anzahl von Elementen, die gefärbt ist, der breite der Zeile entspricht, ist die Zeile voll.

Auf dem Beispielbild ist eine Zeile hervorgehoben. Hier wäre das Ergebnis der Abfrage 11, da 11 Elemente eine gültige CSS-Klasse besitzen, eines nicht. Hätte diese eine Zelle auch eine gültige CSS-Klasse, wäre das Ergebnis 12 und die Zeile wäre voll.

Wenn die Zeile voll ist, wird das Spiel pausiert, damit keine Fehler in der Matrix passieren, denn die betroffene Zeile wird gelöscht (davor ausgeblendet) und oben eine neue eingefügt. Die Punktezahl wird um 10 erhöht pro Zeile.

Benutzereingaben

[UserMoveTetrisBlock tetris.js]

In sämtlichen Abfragen ob die Benutzereingabe erlaubt ist, wird die CheckDraw-Methode verwendet. Das vereinfacht diese Abfragen sehr. Am Anfang der Methode wird der Block ausgeblendet, und nach der Modifkation der Position wieder eingeblendet.

Download

Das gesamte Projekt auf SkyDrive.

Hier können Sie ein Beispiel online testen.


Schlüsselwörter: Tetris, Javascript, Jquery
zuletzt geändert: 12. Mai 2011 16:18
Link zu diesem Artikel: (in die Zwischenablage)





Simon Simon
22.03.2011 16:50

einfache Slideshow mit Javascript


Für die Seite hausdorfblick.at wollten wir eine Slideshow realisieren, damit ein Foto vom Haus im Winter und eins vom Haus im Sommer angezeigt wird. Dazu machte Martin eine Slideshow mit Flash und ich eine mit Javascript/Jquery. Im folgenden erkläre ich meine Realisierung mit Javascript.

Das Grundprinzip ist einfach: Man setzt alle Bilder in einen div-Container und positioniert sie absolut. Dadurch befinden sich alle Bilder übereinander und man kann sie einfach durch Transparenzeffekte überblenden.

Zuerst ein paar CSS-Klassen, damit man die Elemente später leichter über jquery angesprochen werden können:

<style type="text/css">
.SlideshowImage
{

opacity: 0;
position: absolute;

}

.SlideshowActive
{

opacity: 1;

}
</style>

Die Klasse SlideshowImage ist für alle Bilder der Slideshow. Sie macht sie unsichtbar und positioniert sie absolut. SlideshowActive ist nur für das im Moment sichtbare Bild.

 

Nun der Aufbau im HTML-Code:

<div id="Slideshow">


<img class="SlideshowImage SlideshowActive"
src="images/05092010098.jpg" alt="Am Illspitz" />

<img class="SlideshowImage" src="images/05092010100.jpg"
alt="David" />

<img class="SlideshowImage" src="images/05092010101.jpg"
alt="Benjamin wollte kein Foto" />

<img class="SlideshowImage" src="images/05092010102.jpg"
alt="das Flussufer" />

<img class="SlideshowImage" src="images/10092010110.jpg"
alt="David" />

<img class="SlideshowImage" src="images/21092010124.jpg"
alt="Foto von einer Katze" />

</div>

 

Wie zu sehen ist, hat jedes Bild die CSS-Klasse SlideshowImage und nur das aktive Bild hat die Klasse SlideshowActive.

 

Der Javascript Code:

var SlideshowSpeed = 5000;

$(document).ready(function()
{ setTimeout("SlideshowAnimate();", SlideshowSpeed); });

 

Zuerst wird eine Geschwindigkeit für den Wechsel der Bilder festgelegt. Hier sind es 5 Sekunden. Dann wird ein Timeout festgelegt, der die Slideshow startet, sobald die Seite vollständig geladen ist.

 

Hier die wichtigste Funktion, die die Bilder animiert:

function SlideshowAnimate()

{

/* Das aktive Bild holen */

var ActiveImage = $('#Slideshow').children('.SlideshowActive');

/* Ermitteln, an welcher Position sich das jetztige Bild in der Liste
befindet. */

var ActiveIndex = $('#Slideshow').children().index(ActiveImage);

 

/* Wenn das jetztige Bild das letzte ist, dann von vorne anfangen */

if(ActiveIndex == $('#Slideshow').children().size()-1)

ActiveIndex = -1;

 

/* Nun das nächste Bild aus der Liste der Bilder holen */

var NextImage = $('#Slideshow').children().eq(ActiveIndex+1);

 

/* Das nächste Bild auf volle Transparenz animieren und die Klasse
SlideshowActive hinzufügen, damit es beim nächsten Wechsel
wiedergefunden wird. */

NextImage.addClass("SlideshowActive").css(
{ opacity:0 }).animate({ opacity: 1 }, 800);

 

/* Das jetztige Bild ausblenden und die CSS Klasse entfernen */

ActiveImage.removeClass("SlideshowActive").css(
{ opacity: 1 }).animate({ opacity: 0 }, 800);

 

/* Timeout setzen, damit wieder das nächste Bild angezeigt wird */

setTimeout("SlideshowAnimate();", SlideshowSpeed);

}

 

Ein Beispiel kann man auf http://www.get-the-solution.net/media/file/examples/Slideshow/ ansehen.

Das Beispielprojekt kann man auf Skydrive herunterladen:

http://cid-a7082d0a1081e2f0.office.live.com/self.aspx/.Public/Slideshow.zip


Schlüsselwörter: Slideshow, Diashow, Javascript, Jquery, überblenden, opacity, Transparenz, animieren
zuletzt geändert: 22. März 2011 16:55
Link zu diesem Artikel: (in die Zwischenablage)





Martin Martin
16.03.2011 16:20

readynas duo netgear PPtP VPN


 

Achtung diese Anleitung funktioniert nur für einen Netgear ReadyNas duo Sparc platform (getestet unter 2.6.17.14ReadyNAS #1 Wed Sep 22 04:42:09 PDT 2010 padre unknown). Wird diese Anleitung mit den angebotenen Modulen auf einem falschen Gerätetyp angewendet, kann dies zu unvorhersehbaren Schäden führen.

Um einen VPN Service auf einem Readynas duo sparc zu installieren geht man wie folgt vor:

  1. SHH-Zugang freischalten (Add-ons for RAIDiator 4.1.3+ EnableRootSSH )
  2. APT Addon freischalten (Add-ons for RAIDiator 4.1.3+ APT )
  3. "apt-get install pptpd" ausführen
  4. PPTPD konfigurieren siehe dazu: http://poptop.sourceforge.net/dox/debian-howto.phtml
  5. Module hier runterladen und in das Verzeichnis extrahieren:
    /lib/modules/2.6.17.14ReadyNAS/kernel/drivers/net/ppp_async.ko
    /lib/modules/2.6.17.14ReadyNAS/kernel/drivers/net/ppp_mppe.ko
    /lib/modules/2.6.17.14ReadyNAS/kernel/drivers/net/ppp_generic.ko
    /lib/modules/2.6.17.14ReadyNAS/kernel/drivers/net/slhc.ko
    /lib/modules/2.6.17.14ReadyNAS/kernel/crypto/sha1.ko
    /lib/modules/2.6.17.14ReadyNAS/kernel/crypto/arc4.ko

    Die Module wurden unter der Firmware 2.6.17.14ReadyNAS
    und 2.6.17.8ReadyNAS getestet (Wer die 2.6.17.8ReadyNAS Firmware verwendet, muss den Pfad entsprechend anpassen.)
  6. Mit "modprobe -v ppp_generic" kann man testen ob die Module geladen werden können
  7. "/etc/init.d/pptpd restart" Service neustarten, danach sollte das ganze funktionieren

 

Der offizielle Thread vom Netgear Forum.

Verwandte Themen:

Netgear ReadyNAS - RewriteRules einrichten


Schlüsselwörter: netgear
zuletzt geändert: 07. Juni 2011 21:56
Link zu diesem Artikel: (in die Zwischenablage)





Martin Martin
10.03.2011 17:08

MySQL Cursor alternative – Dynamische SQL Cursor


vor kurzem stand ich vor dem Problem, dass ich in einer MySQL Stored Procedure einen Cursor benötigt habe. Das Problem an der ganzen Sache war, dass für die Cursor Deklatraion einige Abfragen (u.a insert into, select usw.) vorausgesetzt wurden. Das Cursor-Statment wird quais während der Laufzeit "generiert".

Das hat zur Folge, dass man einen Deklaration Block hat auf den eben die nötigen Abfragen zum Zusammenstellen des Cursor-Statments machen muss. Erst dann kann der Cursor mit DECLARE definiert werden. Das Problem wie folgt:

CREATE PROCEDURE `tsc_sp_add_page` (in idfolder int(11), in title varchar(65), in template varchar(100))
COMMENT 'creates a new page and adds all wildcards which will be shown infolder,InLanguage,InAll,InPage'
BEGIN

--id of the inserted page

DECLARE pageid INT(11);

...ein paar Deklaration

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

...dann die vorausgesetzten Abfragen für die Definition des Cursors

--get the language of the page
set pagelangid = (SELECT f.idlanguage as pagelangid FROM tsc_folder AS f WHERE f.id=idfolder LIMIT 0 , 1);

--first we create the page record
INSERT INTO `tsc_page` (`id` ,`idfolder` , `title` , `template`) VALUES (NULL , idfolder, title , template);
set pageid = LAST_INSERT_ID();

...cursor deklaration ist abhänig vom insert into statment
declare c_wildcardInAll cursor FOR select distinct w.id from tsc_wildcard AS w, tsc_page_have_wildcard AS wh, tsc_page AS p, tsc_folder AS f
WHERE wh.idpage = p.id
AND wh.idwildcard = w.id
AND p.idfolder = f.id
AND w.InLanguage =1
AND f.idlanguage =pagelangid;

Laut MySQL Syntax müssen aber alle Deklaration ganz zu Beginn der SP stehen. Nach der ersten Abfrage darf keine weitere Deklaration mehr folgen. Mit dem obigen Code-Ausschnitt erhält man dann die Meldung:

Error code 1064, SQL state 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'declare c_wildcardInAll cursor FOR select distinct w.id from tsc_wildcard AS w, ' at line 29

Line 7, column 1

Jetzt wäre es toll, wenn es so etwas wie dynamische Cursor oder Parameter Cursor geben würde, was aber in MySQL 5.0.24 nicht der Fall war (Evtl wird ein solches Feature bei der nächsten Version nachgereicht?, Orcael kennt z.B. Cursor mit Parameter).

Um keine Cursor verwenden zu müssen, kann man eine temporäre Tabelle verwenden, die quasi als Cursor fungiert. Die temporäre Tabelle muss genau auf die Abfrage angepasst werden. Zusätzlich benötigt man eine weitere RowID Spalte um in der Schleife auf alle Datensätze zugreifen zu können, bzw. um iterieren zu können.

1.) Temporäre Tabelle erstellen

Da ich bei meiner Abfrage nur eine Spalte abfrage, sieht meine temporäre Tabelle recht simpel aus.

CREATE TEMPORARY TABLE twildcardInLang (

`RowID` int(11) NOT NULL auto_increment PRIMARY KEY,

`id` int NOT NULL

) ENGINE=MEMORY;

 

2.) Daten abfragen und in die Tabelle schreiben

Wichtig ist, dass die RowID die Eigenschaften auto_increment und PRIMARY KEY hat. Ansonsten kann man nicht durch die Datensätze iterieren. Danach fügen wir die Datensätze in die temporäre Tabelle ein.

INSERT INTO twildcardInLang (id) select distinct w.id from tsc_wildcard AS w, tsc_page_have_wildcard AS wh, tsc_page AS p, tsc_folder AS f

WHERE wh.idpage = p.id

AND wh.idwildcard = w.id

AND p.idfolder = f.id

AND w.InLanguage =1

AND f.idlanguage =pagelangid;

3.)Hilfsvariable für die Schleife setzen

Nun müssen wir wissen wie oft wir die Schleife durchlaufen wollen. Dies entspricht logischerweise der Anzahl der Datensätze in unserer temporären Tabelle. Als nächstes setzen wir die Zähl-Variable auf 1 um die Schleife durchlaufen- und die Daten der Tabelle abfragen zu können.

SET @NumberRecords = (select count(id) as id from twildcardInLang);

SET @RowCount = 1;

4.) Die Schleife erstellen

Der Code der Schleife sollte nun für sich sprechen.

WHILE @RowCount <= @NumberRecords DO

 

set @wildcardid = (SELECT id FROM twildcardInLang WHERE RowID = @RowCount);

 

...irgendwas mit @wildcardid machen

 

SET @RowCount := (@RowCount + 1);

 

END WHILE;

 

5.) Am Schluss entfernen wir die temporäre Tabelle mit DROP TABLE twildcardInLang;

Der komplette Code-Ausschnitt sieht dann in etwa so aus:

...

CREATE TEMPORARY TABLE twildcardInLang (

`RowID` int(11) NOT NULL auto_increment PRIMARY KEY,

`id` int NOT NULL

) ENGINE=MEMORY;

--get InLanguage=pagelangid wildcards with proper language wildcards and insert it into our temporary table (which we use as "virtual curosr")

INSERT INTO twildcardInLang (id) select distinct w.id from tsc_wildcard AS w, tsc_page_have_wildcard AS wh, tsc_page AS p, tsc_folder AS f

WHERE wh.idpage = p.id

AND wh.idwildcard = w.id

AND p.idfolder = f.id

AND w.InLanguage =1

AND f.idlanguage =pagelangid;

-- Get the number of records in the temporary table

SET @NumberRecords = (select count(id) as id from twildcardInLang);

SET @RowCount = 1;

WHILE @RowCount <= @NumberRecords DO

set @wildcardid = (SELECT id FROM twildcardInLang WHERE RowID = @RowCount);

-- link wildcard with page

INSERT INTO `tsc_page_have_wildcard` (`idpage`, `idwildcard`) VALUES (pageid, @wildcardid);

SET @RowCount := (@RowCount + 1);

END WHILE;

DROP TABLE twildcardInLang;

...

 

Links zum Thema:

http://www.sqlbook.com/SQL/Avoiding-using-SQL-Cursors-20.aspx

http://dev.mysql.com/doc/refman/5.0/en/while-statement.html


Schlüsselwörter: SQL, mysql
zuletzt geändert: 12. Jänner 2012 14:09
Link zu diesem Artikel: (in die Zwischenablage)





Seite: 1


(c) 2011 | Impressum |

| Empfehlenswerte Blog Einträge