Latest - General Crap
RSS and Categories
Browser rending weirdness OSX and firefox
Sometimes rendering bugs can be very annoying, IE has it's share of misbehaving, but usually firefox, chrome are consistant and never need much testing. However on one site, prior to going live someone testing on OSX kept saying that the menu bar was broken in Firefox.
Testing on Windows and Linux it looked fine. however on their browser, the horizontal line of buttons for the menu broke into two lines. It was not until I finally did remote control on her PC was I able to see what was going on.
Basically, on first load it rendered fine, but as soon as you went back to the page, the buttons would break. Inspecting it in firebug indicated that the second time it rendered the DOM tree was actually different to the HTML source.
The button code looks a bit like this
<a href="somurl"><div class="btn"><div class="btn-right"><div class="btn-left"><div class="btn-body">Title here</div></div></div></div></a>
The idea is that the div's provide the rounded button edges, and allow nice hover effects all in CSS.
however inspecting the reloaded page indicated the tree looked like
<a href="somurl"></a> <div class="btn"><div class="btn-right"><div class="btn-left"><div class="btn-body">Title here</div></div></div></div>
Where the a tag had broken away from the div, strangely only on one button.
It was only after I ran it through the w3 validator and got an error message about block elements inside and inline one, that I had the idea to rewrite that HTML to use span's, rather than div's. Along with adding display:block to all the CSS for the button elements.
The resulting HTML being
<a href="somurl"><span class="btn"><span class="btn-right"><span class="btn-left"><span class="btn-body">Title here</span></span></span></span>
And amazingly enough it rendered perfectly on all browser.. strange but true....
Leadership lessons, or are MBA courses any good?
And now for something different.. I have a friend doing a course at HKU on Leadership, and with the feedback I'm getting, the course might just be missing the plot a bit.
From my side of the fence, ever since I gave up on my Masters, I have been generally dismissive of post-graduate courses at Universities. There was a serious sense of 'If you can't do it, teach it..' (or now if you really can't do it, blog about it..). My sense is that there is a reasonably large body of acedemia that suffers from the fact that they are kept on board as a result of quantity of research publications. They however they do not appear to understand the principles behind teaching (which teacher training wonderfully encapsulates). I wonder if tutors at university should be required to undertake a teacher training course, rather than slowly migrating from research into tutoring.
Along with all this, I wonder if the type of students these course attract are the exact opposite to 'self-learners', and are more used to a spoon feed education, especially here in asia.
Anyway back to the subject at hand. HKU was teaching a course based around a Harvard case study about a climb of mount Everest resulting in a number of deaths. The students are given the course material and are asked to produce a short piece explaining it and illustrating their ability to extract the leadership lessons that caused the failure.
This is where adult reading (not the picture kind) comes in handy. In Malcom Gladwell's book Outliers, a chapter is dedicated to an interesting study of plane crashes, and pilot assertiveness. If you read the book in the wrong way it appears to sensensionalize the idea that different countries and cultures have different levels of assertiveness which lead to greater crashes with pilot's of different countries. While this inference tends to lead to great press and I presume book sales. It is not really the message that come accross if you read it in detail.
In essense the book points out that individuals (and perhaps to some degree culturally based) are less assertive, in that they feel unable due to their role in society of workforce to assert their opinions. In the case of the pilot's it was the quiet mention that there might be a small issue with the weather. In the case of the climb it was more a case of Doctor's not asserting the seriousness of health issues, or the sherpa's inability to express that they where concern with various issues about the trip. All these would have likely been non-fatal if both communication had been clear and strong, and the subordinates had felt comfortable in the life threatening situations in overriding the leaders actions.
From the sense I got, the course was being taught on leadership, but unfortunatly learning that there are problems occuring with these type of situations has very little to do with leadership, and more to do with realizing that assertiveness training is an essential part of senior management, and more essential in situations which may be life threatening.
What is worse is that the course dynamic's of putting groups into teams and tasking them with these studies looks like it is a perfect example of why failure happens. Rather than using the course to entrench this positive assertiveness it basically leaves the groups to their own devices to produce a result and does not monitor their interaction trying to illustrate the individual's in the groups own abilility to assert their opinions. Would this type of couse not be better taught better with some kind of situation based role playing and instant feedback.
Company rename and RooJS sites now online
After what seems like forever in design and migration, I've turned on the roojs.com and roojs.org domains, I'm slowly in the process phasing out my old company name - AK BK Consulting, which is now rooJSolutions
Quite a few of the key pages are missing content at present, but the blog and it's features are mostly moved over.
After I fill out all the missing content, I'll get back to blogging about how most of the Javascript tools and associated backend libraries all work together. Exciting times for a quality platform neutral Javascript Rich User Interface, guaranteed $(wtf) free...
nested trees in mysql - handy stored procedures.
Storing tree data in Mysql databases, is relatively common, however, all the existing documentation about doing this, makes the whole process rather complex.
If you google it, you will probably find the quite definitive answer at mysql.com, describing the classic parent_id method, and the left/right numbering process. Both of these methods involve rather complex SQL to fetch and update the tree.
In seeking a better solutions for a tree that was infrequently updated, but frequently queried, I thought I'd try seeing if I could write a few stored procedures to simplify the process.
Our basic database structure looks like this:
CREATE TABLE _TREE_ (our key components are
id int(11) NOT NULL auto_increment,
parent_id int(11) NOT NULL DEFAULT 0,
seqid int(11) NOT NULL DEFAULT 0,
depth int(11) NOT NULL DEFAULT 0,
leaf int(1) NOT NULL DEFAULT 0,
name varchar(128) default '',
fullpath TEXT default '',
PRIMARY KEY (`id`),
INDEX qlookup( parent_id , seqid , depth)
);
- id (the nodes id)
- parent_id (the nodes parent - pretty clasic)
- name (the textual name of the node)
- seqid - the generated order item for the whole tree
- depth - how deep the node is (usefull for indenting)
- leaf - is it a leaf node (eg. has no children) - usefull for icons
This does the hard work of iterating through the tree, and updating the sequence number, depth, leaf field and filling in the fullpath field
DROP PROCEDURE IF EXISTS _TREE__resequence;
DELIMITER $$
CREATE PROCEDURE _TREE__resequence(i_sep VARCHAR(4)) DETERMINISTIC
BEGIN
DECLARE v_p, v_d, v_s INT(11);
DECLARE v_fp TEXT;
SET v_fp = '';
SET v_p =0;
SET v_d =0;
SET v_s =0;
SET max_sp_recursion_depth=255;
CALL _TREE__resequence_sub(v_p, v_d, v_fp, i_sep, v_s);
END $$
DELIMITER ;
DROP PROCEDURE IF EXISTS _TREE__resequence_sub;
DELIMITER $$
CREATE PROCEDURE _TREE__resequence_sub(
i_parent INT(11),
i_depth INT(11),
i_fullpath TEXT,
i_sep VARCHAR(4),
INOUT i_seqid INT(11)
) DETERMINISTIC
BEGIN
DECLARE v_nid, v_ex_seqid INT(11);
DECLARE v_name VARCHAR(128);
DECLARE v_leaf INT(1);
DECLARE v_fullpath TEXT;
DECLARE done INT DEFAULT 0;
DECLARE qry CURSOR FOR SELECT id, seqid, name FROM _TREE_
WHERE parent_id = i_parent ORDER BY seqid;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN qry;
REPEAT
FETCH qry INTO v_nid, v_ex_seqid, v_name;
IF NOT done THEN
IF v_ex_seqid != i_seqid THEN
UPDATE _TREE_ SET seqid = i_seqid, depth=i_depth WHERE id=v_nid;
END IF;
IF i_depth > 0 THEN
SET v_fullpath = CONCAT(i_fullpath, i_sep, v_name);
ELSE
SET v_fullpath = v_name;
END IF;
SET v_leaf =0;
SELECT COUNT(id) INTO v_leaf FROM _TREE_ where parent_id = v_nid;
UPDATE _TREE_ SET
fullpath = v_fullpath,
leaf = IF (v_leaf > 0, 0 , 1)
WHERE id=v_nid;
SET i_seqid = i_seqid +1;
#// do the children..
CALL _TREE__resequence_sub(v_nid, i_depth+1, v_fullpath, i_sep, i_seqid);
END IF;
UNTIL done END REPEAT;
CLOSE qry;
END $$
DELIMITER ;
Now our simple add node code just adds the node in the correct place, bumps the seqid along, so that you can then regenerate the tree.
You can now create a generic tree code by replacing my _TREE_ word with your table name:
DROP FUNCTION IF EXISTS _TREE__add_node;
DELIMITER $$
CREATE FUNCTION _TREE__add_node(
i_parent INT(11),
i_after INT(11),
i_name VARCHAR(128)
) RETURNS INT(11) DETERMINISTIC
BEGIN
DECLARE v_depth INT(11);
DECLARE v_seqid INT(11);
DECLARE v_ret INT(11);
DECLARE v_tmp INT(11);
SET v_depth = 0;
SET v_seqid = 0;
SET v_ret = 0;
SET v_tmp = 0;
#// grap parent depth.
SELECT depth +1, seqid + 1 INTO v_depth, v_seqid FROM _TREE_ WHERE id= i_parent LIMIT 1;
#// grab previous id..
IF i_after > 0 THEN
SELECT seqid INTO v_tmp FROM _TREE_ WHERE id = i_after AND parent_id = i_parent LIMIT 1;
IF v_tmp > -1 THEN
SET v_seqid = v_tmp+1;
END IF;
END IF;
INSERT INTO _TREE_ SET
depth = v_depth ,
seqid = v_seqid ,
parent_id = i_parent,
name = i_name;
SELECT LAST_INSERT_ID() INTO v_ret;
#// fix the seqend id
UPDATE _TREE_ SET seqid = seqid +1 WHERE seqid >= v_seqid AND id != v_ret;
RETURN v_ret;
END $$
DELIMITER ;
eg.
#sed -e "s/_TREE_/yourtable/g" tree.js | mysql yourdb -fOnce all that is done the SQL to create tree nodes is very simple:
delete from nametree; alter table nametree AUTO_INCREMENT =1 ;Gives you a nice little table
select nametree_add_node(0,0, 'one at top');
call nametree_resequence(':');
select nametree_add_node(1,0, 'two on one');
call nametree_resequence(':');
select nametree_add_node(1,0, 'three on one (first)');
call nametree_resequence(':');
select nametree_add_node(1,2, 'four on one (last)');
call nametree_resequence(':');
select nametree_add_node(0,1, 'five on top (last)');
call nametree_resequence(':');
select nametree_add_node(0,0, 'six is first');
call nametree_resequence(':');
SELECT * FROM nametree ORDER BY seqid;
Enjoy tree.js (I name my mysql stored procs as js, just so my editor works better with them)
+----+-----------+-------+-------+------+----------------------+---------------------------------+
| id | parent_id | seqid | depth | leaf | name | fullpath |
+----+-----------+-------+-------+------+----------------------+---------------------------------+
| 6 | 0 | 0 | 0 | 1 | six is first | six is first |
| 1 | 0 | 1 | 0 | 0 | one at top | one at top |
| 3 | 1 | 2 | 1 | 1 | three on one (first) | one at top:three on one (first) |
| 2 | 1 | 3 | 1 | 1 | two on one | one at top:two on one |
| 4 | 1 | 4 | 1 | 1 | four on one (last) | one at top:four on one (last) |
| 5 | 0 | 5 | 0 | 1 | five on top (last) | five on top (last) |
+----+-----------+-------+-------+------+----------------------+---------------------------------+
2008 roundup - Recession kicking in?
As my thumbs are twiddling waiting to see if projects start coming in next year, I thought I'd do a roundup of this years projects (open and closed). I was pondering if everyone else was seeing the effects of the recession, so I'd be interested to hear if you've also seen work slacking off.
Let's hope next year we see some more life from the Sales and Marketing, as my current reliance on word of mouth, may not keep feeding my mouth at this rate.
Anyway Merry Christmas and Happy new year to all.
Read on for my Year of Projects
Where have all the good mice gone?
On almost every PC I use, I still have a nice reliable ball mouse, usually wireless, and every few months, it get's a small clean and new batteries. But one of them is now at least 4 years old, and is showing it's age a little, so off I went hunting for a replacement.
To my horror, nobody is selling mice with balls these days (male mice are extinct!!! - female only versions available?). They only sell the optical crap. I've tried optical mouses quite a few times, you always get really bad feedback and the mouse behaviour is eratic at best of times. I usually end up bining them. But I'm still in shock today, that it's so increadibly difficult to buy them. So if you know of any good on-line resellers who sell real mice.. let me know..
On a side line to this, I ended up with a dud piece of hardware from Targus (Note Mac unfriendly supplier!) - their cute looking wireless presenter mouse, has no drivers for OSX, so looks like that one's going back to the shop.. (even linux had support for this!)
[update] I took the Wireless presenter mouse (Targus ARM01AP) back to the shop, after a bit of wiggling by the sales assistant, and pressing buttons on the USB bit, suddly it came to life on the OSX desktop, so after spending 2hours+ trying to find a solution last night, minutes after I plugged it in today, it worked out the box, without any extra software...agghhhh
Microsoft, always delivers... crap...
You know it is going to be one of those days when the lift to the office starts going up, even when you pushed the down button in the lobby..
The morning started with a heated discussion about proposing a video conferencing system to one of our clients. I had come down to two options, a polycom plug and play (hopefully) system, or using 2 iMac's with iChat. But one of my collegues suggested that we recommend a Windows box, with MSN or similar. I was addement, I will never recommend windows for anything as complex as that, the implications for support, securing it (as it needed to have a fixed IP), and knowing that the thing would be guarenteed to fail a good proportion of the times the end user wanted to do a conference. While I sounded alot like a anti-microsoft zealot, I've been burnt far to many times in recommending and installing Windows to even consider it as a reliable option. And it get's difficult arguing with someone who actually think's that OS X has viruses ;)
Anyway, that was just the start of the Microsoft crap for the day. Developers, Developers, Developers I hear them cry, well the day their software actually works as expected, I think they might actually attract enthusiastic developers.
The task for the day was to fix some code I had written to export data to excel. I had practically copy and pasted some code from one project to this one, to implement this process. (I think I've blogged about the concept before), basically you render a HTML table with the data you want to export (a preview), then you use a javascript library, to read the table and generate a gnumeric xml file. This get's sent to the server, that then runs ssconvert to output a beautifully formated excel file, (doing all the colour, background, font effects etc.)
Of course, this library had only be tested on Firefox (as most of the projects that it was used with where XUL based). So I had just said to the tester, does it work with IE?.. of course the answer came back .. NO!
Given the fact that the javascript code in the application followed W3C DOM standards, and did not do anything that amazing, I guess I was a little supprised. So out came vmware, and my nice sandboxed Windows 98. In all it took over 4 hours to solve this, and I guess it's time I regard as a waste of my life (like most times I have to use windows ;)
- First indication of a problem was a little yellow triangle on the browser, pressing on it, told me error at line 0: download()
This it turned out (from what I remember), was that for some reason, IE did not like a href="javascript:download()" as a link, and only when it was replaced with onclick, did it start working ok. - Next up was some message about object does not support that operation on line 134 of xyz.html.
Well, looking at the HTML file, there was no javascript on that line!, it took me quite a while to realize, that the debugger can not handle included javascript files (and uses the line number from the original file) duh!!!, I had to copy all the javascript from the included files, into the main one just to debug it. - That bug turned out to be something as simple as this
x = this.createXMLHttpRequest();
Since x was an object, it could not be checked against a boolean (even though this works perfectly on Firefox)
if (x != false) { - After getting those bugs fixed, the next was a unknown method on an object. which was basically
document.getElementsByTagNameNS('*'',"rows");used to grab sections of the Gnumeric template file, much to my amazement (well less so by now), I realized that IE doesnt actually implement DOM!!! (or DOM3 AFAIK) properly... - At this point I gave up thinking that IE would ever work (or was worth supporting) for my nice exporter. So I started thinking just doing a HTML table to CSV importer, using pretty much the same concept. I however ended up spending a good half hour puzzling over a "Can not download" message, as soon as I added the Content-type header to the output. The kludge workaround for which is actually mentioned on the PHP manual comments.
Mac-mini adventures
I spent a few hours this weekend setting up a new mac-Mini in the bedroom. In general, the whole experience was pretty smooth, and I have considerably more faith that this computer will not become a maintainence nightmare, like the house's last remaining Windows box. The mini scores a few points on linux, for plugging in camera's and setting up sound etc. (but I expect it looses sorely in ability to compile stuff, given the literny of problems I've seen on mailing lists over the last year.)
One thing that did not impress me was Quicktime, while it cutely played movie trailers, It had quite a few problems with avi files.
a) came up with a message about unreadable format, and redirected me to a page listing 3rd party add-ons (without specifying which one I might need)
b) refused to go fullscreen..
Given the overal quality of the rest of OSX, these where rather disappointing. A quick SMS to a friend indicated that VLC was a better bet for AVI's... - he did suggest MS's media player, but keeping anything from MS, as far away as possible from this box, is the general plan..
A few other things installed very easily
- NeoOffice/J (Open office for osx)
- Firefox - Safari is cute, but not quite as polished as firefox.
Now to get ssh working so I can do compile tests with some of the php libraries..
aspx, C#, mono and First Impressions
First Impressions matter, and today, I started with a blank piece of paper, and tried to port a very simple piece of code from PHP to aspx.
While you cant judge a book by it's cover, from today's experience, even reading the first few pages, was enough to make me wonder what all the fuss is with C# and ASPX, it appeared to be a poor joke in comparison to PHP.
I've hacked at C# projects before, having looked very heavily at mcs, and phpLex (a modification of csLex to generate php code). But I'd never really had any need to look at aspx. Today was a little different, a prototype I had thrown together for a project began being rebuilt in C# (dont ask why...)
The first part of the project was to get aspx + mono up and going on the debian box I was using. In general this was a matter of firing up synaptic, searching for asp.net and selecting install, and apply. There was a small issue that the default debian packages do not create a /var/www/.{cant remember the name} directory, and give it write permissions. I eventually spotted an error by starting xsp.exe manually with the verbose flag. (It would be better if xsp.exe install on debian defaulted to logging verbosely to /var/log/xsp.log)
Some of the impressions I got where from things that mono could improve on, others were a little more fundimental in terms of what at present appears to be questionable philosphy in C#, and maybe a lack of experience with aspx.
Having solved the missing directory issue, I went on to try out all the demo's that came with it, alot of these demostrate the web controls, but in general are good enough for a quick feel for the language.
I was a little perturbed by the examples of web controls, the first thing that came to mind was the template files which include <asp:input name="...."> tags would never render on a browser. It would be near impossible to send a file over to a designer and let them focus on the layout. I did like the way that the controls where available as objects (almost like DOM) to the page controller class, but there was a sense that the the base html template had to be altered far too much to enable this interaction with aspx. Ontop of this, although I'm sure it possible to avoid, I got the sense that you where running a HTML page, rather than an application that happened to render HTML. (most PHP I've done in the last year treats the HTML as a skin available to the application, and is nowhere near the page starting/running process). The example also showed only crude examples of including other files, so I'm left pondering if something as simple as a conditional include is even feasible.
But as I got my head around the task at hand, I began to see the other unusual decissions that appear to hamper productivity while developing in the language.
Class's for everything, looks like an ideal for OOP purists, but in reality, it turns simple tasks into a challenge of huge proportions, locating methods of unknown objects. The first task I set myself was sending a P3P header. Which I rather detoured into testing out sending a location header. A little googling / digging on the MSDN pages, and I discovered Response.sendHeaders(key,value). I tested this out on the page with the key=location, and tried to redirect to google.. - nothing happened.. (the browser go the header, but never redirected to anything).. A little further hunting revealed a Response.redirect() method. There was just something smelly about the idea that what should be simple, was made complex by an attempt to make it simple.
The next issue was dealing with cookies, It goes without saying that you need to know two things in PHP to deal with cookies - $_COOKIE (reading) and setcookie() (writing), in C#/aspx I had to deal with creating 2 objects to retrieve a potential cookie, I had to check it was not null, rather than just see if it was false (no native casting of null => false - eg. if (!mycookie) { .... }). and having begain to understand that I needed to use Request.cookies, I made a simple mistake of trying to use Request.cookies to save my new cookie. Again, the complexity of having Response and Request (which when skimming documentation, the difference is easily overlooked), appeared to be another case of trying to make something too simple, and yet adding complexity.
The one that really finished of the effort was looking at md5() - a nice PHP function that returns a string md5 representation of another string. While C# obviously has this, the amount of work required to do what should be a simple task appeared painful at best. Two different classes where needed , one to convert the string to a format that the md5() understood, the md5 one, then a foreach loop to read the bytes returned and convert them back to a nice string.
Along the way I also noticed a few other counter intuative behaviours, (along with one or two slightly cuter features).
- Page exceptions without clear backtracing, and code reveal. (I think) when you try to assign values to asp form elements, that are not strings - I only got a exception, with little explaination..
- Full Page Code reveals for some exceptions, with highlighting of the offending code. (something PHP turned off by default about 2 years ago due to security concerns). - Although it help alot to have it, I'd consider it a bigger problem in the wider picture.
- Vague and often meaningless error messages. I decided to write a small function/method to do the md5 stuff, and defined the method
public String qmd5(String in) {.....}
I kept getting compile errors on the constructor so assumed it was something to do with String using the wrong case. - I eventually guessed that in might be a reserved word or something, and changed it to inStr and solved it..
Happy New Year
Well, a belated New Year update to the blog, So it's more a summary of latest goings on.
Duncan & our Mono chat.
Duncan Mak, a good friend who works alot on Mono, came back to HK for his Christmas break, We had a good chat, given the fact I had to look after my two little monsters at the same time. Mono seems to be moving on really well, I did get a chance to discuss why I think Sterling and Thies idea of targeting Parrot was probably more sensible than .NET. - Basically for all the arguments about stack/register, the real problem comes down to the fact that when writing a opcode compiled language, it is essential to have the knowledge that you have some chance of adding Opcodes (as the ZE2 is now designed to do). The problem which is rather difficult to solve, is the fact that .NET has a specification, and at least 3 implementations. which makes adding opcodes, or native types very difficult. Where as although still complex, it is a matter of persuasion and tact, when you consider this for Parrot.Marching for Democracy
If no-one noticed (like it was all over google news), Hong Kong had another huge March for Democracy on Jan 1st, I went down, and did the 2 hour walk. Although I failed to persuade my better half to join me 'Why should I sacrifice my holiday for this?', which is pretty fair considering how hard she has to work, just so we can survive. But I guess is also indicative of alot of people. The cause is good, they may agree with the motives, but when you get so little free time, it's a hard sell to get involved in improving Hong Kong (or just getting rid of incompetent rulers)Looking after Kids.
Our helper went away for the holidays, leaving me to look after the kids, while it wasnt too bad, they are normally very helpfull around the house. (considering that they think doing the washing up is fun...). It was pretty devistating to any work that I needed to do. I just scraped enough time to finish the slides for the php cruise in march. But got well behind on email.
Follow us
-
- Roo J Solutions Limited is recruiting
- Free your data... seed webkit browser mirror button
- Deleting the View and Controller..
- What was I doing last night... Seed querying xscreensaver
- Watch-out PHP 5.3.7+ is about.. and the is_a() / __autoload() mess.
- Cli parsing in FlexyFramework, PEAR Console_GetArg
- Gtk3 introspection updates and Unusable Unity..
- How to spam in PHP..
Blog Latest
-
Twitter - @Roojs

