Go to content Go to navigation
Stoppt die Vorratsdatenspeicherung! Jetzt klicken & handeln!Willst du auch bei der Aktion teilnehmen? Hier findest du alle relevanten Infos und Materialien:

RegExps und (X)HTML gehören nicht zusammen... · 293 Tage zuvor von Steffen

…ich höre es selbst immer wieder und weise dann oft darauf hin, dass es mit an Sicherheit grenzender Wahrscheinlichkeit die falsche Idee ist (und man ans Reißbrett zurückgehen sollte), wenn man ein (X)HTML-Markup-Problem (oder was auch immer) mit Regulären Ausdrücken angehen möchte. Reguläre Ausdrücke sind zum Parsen von Markup (selbst von Snippets oder kurzen Passagen) einfach nicht geeignet. Schon gar nicht, wenn man HTML-Nutzereingaben “sicher” machen möchte.
Als zweites Problem erweisen sich RegExps an sich…wie Jamie Zawinski es mal ausdrückte:

Some people, when confronted with a problem, think “I know, I’ll use regular expressions.” Now they have two problems.

Ein Satz, an den ich immer zu denken versuche, wenn ich zu Regulären Ausdrücken greife, um ein Problem anzugehen. Dieser erheiternde Stackoverflow-Kommentar zur x-ten HTML-RegExp-Frage faßt es ganz treffend zusammen – und zeigt nebenbei, warum UTF-8 das einzig richtige Encoding im Web ist. ;)

Kommentare

253 Tage nicht geschrieben? · 294 Tage zuvor von Steffen

Naja nicht ganz. Die Agavi-FAQ hat sich ab und zu ein wenig erweitert. Der neueste Eintrag beschäftigt sich mit dem Thema, wie man schnell und einfach Custom-Configs mit Agavi einbinden kann. Mehr zu eigenen Konfigurationsdateien gibt’s in der FAQ oder bei den Webpiraten. Vielleicht bringt mich die Gruppendynamik bei den Webpiraten ja dazu, mal etwas öfter schreibend aktiv zu werden. Einen kleinen Post mit SVN-Einzeilern für Zwischendurch hab ich dort auch abgelegt.

Kommentare [1]

PHP-Framework Agavi 1.0.0 and unofficial FAQ · 547 Tage zuvor von Steffen

Explicitly not calling it yet another web framework in the title, as it’s well designed with an extensible architecture and can be used in a multitude of contexts. Your next web application is as far away as your next console application, SOAP interface or JSON webservice. Or you just reuse everything later on and combine them for the next overly hyped web 2.0 clone.

Agavi has a flexible modular foundation. New developers coming from other frameworks (and other languages like Ruby or Java) should feel at home rather easy. Configuration is XML based (instead of e.g. YAML) and makes use of all the niceties that XSLT (old config file formats get converted automatically to achieve backwards compatibilty), XPointer (XIncludes), XPath and schema validation provide you with. Features include a comprehensive and very capable routing system with so called output types to support any outputs (think HTML, JSON, XML, PDF, $whatever), different layers and renderers, fragment caching for all your (nested) slots, some i18n and l10n features as well as global and action filters for all those people that already know servlet filters and teh like.

Reusability and freedom of choice are a big plus of the framework as nearly everything may be overriden, configured or extended if it doesn’t fit the requirements exactly. Just note, that you don’t have to, as the defaults are well chosen with a strict validation system in place, that requires you to validate not only the standard inputs like request parameters, but also files, headers and cookies. What other framework would a) require you to do that by default and b) makes it that easy with a flexible validation system that comes with a load of validators (nestable and chainable) and lets you create your own custom validators in minutes? Oh and the best for last: just chose whatever third party libraries, object relational mappers (Propel, Doctrine, PDO, whatever) or clientside frameworks (jQuery, mootools etc.) you like.

As the Agavi maintainers are lagging a bit with the tutorial and documentation (they’re working on it though and the source code is well documented), I started compiling some common questions and quickstart hints to ease diving into Agavi’s features. See the small Agavi Framework Frequently Asked Questions (FAQ) document. All handcrafted HTML/CSS and on one page to help you sifting through them in-page. Hope you like it. In case you find some errors and mistakes or just have some nice new snippets or examples to provide for the FAQ, drop me a line or ask for help in the Agavi IRC channel.

Kommentare

Firebug console logging function in Opera · 703 Tage zuvor von Steffen

As some may have noticed, Opera has its own javascript debugging tool now. Dragonfly is still in an early alpha state, but looks very promising and was already quite helpful for me. I use the debug menu and always the latest weekly release (by setting opera:config#DeveloperTools to https://dragonfly.opera.com/app/weekly) from the Dragonfly developer blog. I seriously hope, that the scope protocol gets some attention and will be used in multiple applications/platforms (see the documentation).

The Firebug extension for Firefox is widely in use throughout web developers. Its console methods like @console.log()@, @console.assert()@, @console.time()@ and other are often used. After reading Will Fris' blog entry I thought, that I try to enhance the given code a bit for personal use later on. The following code is everything I came up with so far. It recreates the logging functions, timing functions and the assert function. Remember, that it is just a simple drop-in replacement without the attempt of recreating 100% of the functionality. Simple string substitutions in the logging methods are supported though (imho):

// recreates some things to make scripts with firebug debugging functions
// work in other browsers (especially Opera)
// (just a quick'n'dirty drop-in approach; could perhaps be used as a user javascript)
if (!window.console || !window.console.firebug) {
	var names = ["dir", "dirxml", "group", "groupEnd", "trace", "profile", "profileEnd"];
	var logFx = ["log", "debug", "info", "warn", "error"];
	window.console = {};
	// no more javascript errors in non-firefox browsers
	for (i in names) {
		window.console[names[i]] = function() {};
	}
	for (i in logFx) {
		if (window.opera) {
			// simple replacement of the console.log() etc methods of firebug
			window.console[logFx[i]] = (function (logtype) {
											// using scope to remember the instances of the local variables
											// save function name for later use (logtype === logFx[i])
											// see http://www.howtocreate.co.uk/referencedvariables.html
											return function() {
												if (typeof arguments === "undefined") { // no arguments at all
													return null;
												}
												if (arguments.length === 1) { // single argument provided
													opera.postError(logtype+': '+arguments[0]);
													return logtype+': '+arguments[0];
												}
												var string = arguments[0];
												var regexp = new RegExp(/%([sdifo])/g); // string substitution patterns of firebug console
												var count = 0;
												var match = null;
												// replace found matches with given arguments
												while (match = regexp.exec(string)) {
													string = string.replace(match[0], String(arguments[++count]));
												}
												// display log messages
												var len = arguments.length;
												while (len > count++) {
													if (arguments[count]) {
														string += ' ';
														string += String(arguments[count]);
													}
												}
												opera.postError(logtype+': '+string);
											};
										})(logFx[i]);
		} else {
			window.console[logFx[i]] = function() {};
		}
	}
	if (window.opera) {
		// most simple assertion method with parameters: fn(expected, message)
		window.console['assert'] = function() {
										if (arguments.length !== 2) {
											throw new Exception('Please specify an assertion and a message.');
										}
										if (!arguments[0]) {
											opera.postError('Assertion failed: '+arguments[1]);
										}
									}
		// not a good exchange for the firebug version, as this is dependant of
		// the used counter name and displays a log message for every execution
		window.console['count'] = function(arg) {
									var title = arg || 'defaultCounter';
									if (!window.opera['FireBugEquivalent']) {
										window.opera['FireBugEquivalent'] = [];
									}
									if (!window.opera['FireBugEquivalent'][title]) {
										window.opera['FireBugEquivalent'][title] = 0;
									}
									window.opera['FireBugEquivalent'][title] = window.opera['FireBugEquivalent'][title]+1;
									opera.postError('Counter "'+title+'" '+window.opera['FireBugEquivalent'][title]+'x called.');
								  };
		// start a timer specified by a name
		window.console['time'] = function(arg) {
									var timerName = arg || 'defaultTimer';
									if (!window.opera['FireBugEquivalent']) {
										window.opera['FireBugEquivalent'] = [];
									}
									window.opera['FireBugEquivalent'][timerName] = new Date().getTime();
								  };
		// stops a timer specified by name
		window.console['timeEnd'] = function(arg) {
									var timerName = arg || 'default';
									if (window.opera['FireBugEquivalent']) {
										var startTime = window.opera['FireBugEquivalent'][timerName];
										if (startTime) {
											var stopTime = new Date().getTime();
											var elapsed = (stopTime - startTime);
											opera.postError('Timer "'+timerName+'" took '+elapsed+' millisecond'+((elapsed==1)?'':'s'));
											delete window.opera['FireBugTimerEquivalent'][timerName];
										} else { // no start timer found
											opera.postError('No start timer defined - check timer name or call console.time("timerName").');
										}
									} else { // no timers at all
										opera.postError('No previously stored timers found.');
									}
								  };
	}
}

Tests are in the body part of the demo file:

// console logging tests
var blub = function() { var str = 'some string'; function blub() { return 'blub';} };
console.log(2, 4, 6, 8, "foo", blub)
console.log("%s is %d years old.", "Bob", 42)
console.debug('This is a debug message.');
console.error('This is an error message.');
console.info('This is an info message.');
console.warn('This is a warning message.');

// assertion tests
console.assert(true, "I should pass.");
console.assert("true", "So should I.");
console.assert(false, "I'll fail."); // counts as error in firebug
console.assert(null, "So will I."); // counts as error in firebug
var obj = {}; 
var fn = function(){}; 
obj.prop = "value"; 
fn.prop = "value"; 
console.assert(obj.prop==fn.prop, "Two objects with an equal property.");

// timer tests
console.time('timer 1');
console.time('timer 2');
for (var r = 0; r < 1000; r++) {
	document.write('');
}
console.timeEnd('timer 1');
for (var r = 0; r < 1000; r++) {
	document.write('');
}
console.timeEnd('timer 2');
for (var r = 0; r < 2; r++) {
	document.write('');
	console.count('count title');
}

Gives the following results in Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008092510 Ubuntu/8.04 (hardy) Firefox/3.0.3:

Firebug console output of above code

Opera/9.52 (X11; Linux i686; U; en) gives the following in the error console and dragonfly arror log:

Opera error console output of above code
Opera Dragonfly error console output of above code

Remember, that the javascript code in demo file is just a quick and dirty hack as a training for me after reading Will Fris' blog entry - I just thought of recreating some functionality of Firebug for Opera, just in case I need a drop-in replacement for a script that got developed using Firebug (that is: appearing js errors due to that).

Posting it here, just in case somebody needs something similar. Please note, that the above code could be malformatted due to the first time usage of the dp.SyntaxHighlighter on this blog. :-)

Kommentare

Mixxx SkinEditor · 756 Tage zuvor von Steffen

Mixxx ist ein OpenSource-DJ-Programm, welches man sich unter http://www.mixxx.org/screenshots.php mal näher ansehen kann. Ein Kumpel hatte vor kurzem die Idee, für die Software einen Skineditor zu basteln. Ursprünglich wollte er mit Java/Swing beginnen. Ich hab dann auch mit ihm drüber geredet. Naja, um’s kurz zu machen: Mit HTML, CSS, Javascript (jQuery) kann man in relativ kurzer Zeit recht viel erreichen. Innerhalb weniger Stunden Aufwand in den letzten Tagen habe ich jetzt einen einfachen Ausgangspunkt, der bequem erweitert werden kann. Ein bischen Refactoring tut not und ein paar Kleinigkeiten fehlen noch.
Prinzipiell kann man aber jetzt schon alle Grafikelemente per Drag’n‘Drop neu anordnen und auch schon testweise weitere Eigenschaften der Elemente aus der XML-Datei anzeigen und bearbeiten. Zur Zeit wird die veränderte XML-Datei des Skins nur als Text wieder ausgegeben – aber eine Serialisierung in eine Datei ist eventuell auch noch angedacht. Man könnte auch ein Opera Widget draus basteln – aber wahrscheinlich mache ich das nicht, da ja alle anderen Browser nicht außen vor gelassen werden sollen. ;) Achso – ich hoffe mal, dass der Editor später auf Gegenliebe stößt. Mal sehen. Die nächsten zehn Tage bleibt erstmal keine Zeit für das kleine Projekt. Als Fazit lässt sich aber festhalten, dass jQuery durchaus zu Recht den Status ‘brauchbar’ bei mir hat. Schneller kann man teilweise nicht entwickeln. ;)

Kommentare

Ältere Artikel

Letzte 10 Artikel

RegExps und (X)HTML gehören nicht zusammen...
253 Tage nicht geschrieben?
PHP-Framework Agavi 1.0.0 and unofficial FAQ
Firebug console logging function in Opera
Mixxx SkinEditor
Launch des Freizeitportals für Rügen
The story of stuff...
Wer sich keinen Rechenzentrumstruck...
Die Zukunft des Hostens...
Musikvideos zu produzieren...


Suchen

Kategorien

RSS / Atom



Interessantes

ahoi polloi. Für die (fast) tägliche Portion Karikaturen über den alltäglichen Wahnsinn.

Der Spiegelfechter. “So sagt man, wenn man Jemand mit irgend etwas dem Scheine nach Glaubliches täuscht, es sey eine Spiegelfechterei.” – Beiträge, die zum Nachdenken anregen.

Fefes Blog. Besuchs- und Lesebefehl! Tägliche Informationshäppchen für mehr Aufklärung und Spaß im Leben.

Karl Weiss. Journalismus - so der kurze und prägnante Titel des Weblogs von Karl Weiss. Artikel und Dossiers von ihm (meist veröffentlicht in der Berliner Umschau)

Opera Desktop Team. Blog mit Snapshots des aktuellen Stands der Entwicklung meines Browser-Arbeitstieres.

Püöähh!. Gonmag berichtet Geschichten von seinen Freunden. Oder so. ;)

rabenhorst. "Wenn Du das Weblog liest, wirst Du nie wieder ruhig schlafen." Blog zu Datenschutzthemen und allem was dazu gehört. Samt Gefahr-Indikator für Demokratie & Rechtsstaatlichkeit in Deutschland!

xkcd. “A webcomic of romance, sarcasm, math, and language.” – Comics mit wissenschaftlich-nerdigem Touch. hust Klassiker: Raptorenwitze!


textpattern