Showing posts with label Extension. Show all posts
Showing posts with label Extension. Show all posts

2011/09/03

Toolbar buttons in Writearea

Since version 1.1 it's possible to configure which buttons do you want to use in the toolbar of Writearea. There are in fact two toolbars and you can switch between them with a custom button.

The way to define the buttons is to use the preferences pane of Writearea and put the array of buttons in the corresponding input fields. Note that to try to help a little, you don't need to put the outer [ and ], just the groups separated by commas and with a '/' if you want to start a new row.

These are the default values for each toolbar:

Full Toolbar:
['Save'], ['SaveFile','LoadFile'], ['Source'],['Cut','Copy','Paste','PasteText','PasteFromWord'],['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],['ShowBlocks','Maximize'],['Image','Flash','Table','HorizontalRule','SpecialChar','Iframe'],['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],['BidiLtr', 'BidiRtl' ],'/',['Styles','Format','Font','FontSize'],['Bold','Italic','Underline','Strike'],['TextColor','BGColor'],['NumberedList','BulletedList','-','Outdent','Indent','Blockquote','CreateDiv','Code'],['Link','Unlink','Anchor'],['SwitchToolbar']

BasicToolbar:
['Undo','Redo'], ['Bold', 'Italic', '-', 'NumberedList', 'BulletedList', '-', 'Link', 'Unlink'],['SwitchToolbar']

Most of the commands are the ones available on the default CKEditor install, I don't know if there's any listing of the meaning of all of them, the best thing that I can think of is the user's guide, but it doesn't clearly link the button names with its action.

But beyond those common buttons, there are a few ones with special meaning here:

Custom buttons

'Save': It's available only while in the dialog popup, it will save the content of the editor to the original element. When the editor is integrated into the page you should use the existing save button provided by the page, that way there won't be any problem due to extra event handlers or differences between Save draft, Publish and Preview buttons of the page.

'SaveFile', 'LoadFile': These two options allows you to save/load the content of the editor to a file in your computer, just in case the page doesn't have any auto-save feature or you want to use something more than once.

'SwitchToolbar': These button allows you to switch between the basic and the full toolbar. I would suggest you to use the basic toolbar by default and only switch to full toolbar when there's something extra that you need at that moment. And of course, adjust each toolbar so the basic includes the commands that you usually need and the full toolbar doesn't includes buttons that you know you'll never use.

'Code': it's the SyntaxHighlight plugin available here. I made some little adjustments, but someday I might have to perform some bigger fixes to improve it and make it easier to use.


 

2011/08/13

Upcoming changes for Write Area

It has been a long time, but these days I'm going to try to push a new stable release of Write Area. It will be mostly an upgrade to the current CKEditor 3.6.1, but at the same time I'm gonna try to finish some code that it's available in the betas and provide a simplified version.

The main change will be the removal of the option to select whether to open the editor in a bottom pane or in a dialog. My plan is to finish the behavior of the new "integrated" mode, so that whenever you select to use Write Area with a normal textarea then it will be replaced by a CKEditor instance integrated in the same page. This is similar to what the "bottom pane" provides, but with the advantage of being able to create more than one instance, and the rest of the scripts of the page can get direct access to the contents as if nothing had happened.

If you try to use instead an existing editor that isn't too compatible with the current Firefox or it's missing features, then the editor will be launched in dialog mode. The plan is to do this automatically without the need to select a preference.

Why?

First: Simplify options.
More options means more testing, harder for the user as he has to think about what's better. I can't claim that I know better than him what's better for him, but I know what's more job for me.

Second: Try to avoid future problems due to changes in Firefox.
The bottom pane is a "XUL overlay", that means that it's somehow quite integrated with Firefox, and in the future the plan is to try to move as much extensions as possible to the Addons-SDK. That means that such integrations might be harder or just impossible. If I start removing these blocks I can try to test if it's possible to port the extension to this new world. Anyway that goal is quite far away as I've stated previously that I won't start using the Addons SDK as long as they require to install Python or any other third party libreary/compiler/whatever.

Third: Other browsers.
By using a simpler approach it's possible to create a Write Area version for Chrome, and although I don't use it I understand that other people do, so if there are just a few differences then I can provide a port of the extension. It won't be as feature rich as the Firefox version, but at least is something that people can use.

Conclusion

If you have a strong reason to believe that I'm making a mistake the I would like to hear your concerns. Otherwise I'll go ahead and release the update when it's ready

2011/04/09

New beta for WriteArea with CKEditor 3.5.3

Following the release this week of CKEditor 3.5.3, I've updated the WriteArea extension for Firefox to this latest version to include all the bug fixes and enhacements that have been worked on since the last release (check the change log, it's quite a long list as it's usual for every CKEditor release)

In this version, the only patch applied to the core is the latest from this ticket that allows a new button that you can use to switch toolbar on the fly.

The size of the extension has grown again a little due to several languages that have been updated since the previous checks that I did and so I've restored as new they can be correctly used to localize your CKEditor and not have part of the texts in your language and the other half in English.

Direct download link: WriteArea 1.1beta4

2011/02/06

Creating extensions for each browser

These last days I've tried to create a similar extension for each browser, and this is a little recap of the first differences among them. A page with a full list of differences can be found in the State of the Add-on Developer Union

Firefox

In Firefox there are two options:

  1. Create the extension using the "classic" way that goes back to the very beginning and provides full access to anything in Firefox, you can customize it in any way that you like.
  2. Use the new Add-Ons SDK, only for Firefox 4. These ones doesn't require a restart and it's supposed to be future-proof.

In order to create a classic add-on you can get a skeleton using the Add-on Builder . There are lots of info about how to create these extensions and the API that they can use, and to start creating an Add-on the first step is this page to setup the environment. All you need is a text editor, some patience and be careful following the instructions. You can then configure Firefox to load the extension from the disk but when you make changes to the code you'll have to use an extension to force a reload of all the Firefox code or directly restart it; not nice.

To get started building add-ons with the new SDK, check the tutorial.
First problem: You are required to have Python installed.
What?
I'm so tired of projects that say: you have to install this or that or all of these projects just to get started.
What's so special about Python and the SDK environment that can't be done inside Firefox?
Why should I have to keep the list of instructions instead of being able to click on some buttons "Add extension", "Run tests", "Install", "Reload", etc...
Big boo here.
Maybe they want us to use wget instead of Firefox if they think that command line is so nice.

Anyway, I gave it a go in the Mac (I won't bother trying to install python in windows, it has already too many SDKs there for this and that), and so I followed the basic example, while trying at the same time to adjust it to my goal, I add the files, and when I do the "cfx run" then I get a cryptic error "raise ValueError('invalid resource hostname: %s' % name)". WTF? check again that I haven't done anything too weird. Nops. Then put back exactly the sample code. Nops. Search for the message. Bingo!, although there's no warning about this in the tutorial, you CAN'T use uppercase letters in the folder name. Hello Mozilla, it's 2011, I thought that the problems with uppercase and lowercase were gone long ago since MS-DOS. Why aren't your wonderful Python scripts able to deal with them?
Another big fail.

As a summary: I got a bad taste of the Add-ons SDK. When they put forward something that isn't oriented to Python lovers I might test it again (please note that I haven't even tested the API, just the environment makes me go back to keep using the classic method)

Chrome

It seems that there's a lot of work going on here in order to provide a very complete API for the extensions as well as good documentation and lots of examples. You can see a very basic one here and everything is quite easy to follow. Given the fast path that it's set on the release of new Chrome versions we can expect that this trend will continue and that they will add missing features to make some tasks even easier.

The only thing that you need is a text editor and Chrome, and by following the instructions you can get it working. It's not so powerful as the classic extensions in Firefox, but it's really easy to start creating an extension and there are lots of examples to check how they work.

Safari

It seems again that there's plenty of documentation at a central place, but just in the first page there's something strange:

Important: To develop extensions for Safari, you need to sign up for the Safari developer program online, at http://developer.apple.com. You need a signed certificate before your extension can be installed.

Uh?
So to create an sample extension in my own computer I need a certificate?

Ok, this shows again that Apple is a control freak. Why do I have to register to get an Apple ID and then get enrolled into a "Safari developer" program so that I can finally request a signing certificate, just to create a test extension? I can understand that in order to deploy it I might need to sign it, but I really should be able to create an extension for myself without the need to sign two looong agreements with Apple (I'm not sure if there was a paragraph about my first newborn there)

Anyway I go ahead and get a certificate in the Mac, and then it seems to work, but I would like to keep the development environment in Windows, so I try to install the downloaded *.cer there but anyway Safari keeps saying that there's no signing certificate installed. After a little while and some digging I realize that I must export the private signing key from the Mac KeyChain to Windows and once I installed it there Safari started working.

In some regards this might be the simpler interface of all the browsers in order to create an extension as you get a dialog to setup the basic configuration of the extension instead of editing them in a text file. The way that the code is setup is similar to Chrome (and Opera): background pages, injected scripts, so porting from Chrome wasn't a hard task.

As it happens with almost everything Apple does, if you are satisfied with what they offer, they try to make it quite easy, but if you want something extra then it's a no go.

Opera

I started checking the Opera API with the very first builds where they started adding support for extensions. In those days the API wasn't complete, there were a bunch of things that didn't work at all, so due to my hurry to test it I became a little frustrated because there were so many things missing, there was almost no documentation at the moment so it required a lot of effort to try to make something work because the examples were quite basic.

Now they have improved everything a lot, the behavior is similar to Chrome and Safari, but this is still a fresh SDK, so there are still missing features available in other browsers. They have written now lots of documentation and I guess that very shortly it should be quite easy to port an extension between Opera, Chrome and Safari due to the convergence of APIs that the developers find useful.

For the moment Opera it's lacking an API call similar to the ones that I've used for the other browsers so I will put the extension for browser at rest waiting for them to include them instead of struggle again and get tired of finding that it's not possible in any way.

2010/08/08

Compressing a folder with Firefox nsIZipWriter interface

Writing an extension in Firefox is usually done in Javascript, but instead of using just the classic features available to a web page, there are many others that are exclusive to the inner workings.

One of those features introduced in Firefox 3 is nsIZipWriter; with this interface it's possible for an extension to create or modify a zip archive without the need of any external program.

And that looked perfect for some code that I was planning so I looked at it and after reading the docs page and a little testing I created this zipFolder function that takes as arguments a nsFile object that points to the folder that you want to compress, and the second argument is a callback function.

It takes the contents of that folder (including subfolders thanks to the addFolderContentsToZip recursive function) and compress them in a temporary file that you can use afterwards as it's the parameter passed to the callback function.

The only "problem" is that there is no progress notification about the task, I've configured it to do the job asynchronously (that's why it uses a callback to be notified of the end of the task), but that doesn't allow to set any progress listener or use an interval to check for the number of bytes processed.

/* Zipping functions */
const PR_RDONLY      = 0x01;
const PR_WRONLY      = 0x02;
const PR_RDWR        = 0x04;
const PR_CREATE_FILE = 0x08;
const PR_APPEND      = 0x10;
const PR_TRUNCATE    = 0x20;
const PR_SYNC        = 0x40;
const PR_EXCL        = 0x80;

/**
* folder is a nsFile pointing to a folder
* callback is a function that it's called after the zip is created. It has one parameter: the nsFile created
*/
function zipFolder(folder, callback)
{
 // get TMP directory  
 var nsFile = Cc["@mozilla.org/file/directory_service;1"].  
   getService(Ci.nsIProperties).  
   get("TmpD", Ci.nsIFile); 

 // Create a new file
 nsFile.append( folder.leafName  + ".zip");
 nsFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);  
 
 var zipWriter = Components.Constructor("@mozilla.org/zipwriter;1", "nsIZipWriter");
 var zipW = new zipWriter();
 
 zipW.open(nsFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
 
 addFolderContentsToZip(zipW, folder, "");
 
 // We don't want to block the main thread, so the zipping is done asynchronously
 // and here we get the notification that it has finished
 var observer = {
  onStartRequest: function(request, context) {},
  onStopRequest: function(request, context, status)
  {
   zipW.close();
   // Notify that we're done. 
   callback(nsFile);
  }
 }

 zipW.processQueue(observer, null);
}

/**
* function to add the contents of a folder recursively
* zipW a nsIZipWriter object
* folder a nsFile object pointing to a folder
* root a string defining the relative path for this folder in the zip
*/
function addFolderContentsToZip(zipW, folder, root)
{
 var entries = folder.directoryEntries;  
 while(entries.hasMoreElements())  
 {  
  var entry = entries.getNext();  
  entry.QueryInterface(Ci.nsIFile);  
  zipW.addEntryFile(root + entry.leafName, Ci.nsIZipWriter.COMPRESSION_DEFAULT, entry, true);
  if (entry.isDirectory())
   addFolderContentsToZip(zipW, entry, root + entry.leafName + "/");
 } 
}

Hope you find it useful, it's mostly putting together some sample code and doing some tests, but if you are trying to do it and have some problem it's usually nice to find some code that works as it might be the hint to understand your problem.