Are you really going to buy new phone?

I was an happy Palm Pre (one) user, I bought it with the idea to develop Javascript useful applications to simplify my own tasks, but I never had much free time to really start it. Suddenly, the touch screen started to work badly, becoming every day more unusable.
The time to look for a new phone has come - I though, so I've started looking for new fancy models, diving among specifications and lurking details everywhere.

I never paid too much attention to collegues or friends models, they've always seemed to me too much big, but I had to face it; now, what the hell: I need a mobile phone, not a mobile phone and a bag to put it in, they are almost all that big and won't fit my pocket!

The Pre measures are 100x60x17 millimeters, has nice but weak sliding qwerty keyboard; it's not perfect, but it fits my needs: where those fucking keyboards are now? "Keyboard? It's touch baby, no need for an old junky keyboard and bulky buttons".

Uh? So under the rain with an umbrella on the other hand I'll open the bag, take of the glove I'm wearing, put the glove in the bag or between legs (up there, yep!), take out the mobile phone, maybe take it out also from its case, unlock with thumb, select the application or filling out the number hoping that the touch won't miss a shot, clean a raindrop, touch the wrong option, retry…?

Are you kidding me? Sometimes, walking, I meet people frozen with elbows on stomach trying to type messages without errors: they don't seem happy and it's not even a nice view!

 

Why I'm so upset?

After I've dimissed the Pre, I've reactivated my N80 (95x50x20 mm),  an old model released in 2006 (six, years, ago); I was surprised: the hardware is a bit slow, but I can browse everything with one finger on few buttons; all the apps installed cover almost every need:

  • Phone calls
  • Messages
  • Addresses
  • Calendar
  • Maps
  • Notes
  • Voice Recorder
  • Calculator
  • Clock/Alarm
  • Photo and videos

I can also browse the web, but the screen is too small and I don't mind. I'm able to use it with a winter leather glove with one hand. So what are the benefits over the Pre or other recent touch mobile phones?

It's touch! It's cool! It has tons of apps you can download! It has Facebook! You can browse the Internet like a normal PC!

 It's the average answer I got, and I prefer not to ask which sites they're staring in -more or less- 4 inches.

Make a step back and think about the word "usefulness": the mobile phone is not just a device to make calls, and I'm not a fanatic about "buy just what you need and take the most cheap or you'll be damned!", we're not talking about this here (but maybe you'll be damned anyway): it's multi-functional but it's the idea of function that is gone to be miserunderstood.

To write a message is a function: you can write stupid or good ones; to take a note is another: you can save it on a file or over the Internet; and another one is a timed notification: you can hear it with a creepy beep or a loudy mp3.

The useful function are those actions by themselves, innovation is not the better way you can do them, but how they integrates with your life, and integration means to automatize your own process avoiding the need to think about them, it's freeing your time.

What did the industry do during these years? Selling always the old crap in the nicer boxes that I love; but the marketplaces are just full of clones that could add something to the user experience, but don't make a new phone more useful then the old ones, just more funny.

 

It's all about fun

Take a five minuts video, make a thumb, publish on your social site automagically and share it to the world on you favourite social site: I beg your pardon, are you a journalist?

That's for sure more exciting then to watch the annoying holiday movie of friends and relatives, and has drammatic social implications too; but it cannot be called a useful function for what I've just said. You're just having fun, but that fun it's not mine: I prefer to make the video then edit it and publish in front of a big monitor.
Anyway the device that can handle all this must be powerful and here you are the reason of new models: they let make the "not useful" possible.
Now, I don't use the term useless because it's false they are: I'm happy I can take better photos, but it didn't change the way I take them: unlock the phone, touch and slide pages, find the app, select it, shoot! Oh, I've just lost the smile of my cutie while I was looking at the smoothly animated interface…

 

Why wish for them?

Then there's even a pure psycological view of the subject related to the appearence of the object: new devices are cool, that's it. And don't read this as a granny that tries to teach the real important things in life: appearence is important and if you're proud to carry on with an 80's DynaTAC because it just let you make some calls… good luck!
Appearence is design, design is human effort to improve ergonomics, usability and much more; it creates the style of the environment you live in, making it more comfortable, unique, and it becomes recognizable over time making the history: for instance Brionvega still looks good, you recognize it as obsolete but get immediately the idea of that time.

But again another miserunderstanding occurs: the appareance becomes a status symbol and the mobile phone the "scepter of power" or just something that let you feel to be accepted like a pair of branded shoes; so you need it even if you don't use it.
How many application do you use day by day?
I'm not too much in, but -just for instance- I heard about iPhone related to Steve Jobs, Angry Birds and long (more or less violent) queues outside Apple stores.
Is iPhone just a status symbol? No! It's a pieace of history and design, for external appearence and user interface, but don't come telling me the new release it's life changing and you feel the urge to have it: it's desire to possess, it's a disease.

 

What do we need?

I'm going to make calls and send old plain text sms messages as I've always done since I got my first 5110. The best I used for this purpose has been the Siemens SK65: still good looking, sadly too big, but with the most comfortable keyboard I ever used: chatting on IRC and walking going home from work was a breeze.

Today there are tons of models, but few have unique features: the Xperia Active has the ip67 certification, the Xperia X10 Pro has a nice sliding qwerty keyboard in a decent size. I'd like to go for geocaching or record my running sessions in the district, but it will ends like the programming experiments with the Pre; so better to think about other kind of devices like the SmartWatch or just stop and accept it: there's no need for new mobile devices, there's the need for new software.

We are so one-way minded that the way we divide software never changed: games, production, finance, lifestyle (?!?), sports and other junk are the standard categories we think about. Maybe they are, but not at the very first level and are usually misleading.

Software should be divided in informative, interactive and device enhancements.

You'll have software to just retrieve data and view it, other to manipulate data, other just to personalize the device with Hello Kitty stuff.
The one we require is the interactive and the purpose of interaction should be transparent to the user.
The most fascinating example I found of what I'm talking about is the JITWatch of Martin Frey: it shows perflectly how to solve a concrete problem without making it seem a problem and let you to live your life without thinking about it.

Still convinced you need a new phone? Go for it, but buy the one you'll have most fun with, you'll spend your money for the real value they can offer today.

Keybord remapped? Keyboard owned!

After I bought a tenkeyless keyboard and gone back to Linux, I had a little problem: as italian it's mandatory an italian keyboard's layout to write those special character an us one doesn't have. I had no more excuses to face the problem and it really got me mad.

After two days searching I think I still don't master the subject, but at least I got my cutie to work as I needed, here is the my map:

default xkb_keymap "otaku" { 
        xkb_keycodes  { include "evdev+aliases(qwerty)" }; 
        xkb_compatibility { include "complete" };
        xkb_types     { 
                include "complete"
                virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper;

                type "SUPER_LEVEL"  {
                        modifiers= Super+Lock+Control+Shift+LevelThree;
                        map[Shift]= Level2;
                        map[LevelThree]= Level3;
                        map[Shift+LevelThree]= Level4;

                        map[Control]= Level5;
                        map[Shift+Lock+Control]= Level5;

                        level_name[Level1]= "Base";
                        level_name[Level2]= "Shift";
                        level_name[Level3]= "Alt Base";
                        level_name[Level4]= "Shift Alt";
                        level_name[Level5]= "Level5";

                        map[Super]=Level5;
                };
        }; 
        xkb_symbols   { 
                include "pc(pc105)+it+inet(evdev)" 
                replace key <MENU> { [ Multi_key, Multi_key ] }; 

                replace key <AD11> {                                                                     
                    type= "SUPER_LEVEL",
                    symbols[Group1]= [egrave, eacute, bracketleft, braceleft, less]
                };
                replace key <AD12> {                                                                     
                        type= "SUPER_LEVEL",
                        symbols[Group1]= [plus, asterisk, bracketright, braceright, greater ]
                };
                replace key <AB09>  {
                        type= "SUPER_LEVEL",
                        symbols[Group1]= [period, colon,periodcentered, diaeresis,ellipsis]
                };
                replace key <AE10> {
                        type= "SUPER_LEVEL",
                        symbols[Group1]= [0, equal, braceright, dead_ogonek, notequal ]
                };

                replace key <AE12> {
                        type= "SUPER_LEVEL",
                        symbols[Group1]= [ igrave,     asciicircum,      asciitilde, dead_circumflex,  U266B]
                };
        }; 
        xkb_geometry  { include "pc(pc105)" };
};

 

The first intention was to remap the right window key to type diamonds (<>) characters  pressing AE11 and AE12 characters (the ones on the right of p key on a qwerty keyboard), but the idea itself was wrong: the current mapping has to be replaced by another mapping with another level for the symbol triggered by the modifier.

That's why I've created a new type that handles the Super modifier. The string:

map[Super]=Level5;

means to use the fifth position of the symbol when the keycode of that type will be pressed. Creating the new type was a mess because I forgot to replace all  already existent  levels.

To create a new type with just a single modifier hoping it will be merged somehow won't work.

Is this the right way to do it? Dunno, I'm still thinking why I had to add the virtual_modifier list and how all those mapped levels work, but after all rumblings it works and finally I can type with just one keystroke… ♫ TA-DAaa!

Uh, and it's obvious I'm using my own file to apply these changes, I can't understand why people accept to change with ease their distro's files… mah.

Many thanks to / see also:

 

Mobo got the power!

With my D201GLY motherboard I was struggling about how to make the wake on lan feature to work: it only worked after pulling out and in the power cable; Google searches helped me only after I understood I need to set the ethernet device in a status able to receive the magic packet even if the halt command not seems to be called with the -i option.

So I found I just need to add this command to my halt script:

ethtool -s eth0 wol g

and now it always accepts my gorgeous packets

See also All about system power states by Intel, Wake_on_Lan by Anchor Systems, wakeonlan.html on Calomel.org.

Firebug, the time thief.

I created a page with two dijit.Editor, two ValidationTextBox and two FilteringSelect. I was surprised by how long the page took to render: almost 70 seconds.

So I've created a small html to check it out; I already knew that Firebug makes everything slower but not so slow: Chrome makes the dirty job in 609ms with the console opened, showing even, at the end, a cleaner profiler layout.

Should I seriously consider Chrome for Javascript development?

1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <script src="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js" type="text/javascript"></script>
 5         <script type="text/javascript">
 6             dojo.require("dijit.Editor");
 7             dojo.require("dijit._editor.plugins.LinkDialog");
 8             dojo.require("dijit._editor.plugins.ViewSource");
 9             dojo.require("dojox.editor.plugins.PasteFromWord");
10             dojo.require("dojox.editor.plugins.FindReplace");
11         </script>
12         <script type="text/javascript">
13             dojo.addOnLoad(function() {
14                 console.time('parse');
15                 console.profile();
16                 dojo.parser.parse();
17                 console.profileEnd();
18                 console.timeEnd('parse');
19             });
20         </script>
21     </head>
22     <body>
23         <div  dojotype="dijit.Editor" plugins="['cut','copy','paste','findreplace','|','bold','italic','underline','strikethrough','|','removeFormat','insertOrderedList','insertUnorderedList','insertHorizontalRule','subscript','superscript','|', 'indent', 'outdent', 'justifyLeft', 'justifyCenter', 'justifyRight','|','createLink','insertImage','|','viewSource','pastefromword']">Waiting for firebug...</div>
24     </body>
25 </html>


Then, gone back to my code, I've stared the screen pleasing with how fast it is.

DBIx::Class love

It's not that hard to make me happy, DBIx::Class did it, letting me update easly data in a many-to-many relationship. This one is between two tables, Collection and Items; after I've configured the DBIC relationship inside schema's packages and the bridge table has been created automatically, few lines of code are enough to do the trick:

my $collection = $model->resultset('Collection')->single({id=>$id});
my @items = $model->resultset('Item')->search({id=> {-in => \@ids} });

$collection->set_items(\@items)

This would be converted in these annoying sql queries: DBIC will remove and insert what needed.

SELECT me.id, me.label, me.description FROM Collection me WHERE ( id = ? ): '4'
SELECT me.id, me.idMeta FROM Item me WHERE ( id IN ( ?, ?, ? ) ): '52', '53', '57'

DELETE FROM Item_Collection WHERE ( idCollection = ? ): '4'
INSERT INTO Item_Collection ( idCollection, idItem) VALUES ( ?, ? ): '4', '52'
INSERT INTO Item_Collection ( idCollection, idItem) VALUES ( ?, ? ): '4', '53'
INSERT INTO Item_Collection ( idCollection, idItem) VALUES ( ?, ? ): '4', '57'

Harrr! Every mighty pirate should do this!
This has been so easy that I know for sure I'll forget it in few days, that's why I'm writing it...

See also DBIx::Class::Relationship::Base.

XMLHttpRequest.send files without multipart form

The proper way to send file over http  should be by using a multipart form, current browsers -and with the term browser I'm not considering Internet Explorer that I won't support- don't implement an XMLHttpRequest stable an mature API.

Currently, File object's methods like getAsBinary are deprecated and implemented in Firefox only, FormData object will be available from Firefox 4.0, Chrome and Safari don't support sendAsBinary, and so on: it seems the send method is the only one I can use without creating a full featured upload manager like Plupload or hacks that work for just a particular browser.

So I decided to use the send command, adding filename and stuff in the headers while keeping the file inside the body. Server side I'll grab the body and create a new Mojo::Asset instance, read the filename from headers and move the file into the directory I need.

What problems could I face waiting for a stable API?

 

Javascript:

_upload: function(/* object */ file) {
        //        summary:
        //                create and configure XHR to send file inside body

                xhr = new XMLHttpRequest();
                 
                // Manage some nasty effects
                xhr.upload.addEventListener("progress", dojo.hitch(this, this._uploadProgress), false);
                xhr.upload.addEventListener("load", dojo.hitch(this, this._uploadComplete), false);
                // After and only after event bindings the xhr call open
                xhr.open("post", "/file", true);
                
                xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
                xhr.setRequestHeader("X-File-Name", file.fileName);
                xhr.setRequestHeader("X-File-Size", file.fileSize);
                xhr.setRequestHeader("X-File-Type", file.type);

                xhr.setRequestHeader("Content-length", file.size);
                xhr.setRequestHeader("Connection", "close");

                // Start the voodoo
                xhr.send(file);
        },

Perl/Mojolicious:

# In the meanwhile, in sub called by a route...
sub upload {
        my $self = shift;

        # Read request data
        my $headers = $self->req->headers;
        my $body = $self->req->body;

        # Define the complete filename
        my $filename = $self->app->defaults->{the_path_you_want} . $headers->header("x-file-name");

        # Create a new file instance and add body
        my $asset = Mojo::Asset::File->new;
        $asset->add_chunk($body);
        $asset->move_to($filename);

        # I'm rubber you're glue!
        $self->render(json => {status=>"Love u Elaine!"});
}

onDrop doesn't work. Yes, it does.

You've probably forgotten to remove dragover and dragenter events as written in Specifying Drop Targets:

When the user releases the mouse, the drag and drop operation ends. If the mouse was released over an element that is a valid drop target, that is, one that cancelled the last dragenter or dragover event, then the drop will be successful, and a drop event will fire at the target. Otherwise, the drag operation is cancelled and no drop event is fired.

 

Just in plain html, this will work:

<div ondragover="javascript:return false;" 
    ondrop="javascript:console.debug('Yes, it does.');return false;"
>Test1</div>

while this won't:

<div  ondrop="javascript:console.debug('No, it does not.');return false;"
>Test2</div>