How to add a second taskbar to your other monitor in twinview in ubuntu

I have an Ubuntu workstation at work with a nvidia graphics card and dual monitors in Twinview mode (meaning, they act like one large desktop, except that the full screen apps take only one monitor, if I got it right).

Anyway, I wanted to add a taskbar to my other monitor – mainly because I wanted a second taskbar with the window list. My main problem was that I had no apparent way to add any panels to the second monitor – they all ended up on the primary.

Well, here is how one can do it:

1.) Right click on anywhere on the old panels and  click “New Panel”

2.) hold down ALT + Drag the new panel to any monitor/location.

3.) Right click on the new panel and click “Add to Panel”

4.) Now you can add the window list (Right-click -> Add -> Window List) or anything you need here.

5) Click Close.

Posted in linux | Tagged dual-monitor, taskbar, twinview, ubuntu | Leave a comment

World, meet Isaac! Isaac, meet World!

I’ve just been given an amazing present and a huge responsibility: Isaac. Isaac is a cactus, I don’t know the sort yet, but I will find out, I hope. Now I need to take care of it and make sure it grows old :-)

Anyway, here is a low quality photo I made with my cellphone. I hope you like Isaac!

Isaac the Cactus

Isaac the CactusIsaac the Cactus

Posted in General | Tagged cactus | Leave a comment

Baked Catfish with Mushroom Sauce Recipe in JavaScript

This is a small demo why programmers can usually get to be good cooks! Here is how you cook a nice catfish in some mushroom and wine sauce in JavaScript.

Disclaimer: I’m not a JavaScript ninja, and this was written in parallel!! to making the actual dinner, so I know it could be vastly improved. You should probably not follow the JavaScript examples from the script, especionally the pausing time! I just didn’t have the time to implement proper event engine that would run on its own.

First, the last part of the script (link) (which runs without errors in node.js v0.6.5 and Chrome Developer Console):

// Lets cook!!
ingreedients.push({"catfish filets": "2"});
ingreedients.push({"soy souce": "1 tsp"});
ingreedients.push({"pepper": "2 pinch"});
ingreedients.push({"wine": "1/2 cup"});
ingreedients.push({"pepper": "1 pinch"});
ingreedients.push({"salt": "1 pinch"});
ingreedients.push({"sliced mushrooms": "2 cups"});
ingreedients.push({"garlic": "2 pcs"});
ingreedients.push({"olive oil": "2 tsp"});
pan.heat(180);
pan.add(ingreedients.next());
pan.heat(90);
pan.add(ingreedients.next());
pan.heat(120);
pan.add(ingreedients.next());
pan.braise();
pan.add(ingreedients.next());
pan.add(ingreedients.next());
pan.simmer(10);
pan.add(ingreedients.next());
pan.simmer(6);
bakingPan.heat(120);
bakingPan.add(ingreedients.next());
bakingPan.add(ingreedients.next());
bakingPan.add(ingreedients.next());
bakingPan.bake(25);
bakingPan.serve();
console.log(log);

The last part – console.log – outputs all this stuff:
Warming up pan for 180 seconds…
…done
Adding 2 tsp olive oil to pan.
Warming up pan for 90 seconds…
…done
Adding 2 pcs garlic to pan.
Warming up pan for 120 seconds…
…done
Adding 2 cups sliced mushrooms to pan.
Braising olive oil, garlic, sliced mushrooms…
…done
Adding 1 pinch salt to pan.
Adding 1 pinch pepper to pan.
Simmering ingreedients olive oil, garlic, sliced mushrooms, salt, pepper in the pan for 10 minutes…….
…done
Adding 1/2 cup wine to pan.
Simmering ingreedients olive oil, garlic, sliced mushrooms, salt, pepper, wine in the pan for 6 minutes…….
…done
Warming up pan for 120 seconds…
…done
Adding 2 pinch pepper to pan.
Adding 1 tsp soy souce to pan.
Adding 2 catfish filets to pan.
Baking ingreedients in the oven (olive oil, garlic, sliced mushrooms, salt, pepper, wine, pepper, soy souce, catfish filets) for 25 minutes…….
…done
The dish is ready. Bon apetit!)


Of course, here’s the initialization stuff: 

var log = 'Replaying log: ';
var ingreedients = [];
ingreedients.next = function () {
  return ingreedients.pop();
}

var pan = new Object();
pan.add = function (ingreedient) {
  var i;
  if (!this.stuff) {
    this.stuff = '';
  }
  for (i in ingreedient) {
    if ('' != this.stuff) {
      this.stuff = this.stuff + ', ';
    }
    this.stuff = this.stuff + i;
  }
  console.log('Adding ' + ingreedient[i] + ' ' + i + ' to pan.');
  log += '\r\nAdding ' + ingreedient[i] + ' ' + i + ' to pan.';
}

pan.braise = function(seconds) {
  var start = new Date(), end, milis;
  // bad bad mojo but no time for writitng asynchronous calls and parallelization and stuff now
  console.log('Braising ' + this.stuff + '...');
  log += '\r\nBraising ' + this.stuff + '...';
  if (seconds < 40) {
    milis= seconds * 117;
    console.log('(I will compress time a little bit, of course)');
  } else {
    milis = 4000;
    console.log('(I will compress time a little bit, of course)');
  }
  do { end = new Date();}
  while (end - start < milis);
  console.log('...done');
  log += '\r\n...done';
}
pan.heat = function(seconds) {
  var start = new Date(), end, milis;
  // bad bad mojo but no time for writitng asynchronous calls and parallelization and stuff now
  console.log('Warming up pan for ' + seconds + ' seconds...');
  log += '\r\nWarming up pan for ' + seconds + ' seconds...';
  if (seconds < 40) {
    milis= seconds * 117;
    console.log('(I will compress time a little bit, of course)');
  } else {
    milis = 4000;
    console.log('(I will compress time a little bit, of course)');
  }
  do { end = new Date();}
  while (end - start < milis);
  console.log('...done');
  log += '\r\n...done';
}
pan.simmer = function (minutes) {
  var start = new Date(), end, milis;
  // bad bad mojo but no time for writitng asynchronous calls and parallelization and stuff now
  seconds = minutes * 60;
  milis= seconds * 1000;
  console.log('Simmering ingreedients ' + this.stuff + ' in the pan for ' + minutes + ' minutes...');
  log += '\r\nSimmering ingreedients ' + this.stuff + ' in the pan for ' + minutes + ' minutes...';
  var tickerTime = 600;
  var ticker = start;
  var breakAt = 2500;
  do {
    end = new Date();
    if (end - start > breakAt) {
      console.log('Compressing time a bit..........');
      start = end + 2500;
    }
    if (end - ticker > tickerTime) {
      ticker = end;
      console.log('.');
      log += '.';
    }
  }
  while (end - start < milis);
  console.log('...done');
  log += '\r\n...done';
}
pan.bake = function (minutes) {
  var start = new Date(), end, milis;
  // bad bad mojo but no time for writitng asynchronous calls and parallelization and stuff now
  seconds = minutes * 60;
  milis= seconds * 1000;
  console.log('Baking ingreedients in the oven (' + this.stuff + ') for ' + minutes + ' minutes...');
  log += '\r\nBaking ingreedients in the oven (' + this.stuff + ') for ' + minutes + ' minutes...';
  var tickerTime = 600;
  var ticker = start;
  var breakAt = 2500;
  do {
    end = new Date();
    if (end - start > breakAt) {
      console.log('\r\nCompressing time a bit..........');
      start = end + 2500;
    }
    if (end - ticker > tickerTime) {
      ticker = end;
      console.log('.');
      log += '.';
    }
  }
  while (end - start < milis);
  console.log('...done');
  log += '\r\n...done';
}
pan.serve = function() {
  console.log('The dish is ready');
  log += '\r\nThe dish is ready. Bon apetit!)';
}
var bakingPan = new Object(pan);
bakingPan.stuff = '';

Posted in General | Tagged catfish, javascript | Leave a comment

A smallish bitbucket trick: handling more then one account

Today I had to think on how to handle two separate bitbucket.org git accounts without conflicts.

I have my private bitbucket account: zladuric. There I have some play-code – thing to play with.  I also have a company bitbucket account: zduric. There’s the company central-sort-of code repository.

Now, I can checkout something from my company account:

git@bitbucket.org:zduric/myoffice.git

I need to enter my details, username, email, password and all. But now I also have a private account.

git@bitbucket.org:zladuric/jam.git

How to handle that?

Well, that’s where SSH comes in. I already use SSH’s config file to handle authentication. I have a ssh key and config section in my .ssh/config, and I use it like this:

Host bitbucket.org
        User git
        HostName bitbucket.org
        PreferredAuthentications publickey
        IdentityFile ~/.ssh/id_rsa

Now, I just added another section, to ssh config file, with my git-specific key:

Host bitbuck
        User git
        HostName bitbucket.org
        PreferredAuthentications publickey
        IdentityFile ~/.ssh/git_id_rsa

There is one last detail:

When checking out private files, I use

git@bitbucket.org:zladuric/jam.git

And for company repo, I can safely use:

git@bitbuck:zduric/myoffice.git

SSH can handle the rest. Pretty nifty, huh?

Posted in linux | Tagged bitbucket.org, git, ssh | Leave a comment

Gmail Cheat Sheet (iliti Gmail šalabahter)

Ovdje se nalazi verzija za ispis Googlove Help stranice za Gmail.

Tražio sam način kako u gmailu nešto napraviti automatski i u googlanju sam naletio na tu stranicu. Pa sam si ju isprintao i zalijepio na stol, dok ne zapamtim one najvažnije.

Posted in General | Leave a comment

Vim search and replace throughout the file

Zlatko,

When you want to search and replace every instance of a string1 with string2 in a file, don’t look up the web to get the correct syntax for the milionth time.

Just write down:

:%s/string1/string2/g

Sincerely,

Zlatko

Posted in linux | Leave a comment

YUI handlers and their scope

I’m creating an Alfresco dashlet right now, which has a YUI Button in it, which in turn creates a YUI DataSource and invokes a YUI Dialog, which gets created and also renders a nice YUI DataTable based on the datasource above.

Now, I’ve ran into a question: when I wanted to “handle” the submit from that dialog, I wanted to reach the datasource. But the handler functions’ this was the Dialog instance, not the object holding it (and the datasource). So I googled and I found out how to do it.

Instead of

var dialogConfig = { buttons: [
{"text": "OK", handler: handleSubmit, isDefault: true},
{"text": "Cancel", handler: handleCancel}
]};

you give the config objects’ handler property another object:

{fn:this.handleSubmit, obj: this, scope: this}

This way you pass the scope and the object (which doesn’t have to be this, by the way, it can be something custom).

And then I remembered that in YUI Ajax callback configuration, you also use this format. Again YUI proves to be really well thought! So I’m going to use it more from now on, I think.

 

Posted in YUI | Leave a comment

Alfresco 3 Cookbook review

I recently got a e-copy of a book “Alfresco 3 Cookbok“, with “over 70 recipes for implementing the most important functionalities of Alfresco”. The book is one of few good PacktPubs’ publishings about this open-source document and records management and collaboration platform. It was written by Snig Bhaumik, the Technical Director at InfoAxon Technologies Ltd in India. The recipes are supposed to help new Alfresco administrators and developers accomplish common tasks. The tasks described go from setting up Alfresco from ground up, basic and a bit advanced administrative management of the installation, and further into customizing and developing Alfresco. Since I’m developing a platform based on Alfresco 3 Comunity edition, I was looking forward to the book. It’s based on Alfresco 3.3. At the time I got it, the 3.4 version of Alfresco was long in production already, but that’s no problem. All of the 3.x versions are pretty similar as it is, and 3.3 and 3.4 only have minor differences. But for people starting with the new installation, I suggest using Alfresco 4.0. The Alfresco developers made quite a few changes and it would be really worth it.
The book is set up in 14 chapters. As usual, there’s an introductory chapter. What is Alfresco and what do you use it for? If you didn’t know that, and picked up the book by accident, you’ll find out more about it here. You also find the first recipes here. There are instructions on how to download and install Alfresco on Windows and Linux. The setup instructions are detailed and you can blindly follow without really knowing what you’re doing.

Then come chapters 2 and 3. These brought a little dissapointment for me. There were recipes for most basic of actions – how to create a user, how to upload documents to the repository, all of the really elemental features. I thought, “hey, you really have to be stupid to install and use a document management platform and then to have to read a book to put a document in it”. Chapters 4 and 5 were a bit more advanced, but it still wasn’t interesting to me. Again I thought to myself, “Yeah, right, now you’re telling me! Where were you when I was just starting with Alfresco two years ago?”. But then it hit me. If I had this book two years ago, I would be far further then I am now. Then I started reading more cautiously. Recipes were describing some really simple tasks, as well as some a bit more advanced.

How to create a document, how to copy it, how to create a rule or change users’ password. These are all actually excellent recipes! You could follow them without ever hearing about Alfresco before! Further chapters became more and more interesting – there are recipes on content model, JavaScript and Javascript consoles, webscripts, and all of those don’t go into theory much. They just tell you how you can accomplish a task with Alfresco. As I was reading, I found more and more examples that I could use. For example, the (freely available) Chapter 8 describes how you can work with javascript files. It offers steps on accomplishing a simple task yourself. But it also gives an overview of much wider functionality you can use.

After reading it, I think that the book is well written. There are good, simple to follow, step-by-step instructions on how to work your way through the Alfresco, from installation and installation, to customization and development. It mentions and somewhat explaines advanced Alfresco features. It gives an overview of options, features, posibilities of Alfresco. On the downside, to really understand some of those, you need to be experienced with alfresco – and in that case you likely won’t be going for this book. Also, it’s based on version 3.3, which is a bit old now and I think that new Alfresco users should really go for version 4 at this time, if possible.

If you’re just starting with Alfresco, especially if you’re comming into Alfresco 3.x environment, I highly recommend this (or any) book on Alfresco. You should take two-thee days to just sit with the book and work your way through. What you end up with is a knowledge and skillset to use Alfresco and basic understanding of its posibilities.

Posted in Alfresco | Tagged alfresco, book, ebook | Leave a comment

Alfresco document library path encoding

I am developing a Share dashlet that should point the user to some document library spaces in Alfresco. You need to doubly-encode the path:

encodeURIComponent(encodeURIComponent("My local path/With croatian letters/šđćčž"));

Why is this? Because if you only encode once, the spaces and slashes will be encoded – but the extra characters will be encoded with those special characters and the document library filter won’t be able to get it. I assume that this is because the doclib filter will take your given path, then call a remote webscript with it to get the space contents. But if your name has special characters, this doesn’t get decoded well on the way.

Standard disclaimer: this post is only for purposes of me having to write it down and then possibly remember it better next time.

Posted in Dashlets, Share | Leave a comment

Why won’t my dashlet fire?

I was developing a new dashlet for my clients’ Alfresco installation, MyOffice.

So I had a client-side javascript where I extended the Alfresco.dashlet class (that’s how I construct my objects lately).  So my code was something like…

(function () {
/*blah*/
Alfresco.dashlet.ChangeRequestClient = function(htmlId) {
return Alfresco.dashlet.ChangeRequestClient.superclass.constructor
.call(this,
"Alfresco.dashlet.ChangeRequestClient", htmlId, ["json", "button", "menu"]);
}
YAHOO.extend(Alfresco.dashlet.ChangeRequestClient,
Alfresco.component.Base,
{
/*blah*/
onReady: function blah (htmlId) {
/*blah till the end*/
})();

I was constructing this, the script was firing up, the constructor did its job, but my onReady function didn’t work. So I checked and checked and checked. And what I found was that I was calling the script with

new Alfresco.dashlet.ChangeRequestDashlet();

And now my onReady was waiting for undefined or something to be ready, which was never.

Lesson learned:

Always call your dashlets with “${args.htmlid}” parameter!

 

 

Posted in Alfresco, Dashlets | Tagged alfresco, dashlet, onready, yui | Leave a comment