2011/10/14
Write Area 1.1 discussion
First, I've added a survey at the side pane. Of course, remember that we are talking just about the textarea replacement; if you're using it to replace an existing HTML editor then this survey isn't for you because there's no integrated mode in that situation. In the survey you should be able to check more than one option if you think that you would use more than one mode if all there were available.
So far the complains have been about the removal of the option to edit in a popup dialog, I didn't read anyone complaining about the removal of the bottom pane and at least that's a good thing. Can we all agree that the bottom pane isn't needed?
Then the dialog thing. Why are you having problems with the new mode and need the dialog back?
Please, write a comment here explaining (in a civilized way) why the integration mode doesn't work for you. I've got one comment about problems in tumblr.com, I'll try to check that tomorrow, although I'm not sure if I'll have enough time as I had planned other things to do.
But if you provide a list of things that don't work as expected then I can try to look at them and then fix them one by one or bring back the dialog if they can't be fixed in integrated mode.
Now it's your turn if you want a change in this extension.
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/22
ServerPreview plugin for CKEditor
Some years ago I created a plugin for FCKeditor to easily provide a preview of the contents that are being edited as they will look in the final site. That's specially important when you're using special markup in the editor that it's being replaced at the server by a widget or just some plain data.
The plugin is quite simple as the idea itself is simple: Get the current contents, and instead of opening a window with that HTML, post it to a custom page at the server and that page will be the one that can provide the proper context and show the HTML as it will be rendered in the final page.
This weekend I was tasked by Flatbooster GmbH to upgrade it so it can be used with CKEditor, and also perform some additions like controlling the size of the preview window.
The usage is quite basic, you just have to add it to your extraPlugins, specify the serverPreview_Url with your server script and use the posted "htmlData" variable. You can read the install.html to learn about other little options.
The plugin replaces the normal 'Preview' button, so there's no need to do anything to your toolbar.
The plugin can be downloaded here: Server Preview plugin for CKEditor 1.4.
Update 15/10/2011
Version 1.4, allow to use other CKEditor instances in the serverPreview_AdditionalFields setting.
2011/08/21
Is your clock adjusted correctly?
FoxToPhone now uses OAuth
In July I changed the authentication routines in FoxToPhone to start using OAuth like the latest version of ChromeToPhone. Using OAuth in a Firefox extension was a little harder at the start because I couldn't find something easy to use like the snippet that it's available for Chrome extensions.
Finally I took that code and adapted it to be able to use it the way that I wanted, without the need of a "background page", and reusing most of the code to avoid introducing any unexpected error.
This weekend this version 1.2 of FoxToPhone has been approved and now it's being updated as Firefoxes check for updates of the extensions. And despite all our hopes on the beta testers it's clear that not everything is OK.
Some people have been experiencing login problems with ChromeToPhone getting a hardly useful "redirecting..." message, and it's not clear what's going on, so it should be expected that some people would get also strange errors in Firefox with the new authentication. We fixed one or two such issues during beta testing, and today I've found another reason.
Your clock settings
Other people have already commented about it in that ticket, and I didn't look at it, but today one user reported login issues and after a little testing I found that while starting the authentication, one request is done that includes the current time, and in this case the request showed that it was one hour ahead of the current time. And the Google server replied with an status 400 meaning that the request was wrong.
So the user just moved his clock one hour back and then he was able to login and start sending the requests. Great!, we're moving ahead.
So if you get a response status 400, then you should check the settings on your control panel about the time zone and daytime savings are correct. Even if you see that the clock matches the one in your wrist, the computer also has additional information like the zone/country where you are, so when it tries to convert that local time to a global timestamp it will generate the wrong data if some of your info is wrong.
Testing time
This is a little script that tries to request the current time to the Yahoo servers and then checks it with your local time, if you see an error message then you should review the time settings in your computer
Hey Google, can you improve that error page?
Certainly returning "400 (Bad Request)" when the problem is the timestamp seems a little rude. It's clear that it's possible to check that the parameter is out of the allowed bounds, so in order to be helpful the error message should give a clearer hint that the problem is just that parameter. No real attacker is gonna try to send a request with that parameter wrong, it's just too easy to do it right, so the only people that would pass wrong data there are those users that don't realize that there's a problem with their clock settings.
Just as I've been able to mock a little script that performs a simple test, I guess that you should be able to provide at the very least the same check in a dedicated page and working a little further it should be able to guess more exactly if the problem is the time zone, the DTS or just the clock itself, something that shows the user the correct screenshots to check their settings etc...
2011/08/15
Location aware password policy
This morning I waked up and I was thinking about the password on my phone. I've always found it annoying having to retype it every now and them, specially if I'm at a place like my home where no one else can grab it.
So I thought that the device should be smarter, and I think that currently it should be possible to bring a little intelligence to these "smartphones". When I'm at a place that I have to configured to be trusted, then once I unlock the phone it should remain unlocked as long as it remains there or I don't explicitly lock it.
One easy way to achieve this would be to enhance the wifi manager, whenever I connect to a protected wifi with a password one new option is available: "this is a trusted site", by checking it the phone (or any similar mobile device) will remain unlocked and it's also possible to specify if the unlock should last some minutes (5 or 10, like when you are doing something with 2 devices, leave one apart and when you pick it up again it's locked so you waste time unlocking it), one hour or remain unlocked as long as you're connected.
That simple change could help lots of times, if we can use the devices at home without the need to retype the password (or whatever lock mechanism you've chosen), then we would be slightly happier and we could use slightly harder passwords for the moments when we're out of home.
Additional refinements could defined as an option to specify a coverage zone: instead of home, you're at work in your office, so you want the device to remain unlocked while you're there, but if you move out of the office then it should go back to the normal behavior.
I think that many people might not be using currently any password just to avoid the hassle of having to unlock his device every now and then, but if a system like the proposed in this post would be available then I would bet that they would be much happier to know that they have a secure device when they're walking down the streets while keeping the simplicity of an always available device at home without the need to retype the password at every moment.
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/07/31
Third version for seamless replacement of textareas
Sometime ago I wrote a script that allows to use CKEditor, and at the same time keep using older scripts existing on the page that relied on reading the textarea.value (or even writing it), without having to modify them to use the CKEditor API.
The initial version worked with Firefox and Internet Explorer 8, and shortly after I added some adjustments so that Opera was also supported.
Recently a comment in that second post stated that the script gave errors in Chrome, although it tries to detect if the API that I was using is supported, but of course, webkit guys decided to implement the API but not make it available for native properties. Their statement is that treating native properties as overridable would have a negative effect on performance, and as we all know it's much more important to have a fast browser than a browser that allows the developers to do new things; unless you're in their team then you can write a new API for whatever you need and everyone else should use this API because it will change the world, you'll no longer have to use Flash because now you have this API to overcome other problems that we didn't want to fix. Besides the bug tickets commented previously, here's another one: bug 36423
Ok, enough ranting.
As I said, I've worked to find out the problems and the funny fact about this new version is that it works in Chrome but it still fails in Safari 5.1. So you can use it in your site if can restrict the browser used by your users to IE8+, Firefox 3.5+ , Opera 10+, and Chrome 12+ (I don't really know the oldest version of Firefox, Opera and Chrome where this will work, but I wouldn't expect anyone to use old versions of those browsers)
// Modify the default methods in CKEDITOR.dom.element to use .nativeValue if it's available
CKEDITOR.dom.element.prototype.getValue = function()
{
if (typeof(this.$.nativeValue) == "undefined")
return this.$.value;
return this.$.nativeValue;
}
CKEDITOR.dom.element.prototype.setValue = function( value )
{
if (typeof(this.$.nativeValue) == "undefined")
this.$.value = value;
else
this.$.nativeValue = value;
return this;
}
// Hook each textarea with its editor
CKEDITOR.on('instanceCreated', function(e) {
if (e.editor.element.getName()=="textarea")
{
var node = e.editor.element.$;
// If the .nativeValue hasn't been set for the textarea try to do it now
if (typeof node.nativeValue == "undefined")
{
// for Opera & Firefox
if (!DefineNativeValue(node))
{
// IE8 & Webkit
if (!DefineValueProperty(node))
{
alert("Your browser is buggy. You should upgrade to something newer")
return;
}
}
}
node.editor = e.editor;
// House keeping.
e.editor.on('destroy', function(e) {
if (node.editor)
delete node.editor;
});
}
});
// This function alters the behavior of the .value property to work with CKEditor
// It also provides a new property .nativeValue that reflects the original .value
// It can be used with HTMLTextAreaElement.prototype for Firefox, but Opera needs to call it on a textarea instance
function DefineNativeValue(node)
{
if (!node.__lookupGetter__)
return false;
var originalGetter = node.__lookupGetter__("value");
var originalSetter = node.__lookupSetter__("value");
if (originalGetter && originalSetter)
{
node.__defineGetter__("value", function() {
// if there's an editor, return its value
if (this.editor)
return this.editor.getData();
// else return the native value
return originalGetter.call(this);
}
);
node.__defineSetter__("value", function(data) {
// If there's an editor, set its value
if (this.editor) this.editor.setData(data);
// always set the native value
originalSetter.call(this, data)
}
);
node.__defineGetter__("nativeValue", function() {
return originalGetter.call(this);
}
);
node.__defineSetter__("nativeValue", function(data) {
originalSetter.call(this, data)
}
);
return true
}
return false;
}
function DefineValueProperty(node)
{
var originalValuepropDesc = Object.getOwnPropertyDescriptor(node, "value");
if (!originalValuepropDesc)
return false;
// Safari doesn't allow to overwrite the property (but Chrome does)
if (!originalValuepropDesc.configurable)
return false;
Object.defineProperty(node, "nativeValue",
{
get: function() {
return ( originalValuepropDesc.get ? originalValuepropDesc.get.call(this) : originalValuepropDesc.value );
},
set: function(data) {
originalValuepropDesc.set ? originalValuepropDesc.set.call(this, data) : originalValuepropDesc.value = data;
}
}
);
Object.defineProperty(node, "value",
{
get: function() {
// if there's an editor, return its value
if (this.editor)
return this.editor.getData();
// else return the native value
return this.nativeValue;
},
set: function(data) {
// If there's an editor, set its value
if (this.editor) this.editor.setData(data);
// always set the native value
this.nativeValue = data;
}
}
);
return true;
}
// Detection, not really needed, but it can help troubleshoting.
if (Object.defineProperty)
{
// IE 8 and updated webkits
// Detect Safari
if (document.head)
{
var test = Object.getOwnPropertyDescriptor(document.head, "innerHTML");
// IE9
if (!test)
{
if (!DefineValueProperty(HTMLTextAreaElement.prototype))
alert("Unable to define property override on the prototype");
}
else
if (!test.configurable)
alert("Safari doesn't allow to overwrite native properties");
}
}
else if (document.__defineGetter__)
{
// FF 3.5 and Opera 10
// We try to get the innerHTML getter for the body, if it works then getting the value for each textarea will work
// Detect old webkits
if (!document.body.__lookupGetter__("innerHTML"))
alert("Old webkits don't allow to read the originalGetter and Setter for the textarea value");
}
else
{
// detect IE8 in compatibility mode...
if (document.documentMode)
alert("The page is running in Compatibility Mode (" + document.documentMode + "). Fix that")
else
alert("Your version of IE is too old");
}