2012/04/23

Hide dialog fields in CKEditor

Sometimes removing an element is not the right solution in a CKEditor dialog: the code might depend on it, or the layout will break too much if the elements are changed without taking care to adjust more things in the dialog, so the right choice at that point is to hide the element.

Of course, the CKEditor API allows such manipulations, but it's boring writing the same code "check if it's the dialog that we want, then get the tab, the field and hide it" ...

So I've added such option to the Configuration Helper plugin as version 1.2:

config.hideDialogFields

This entry uses the same sintax that the 'removeDialogFields' option. The difference is that some fields can't be removed easily as other parts of the dialog might not be ready and might try to always use it, generating a javascript error. In other cases the layout might be broken if the field is removed instead of hidden.
In those cases it's possible to hide the fields using this entry, and the preview in the image dialog is an example of such a field.

config.hideDialogFields="image:info:htmlPreview";

2012/04/16

Placeholder text in CKEditor

This weekend I worked on a little bunch of code to support the HTML5 "placeholder" attribute in CKEditor.
The idea is simple: show a little text instead of empty content when the editor loads for the first time, and make it disappear automatically when the content gets focus.
There are two main problems to do this correctly: find out when the editor is focused or blurred and avoid the placeholder text when the content is read by other scripts.
In theory to get the focus status it should be enough to handle the 'focus' and 'blur' events of the editor instance, but one problem is that when a dialog opens the content fires a blur, but in in this situation we don't want to insert again the placeholder text, so the event listener checks if a dialog has been opened before inserting the text.
Passing that check we must verify if the content is "empty" so we get the raw data of the editor and test it again "empty" strings like "<br>" "<p>&nbsp;</p>" and the like that can be generated by different browsers.
As I didn't want to handle yet another plugin I've included it in the configuration Helper plugin and released as version 1.1. Also, the correct name for this plugin is already being used by a plugin that ships with the default CKEditor install but that it's totally unrelated to this feature that plugin resembles more the mail merge fields from MS Word, but at the time that plugin was created I don't think that HTML5 existed.

Demo:

You can set the focus in and out of the editor, type and delete, etc... when the editor isn't focused and it's empty it will show the text that I've specified for the textarea placeholder: "Type here..." While in Source mode it tries to leave that task to the browser if it already supports this feature.


2012/04/07

Bug in the widget code of Twitter

Description

The profile widget from Twitter (https://twitter.com/about/resources/widgets/widget_profile) has a bug if you try to load and execute the code after the page has been loaded in IE.
In this case, the widget colors aren't shown as the stylesheets aren't appended to the head

To test it, click the button below and compare IE vs any other browser. The culprit is this code that doesn't take into account executing the code after the document has been loaded (http://twitter.com/javascripts/widgets/widget.js)

        // oh IE we love you.
        // this is needed because you can't modify document body when page is loading
        if (!browser.ie || isLoaded) {
          append();
        }
        else {
          window.attachEvent('onload', function() {
            isLoaded = true;
            append();
          });
        }
Fix: change isLoaded to (document.readyState == "complete")
      twttr.css = function(rules) {
        var styleElement = document.createElement('style');
        styleElement.type = 'text/css';
        if (browser.ie) {
          styleElement.styleSheet.cssText = rules;
        }
        else {
          var frag = document.createDocumentFragment();
          frag.appendChild(document.createTextNode(rules));
          styleElement.appendChild(frag);
        }
        function append() {
          document.getElementsByTagName('head')[0].appendChild(styleElement);
        }

        // oh IE we love you.
        // this is needed because you can't modify document body when page is loading
        if (!browser.ie || document.contentReady == 'complete') {
          append();
        }
        else {
          window.attachEvent('onload', append);
        }
      };
(and the anonymous function might not be no longer needed)