Wigbi 1.0 alpha done

July 31, 2010 by danielsaidi

I have just ended a couple of months worth of Wigbi 1.0 development. The result is a complete rewrite of previous Wigbi versions, with a load of new features, increased stability and…well, more :)

Since Wigbi 1.0 is developed with TDD, I have found several major bugs that I have not known about before. Thanks to the fact that I have unit tests for every bit of source code, future Wigbi versions should be rock-steady as well.

I will generate documentation for Wigbi 1.0a and will then put it out for download. Notice, however, that no the alpha release will include no plugins, since I have not ported the old versions to 1.0 yet.

All of you who prefer to download the source code will notice that I have removed a lot of in-code documentation, since I believe that the code speaks for itself. The class documentation has been slimmed down a bit as well.

Wigbi 1.0 alpha download will be out really soon…but now: bed.

Long summer break

July 25, 2010 by danielsaidi

After a long and busy summer, I have once again picked up the Wigbi 1.0 development. A beta is not far away, since the only class to finish now is the WigbiDataPlugin (called Seed in previous releases) JavaScript class.

The Wigbi 1.0 release is way different than the 0.99.2 version that was released earlier this year. It is a complete rewrite and features a lot of improvements.

The beta will be out at the end of July, but will not contain any plugins, since all 0.99.2 plugins have to be modified to work with Wigbi 1.0. It wouldn’t take long though.

PHP and JS CacheHandler path differences

June 11, 2010 by danielsaidi

As I am finishing the Wigbi 1.0 implementation, the time has come to implement the JS versions of the Wigbi PHP handler classes. As I implemented the CacheHandler JS class, I came across an interesting problem.

In this post, ~/ indicates the application root, which is where the wigbi folder is located.

In PHP, the CacheHandler class uses page relative paths to the cache folder. All class functions are executed directly when called, which makes page relative paths natural.

In JavaScript, however, the same does not apply. Since the JS class uses asynchronous methods, a page that calls a method will not exist in the same folder as the one that executes it.

This leaves us with an interesting scenario. Say that the page ~/admin/account/myAccount.php sets the cache folder to ../cache.

With PHP the cached files will end up in ~/admin/cache/.

With JavaScript, however, the call is sent to ~/wigbi/pages/postBack.php, where it is executed. Thus, the ../cache path will make the cached cached files end up in ~/wigbi/cache/.

Using the same kind of paths for PHP and JavaScript will therefore not work. Instead, the JavaScript class is set to use application relative paths. Instead of ../cache, use admin/cache.

The CacheHandler JavaScript class will automatically adjust application relative paths so that the postback page can use them.

New class inheritance and JSON functionality in Wigbi.JS 1.0

June 10, 2010 by danielsaidi

Previous versions of Wigbi have used both MooTools and jQuery as embedded toolkits. Now, however, I have decided to exclude MooTools and only keep jQuery.

MooTools have some really nice features, but since i only used its object inheritance and JSON implementation, I decided to exclude it in the upcoming 1.0 release. The less 3rd part components, the better.

New class inheritance model

When I no longer have the MooTools Object class, I use the jQuery extend function to create inheriting classes, as such:

function InheritingClass()
{
   $.extend(this, new BaseClass("optional parameters"));
};

while the MooTools Object class required a syntax like this:

var InheritingClass = Class(
{
   Extends: BaseClass,
   initialize: function() { this.parent("optional parameters"); }
});

The later example requires knowledge about the MooTools object model, while the first only requires that developers know how to use the extend method. In my opinion, it is also easier to implement a function rather than an associative array.

JSON encoding/decoding

MooTools features a nice JSON encode/decode implementation, which I thus will not be able to use anymore. Therefore, I had to find an alternative way of working with JSON.

jQuery contains (at least) two functions that can be used to handle JSON – parseJSON and serializeArray. However, the later only works with DOM elements, so it is not really what I was after.

After doing some reading, it seems like the official json.org JSON JavaScript implementation is the best around, while a jQuery plugin that I found had quite an extensive issue list.

So, although it makes me depend on yet another 3rd part component, I chose this nice little class, which I have used before. MooTools is hereby completely replaced with jQuery (and the small JSON class).

Log and JavaScriptPacker bundled into Wigbi

June 10, 2010 by danielsaidi

Wigbi uses the PEAR Log Package for logging and the JavaScriptPacker to obfuscate the JavaScript code of the, in runtime, auto-created plugin classes.

Previously, the class files (Log.php and JavaScriptPacker.php) has been separate files within the wigbi/php/system/ folder. They have automatically been included when Wigbi was started.

However, since the wigbi/php/system/ folder does not exist in Wigbi 1.0, these two files will be emedded into the wigbi/php/wigbi.php file instead, so that it is not possible to accidentaly remove either file.

I will, however, NOT do the same thing with the wigbi/js/jQuery-x.x.x.js file, since it likely that developers over time may want to replace this file with a newer version.

Bundle CSS files

June 8, 2010 by danielsaidi

In Wigbi 0.99.2, all CSS files within the selected theme folder (if any), as well as within the wigbi/css folder, were added to the virtual bundle file wigbi/wigbi.css. The Wigbi theme engine parsed all files and added them to the virtual file output, as one mega string (or quite small if not that much CSS was defined :)

This is how the output could look:

.validation-error{border: solid 1px #bb4444;background: #ffdddd;}.RatingBar .images a{display: inline-block; width: 20px;height: 20px;}.RatingBar .unrated { background-image: url(../../../wigbi/content/img/controls/RatingBar/rating_unrated.gif); }.RatingBar .rated { background-image: url(../../../wigbi/content/img/controls/RatingBar/rating_rated.gif); }.RatingBar .half { background-image: url(../../../wigbi/content/img/controls/RatingBar/rating_half.gif); }.RatingBar .createdBy { background-image: url(../../../wigbi/content/img/controls/RatingBar/rating_createdBy.gif); }.RatingBar .hover { background-image: url(../../../wigbi/content/img/controls/RatingBar/rating_createdBy.gif); }@import url(../../../box.css);@import url(../../../classes.css);@import url(../../../controls.css);@import url(../../../design.css);@import url(../../../elements.css);@import url(../../../grid.css);@import url(../../../lists.css);html, body{margin: 0px;background-color: #FFFFFF;background-image: none;}.box{border: solid 1px #bbbbbb;}.box .body{padding: 5px;border: solid 2px white;background: #f6f6f6;}.w100 { width: 100%; }.w95 { width: 95%; }.w90 { width: 90%; }.w85 { width: 85%; }.w80 { width: 80%; }.w75 { width: 75%; }.w70 { width: 70%; }.w65 { width: 65%; }.w60 { width: 60%; }.w55 { width: 55%; }.w50 { width: 50%; }.w45 { width: 45%; }.w40 { width: 40%; }.w35 { width: 35%; }.w30 { width: 30%; }.w25 { width: 25%; }.w20 { width: 20%; }.w15 { width: 15%; }.w10 { width: 10%; }.w5 { width: 5%; }.align-center { text-align: center; }.align-left { text-align: left; }.align-right { text-align: right; }.valign-middle { vertical-align: middle; }.valign-top { vertical-align: top; }.float-left { float: left; }.float-right { float: right; }.bold { font-weight: bold; }.bold-italic { font-weight: bold; font-style: italic; }.italic { font-style: italic; }.invisible { display: none; }.clear { clear: both; }span.large { font-size: 1.3em; }span.yellow { color: #ff9900; }img.border{padding: 3px;border: solid 1px #cccccc;}#main-content-middle img.top{padding-bottom: 15px;}div.separator{margin-top: 10px;margin-bottom: 10px; font-size: 1px;height: 5px;border-bottom: solid 1px #dddddd;background-image: url(../../../img/themes/pro/bg_lines.gif);}#main-content-right div.section-title{height: 25px;padding: 3px;background: #f6f6f6;border-top: solid 1px #cccccc;border-bottom: solid 1px #cccccc;}#main-content-right img.section-icon{float: left;margin-right: 8px;}#main-content-right div.section-text{font-weight: bold;margin-top: 7px;margin-bottom: 15px;}.control input[type="text"],.control input[type="password"]{width: 98%;}.control textarea{width: 99%;}.control-body div{margin-bottom: 10px;}.control-footer{margin-top: 10px;text-align: right;}.NewsletterSubscribeForm .email { margin-bottom: 0px; }.NewsletterSubscribeForm .unsubscribe { text-align: right; }html, body{background: #222222;margin: 0px;margin-top: 50px;margin-bottom: 100px;}#main-top, #main-bottom{color: #c4c4c4;}#main-top{padding-bottom: 50px;background-position: bottom;background-repeat: repeat-x;background-image: url(../../../img/themes/pro/bg_top.jpg);}#main-logo{padding: 0px;padding-left: 150px;padding-top: 30px;background-image: url(../../../img/themes/pro/logo.gif);background-repeat: no-repeat;}.main-width{width: 900px;margin: 0 auto;}#main-content { background: white; }#main-content-left { width: 210px; }#main-content-middle { width: 412px; }#main-content-right { width: 220px; }#main-content-left,#main-content-middle,#main-content-right{padding-left: 10px;padding-right: 10px;}#main-content-left, #main-content-right {border-left: solid 1px #cccccc;border-right: solid 1px #cccccc;}#main-bottom{padding-top: 60px;background-position: top;background-repeat: repeat-x;background-image: url(../../../img/themes/pro/bg_bottom.jpg);}#main-bottom-left, #main-bottom-right{color: white;font-size: 0.82em;}#main-bottom-left{padding-right: 10px;border-right: solid 1px #000000;}#main-bottom-right{padding-left: 10px;border-left: solid 1px #333333;}html, body{color: #333333;font-family: Helvetica, Tahoma, Arial, sans-serif, Verdana, Geneva;font-size: 0.9em;}a{color: #ff9900;font-weight: bold;text-decoration: none;}a:hover { color: #ffbb00; }a, ul a { outline: none; }form{padding: 0px;margin: 0px;}h1{font-size: 1.65em;}h2{font-size: 1.4em;margin-top: 25px;border-bottom: solid 1px #cccccc;}h3{margin-top: 25px;margin-bottom: 10px;}h1, h2, h3 { color: #444444; }h1, h2.first, h3.first { margin-top: 0px; }h1.nospace, h2.nospace, h3.nospace { margin-bottom: 0px; }img, a img{border: none}table{border-collapse: collapse;}table td{padding-right: 5px;vertical-align: top;}.grid {}.grid .row {}.grid .row .cell { float:left; width: 100%; }.grid .row.one .cell { float:none; width: 100%; }.grid .row.two .cell { width:50%; }.grid .row.three .cell { width:33.2%; }.grid .row.four .cell { width:25%; }.grid .row.five .cell { width:20%; }.grid .row.six .cell { width:16.6%; }.grid .row.seven .cell { width:14.2%; }.grid .row.eight .cell { width:12.5%; }.grid .row.nine .cell { width:11.1%; }.grid .row.ten .cell { width:10%; }.grid .row, .grid .row .cell.last { overflow: hidden; }.grid .row .cell.last { float:none; width:auto; }.grid.border .row { border-top: solid 1px black; }.grid.border .row.last { border-bottom: solid 1px black; }.grid.border .row .cell { border: none; border-left: solid 1px black; }.grid.border .row .cell.last, .grid.border .row.one .cell { border-right: solid 1px black; }ul.horizontal,#main-menu ul, #main-bottom ul,#main-content-middle ul.titleMenu,#main-content-middle ul.images{margin: 0px;padding: 0px;list-style: none;}ul.horizontal li,#main-menu ul li, #main-bottom ul li,#main-content-middle ul.titleMenu li,#main-content-middle ul.images li{display:inline;}ul.vertical-list,#main-subMenu ul, #main-content-middle ul{border-top: solid 1px #cccccc;margin: 0px;padding: 0px;list-style: none;}ul.vertical-list li,#main-subMenu ul li, #main-content-middle ul li{border-bottom: solid 1px #cccccc;margin: 0px;padding: 5px;}ul.vertical-list li.even,#main-subMenu ul li.even, #main-content-middle ul li.even{background-color: #f3f3f3;}ul.vertical-list li.selected,#main-content-middle ul li.selected{border-bottom: solid 1px #bbbbbb;background-color: #eaeaea;}ul.vertical-list li.separator,#main-subMenu ul li.separator, #main-content-middle ul li.separator{font-size: 0.1em;background: url(../../../img/themes/pro/bg_lines.gif);}ul.vertical-list li:hover,#main-subMenu ul li:hover, #main-content-middle ul li:hover{background-color: #f9f9f9;}#main-menu li{font-size: 1.5em;font-weight: bold;}#main-menu li { margin-right: 10px; }#main-menu li a { margin-right: 5px; }#main-bottom li { margin-right: 5px; }#main-bottom li a { margin-right: 3px; }#main-menu li a, #main-subMenu li a, #main-bottom li a { text-decoration: none; }#main-menu li a, #main-bottom li a { color: white; }#main-subMenu li a { color: black; }#main-subMenu li a, #main-bottom li a { font-weight: normal; }#main-menu li.selected a, #main-subMenu li.selected a, #main-menu li a:hover, #main-subMenu li a:hover, #main-bottom li a:hover, #main-bottom li.section, #main-bottom li a.more{color: #ff9900; }#main-subMenu li.selected{background-image: url(../../../img/themes/pro/bg_subMenu_selected.gif);background-repeat: no-repeat;}#main-subMenu li.selected a{font-weight: bold;padding-left: 5px;}#main-bottom li.section { width: 90px; }#main-bottom li.section, #main-bottom li a.more { font-weight: bold; }#main-content-middle ul.titleMenu{padding:5px;padding-top:7px;margin:0px;margin-top: 10px;text-align: center;background-color: #f8f8f8;border-bottom: solid 1px #cccccc;}#main-content-middle ul.titleMenu li,#main-content-middle ul.titleMenu li:hover{background: none;padding: 10px;border-bottom: none;}#main-content-middle ul.titleMenu li a{color: #505050;}#main-content-middle ul.titleMenu li a:hover{color: #ff9900;}#main-content-middle ul.images{border: none;text-align: center;}#main-content-middle ul.images li,#main-content-middle ul.images li:hover{padding: 5px;border-bottom: none;}#main-content-middle ul.images img{padding: 3px;border: solid 1px #cccccc;}#main-content-middle ul.images img { margin-bottom: 8px; }#main-content-middle ul.songs, ul.songs{margin-top: 10px;}ul.songs li,ul.songs li:hover{line-height: 23px;padding: 0px;padding-top: 4px;}ul.songs li span { float: right; }#lbOverlay {position: fixed;z-index: 9999;left: 0;top: 0;width: 100%;height: 100%;background-color: #000;cursor: pointer;}#lbCenter, #lbBottomContainer {position: absolute;z-index: 9999;overflow: hidden;background-color: #fff;}.lbLoading {background: #fff url(../../../img/slimbox/loading.gif) no-repeat center;}#lbImage {position: absolute;left: 0;top: 0;border: 10px solid #fff;background-repeat: no-repeat;}#lbPrevLink, #lbNextLink {display: block;position: absolute;top: 0;width: 50%;outline: none;}#lbPrevLink {left: 0;}#lbPrevLink:hover {background: transparent url(../../../img/slimbox/prevlabel.gif) no-repeat 0 15%;}#lbNextLink {right: 0;}#lbNextLink:hover {background: transparent url(../../../img/slimbox/nextlabel.gif) no-repeat 100% 15%;}#lbBottom {font-family: Verdana, Arial, Geneva, Helvetica, sans-serif;font-size: 10px;color: #666;line-height: 1.4em;text-align: left;border: 10px solid #fff;border-top-style: none;}#lbCloseLink {display: block;float: right;width: 66px;height: 22px;background: transparent url(../../../img/slimbox/closelabel.gif) no-repeat center;margin: 5px 0;outline: none;}#lbCaption, #lbNumber {margin-right: 71px;}#lbCaption {font-weight: bold;}

This is great, right? However, this approach – which is seen in various CSS bundle solutions around the web – suffers from a major flaw…file paths.

Since the virtual file does not exist at the same place in the file system as the parsed files (or most likely does not), all url paths will be invalid. This especially is the case when parsing files from many different folders.

To account for this, it is possible to adjust the urls and make them relative to the virtual file. This, however, involves way too much work and testing for me to be interested in implementing such a solution…at least now.

So, in Wigbi 1.0, I have taken a step back. The bundle file still remains, but instead of adding all file content to the output as above, I simply import all files of interest. The virtual file output will thus look something like this:

@import url("../css/default.css");@import url("../../wigbi/css2/x.css");@import url("../../wigbi/css2/y.css");

I’m sure that this is not as fast as the compact first option, but by linking to the CSS files like this, I do not have to account for file paths within each file. It works automatically…like a charm :)

Static -> non-static -> static?

June 8, 2010 by danielsaidi

I am currently, as all PHP/JS tests are written and working, having some second thoughts regarding the non-static approach for the various system classes.

It is a nice feature to be able to create your own instances and in such way be able to use them as you see fit, but the default instances are not as easily accessed as when the classes were static, especially not via AJAX.

I still believe that the non-static approach will remain, but I may just add static functions to each class to make it easy to use the classes without having to create instances.

Another thing to consider is which classes that have to be non-static. The DatabaseHander class, for instance, gains a lot from being non-static, since it makes it possible to work with several databases. SessionHandler, on the other hand, maybe does not gain that much, since $_SESSION is static.

I do not have this completely figured out yet, but I’m getting there :)

Wigbi 1.0 PHP system and core packages DONE

May 25, 2010 by danielsaidi

I have finished rewriting all PHP system/core classes. It has been great fun and since Wigbi 1.0 is test-driven, future releases will be rock steady, which will be a relief.

I will now move on to the JavaScript classes, and will search for a nice TDD framework for JavaScript. If you have any suggestions, please let me know. After finishing the JS classes, which should be a piece of cake, I will rewrite all data and UI plugins as well.

However, since Wigbi is entirelly based on the system/core classes, the rest of the work should be a smooooth ride.

Wigbi 1.0 system and core packages almost done

May 15, 2010 by danielsaidi

I have almost completed rewriting all the Wigbi 0.99.3 system and core package classes. The new Wigbi version is fully test-driven, which is a huge improvement from earlier versions. All in all, the new version features a lot of improvements, some class/method removals and a much more slick framework.

All system and core classes are now entirelly independent of the Wigbi class. Only one static class remains (SessionHandler) – the rest have been made unstatic, with default instances that can be accessed via the Wigbi class.

I only have the Wigbi and WigbiDataPlugin (previously called Seed) classes left before I start to convert all the various plugins. All in all, the plugins should be a rather short business to convert, since they all benefit from functionality in already tested base classes.

The documentation will be slicker than before as well. I am currently considering to NOT write demos for all the various system classes and plugins, since the web site has few visitors. Instead, I think I’ll make it possible to request demos to be written, so that I only have to write demos when people need them.

Finally, the AJAX pipeline previously only supported functions that used base type parameters, like strings, integers, booleans and arrays. In Wigbi 1.0, I want to make it possible to serialize/unserialize data back and forth between PHP and JavaScript, and would thus need a serialize/unserialize implementation in JavaScript. Please let me know about any such implementations that gets the job done.

The work with Wigbi 1.0 proceeds

April 28, 2010 by danielsaidi

I am currently working with the Wigbi 1.0 release, which I wrote about earlier. I have now finished writing new versions for the following classes:

  • CacheHandler
  • IniReader
  • JavaScript
  • LogHandler
  • SessionHandler
  • Wigbi (part done)

Working with SimpleTest has simplified development a lot, which is why the pace is so good ;)

In Wigbi 1.0, all system classes will be independent of the Wigbi class (except—the Wigbi class), which means that you will be able to use them for other purposes as well, without having to rely on Wigbi. The only static classes (so far) are JavaScript and Wigbi. All other system classes now have default handlers that are initialized by Wigbi and accessed as properties of the Wigbi class.

Several classes remain,  as well as data and UI plugin classes…but I’m getting there.