2012/06/03

Steps to shutdown windows

Using the current Windows 7 (previous versions is quite similar and everyone has learnt how to do it):

  1. Go to the Start or Windows button in the lower left corner.
  2. Click it
  3. Click the Shutdown button.
  4. Done!

Using the Windows 8 Release Preview

  1. Uh, there's nothing at the lower left corner?
  2. Anyway, move the mouse there, maybe there's a glitch in the graphics as everyone is used to know that there are strange bugs in Windows sometimes
  3. Clicking there doesn't do anything.
  4. Move to the really lower bottom corner
  5. A "Start" popup appers
  6. After hunting it a little you're finally able to click it
  7. Congratulations, you're now back to the "Windows Metro" screen.
  8. At least now you have an icon about your account on the top right
  9. Click it.
  10. In that dropdown select "Sign out"
  11. We're back to the start screen. Now we have the plug&screen icon. Click it.
  12. So now we can login again...
  13. But theres a Power icon at the bottom right
  14. Yeah, click it
  15. Now select "Shut down"
  16. Finally you got it!!!

Ok, there are some faster ways:

  1. Move your mouse to the bottom right corner
  2. Yes, I know that there's no hint that you should move your mouse there, but there isn't also any hint now about the bottom left corner.
  3. Some white icons appear above. Go to the last one, the one that looks like a gear.
  4. Now you see that it's titled Settings. Not promising, but please, click it.
  5. Now a pane shows up, there are two rows of icons below, and one of them is Power
  6. Click it
  7. Select Shut down
  8. You're done.

Using this method we have been able to halve the steps required to shutdown windows. Now you just have to print this short list and paste it at the right side of the monitor of anyone that has to use Windows 8.

That way Microsoft is saving some little pixels on the screen and you just have a little post it on your screen.

 

2012/05/23

Creating a button to insert some HTML in CKEditor

Sometimes it can be useful to have a toolbar button in CKEditor to insert a predefined block of HTML. The fact is that creating such option is quite easy, but for those that don't know much about javascript it might look more complex than it really is.
So this plugin allows to define as many new toolbar buttons as desired just by specifiying their properties in a config object.
After adding the "htmlbuttons" plugin you can add to your configuration a new entry "htmlbuttons" (yes, the same name I didn't want to think today). That entry must be an array of javascript objects, and each object has four properties; here's one example:
{
 name:'button1',
 icon:'icon1.png',
 html:'<a href="http://www.google.com">Search something</a>',
 title:'A link to Google'
},
First, the name for the command and button that you can use in the toolbar. Then the icon to use (place them in the plugin folder), next is the block of HTML that you want to insert, and finally a title to show up while hovering the button.
So now you can add those new buttons to your toolbar and when you reload the editor you can use those buttons to insert the HTML.
This sample shows the plugin in action with the default sample buttons (icons picked randomly from the Tango! project, if someone has some suggestions about better code samples and icons they're welcome).
The buttons (the three smileys) are from left to right:
  1. Insert a link pointing to Google
  2. Insert a 2x2 table
  3. Insert a nested list


Download:
Edit 2016: go to CKEditor plugins repository:
HTML Buttons plugin

2012/05/20

White list of elements and attributes for CKEditor

Sometimes you want to use CKEditor in a page where you can't fully trust the users, so they will have a restricted version with just some basic features: headings, bold, maybe links and images...

Of course it's easy to adjust the toolbar to show only those options, and with a good filter at the server you can be quite safe to accept the situation, but it would be even better if anything that will be stripped out at the server couldn't be added to the editor for example by pasting.

The fact is that using the dataProcessor of CKEditor it isn't too hard to setup something basic to perform the task: listen for each element and reject the ones that aren't whitelisted.

I've created a little plugin that does that job. It comes preconfigured with just some basic elements and attributes, but it's possible to modify that as it's just a simple javascript object that you can define in the CKEditor configuration.

Download: Whitelist plugin for CKEditor 1.1

Please, remember that you must use a filter at the server to perform at the very least the same filtering (or better) because this is not a real security option.

For PHP you can use HTML Purifier, in the case of Asp.Net previously the solution was the Microsoft AntiXss library but in January they released a broken version and haven't fixed it despite the complains. (Does anyone know an alternative solution)

 

This sample uses the default whitelist so it won't allow most HTML elements, and only basic attributes on links or images.

Edit: 20/01/13

Updated to version 1.1 to fix the attributes bug mentioned by Chris Hough

2012/05/01

Recipe: Live preview of CKEditor

Today we're gonna prepare a live preview of the contents edited with CKEditor.

A live preview with a WYSIWYG editor is not so important compared to other text-based editors, but anyways the behavior inside the editor might not match exactly the final output, so in those cases we can provide this option for those that want it.

Ingredients:

1 Instance of CKEditor

1 Preview container (for example a Div)

1 Copy of the onChange plugin

In case that you want to use this method with more than one instances, then you'll need as many preview containers as CKEditor instances you want to use.

Method:

1. Create the CKEditor instance in your page using any method that you like, and add the OnChange plugin to the list of extra plugins:

For example:

<textarea name='contents' id='contents'>This is an editor</textarea>
<script type='text/javascript'>
var config = { extraPlugins: 'onchange'};
CKEDITOR.replace('contents', config);
</script>

2. Now add add a little extra javascript to listen for changes in the editor instance and mirror those changes in the preview div, (based on this StackOverflow question)

CKEDITOR.on('instanceCreated', function (e) {
    e.editor.on('change', function (ev) {
        document.getElementById( ev.editor.name + '_preview').innerHTML = ev.editor.getData();
    });
});

That code will take care of any CKEditor instance and automatically copy its contents into the container with an id like the editor instance with an ending "_preview".

3. The only missing part is to initialize the preview before the user starts typing:

document.getElementById( e.editor.name + '_preview').innerHTML = e.editor.getData();

All the code together

<textarea id="contents" name="contents">This is an editor</textarea></p>
<div id="contents_preview"></div>

<script type='text/javascript'>

CKEDITOR.on('instanceCreated', function (e) {
    document.getElementById( e.editor.name + '_preview').innerHTML = e.editor.getData();
    e.editor.on('change', function (ev) {
        document.getElementById( ev.editor.name + '_preview').innerHTML = ev.editor.getData();
    });
});
var config = { extraPlugins: 'onchange'};
CKEDITOR.replace('contents', config);
</script>

This code in action:

 

 

 

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)