Built-in Dialogs

A straightforward way to interact with the user is through dialogs. Cloud9 comes with a set of common dialogs that will make it easy to add basic interaction to your plugin. The set of common dialogs is used throughout Cloud9 by the core plugins and using them will give the user a consistent experience.

This guide will go over each of the common dialogs and provide code examples accompanied by screenshots to get you started using dialogs. It's also pretty easy to create dialogs of your own. We'll add a guide on that in the future. For now use the mailinglist to ask questions or check out the source.

dialog.alert

Use the alert dialog to notify users of something that happened, similar to the native window.alert() function in the browser. The user can close the window by clicking an OK. You can set the title a heading and the body of the window and use both plain text and html for the content.

Here's a simple example

var alert = imports["dialog.alert"].show;
alert("Success!");

And one a bit more elaborate:

alert("Download", 
    "Download success!", 
    "You have successfully download this file",
    function(){
        console.log("The user has closed the alert");
    });

You can also show a "don't show this message again" checkbox that will allow the user to silence future messages. In the example below, we're using the settings plugin to store the choice of the user.

var alertDialog = imports["dialog.alert"];

if (settings.getBool("user/my-plugin/@no-alert"))
    return;

alertDialog.show("Terminal", 
    "Do you want to close this terminal?", 
    "Closing the terminal will stop <strong>all the running processes</strong> in that session.",
    function(){
        if (alertDialog.dontShow)
            settings.set("user/my-plugin/@no-alert", true);
    }, {
        isHTML: true,
        showDontShow: true
    });
785785

dialog.confirm

Use the confirm dialog to ask users of to confirm an action, similar to the native window.confirm() function in the browser. The user can confirm by clicking the OK button or pressing 'Cancel' otherwise. Similar to the alert dialog, you can set the title a heading and the body of the window and use both plain text and html for the content.

var confirm = imports["dialog.confirm"].show;

confirm("Save changes?",
    "Do you want to save these changes?",
    "The file 'stuff.js' has changed. Click OK to save the changes?",
    function(){
        console.log("The user confirmed");
    },
    function(){
        console.log("The user cancelled");
    });
735735

dialog.question

Use the question dialog to ask yes/no questions to users. The dialog optionally also allows yes to all and no to all. Similar to the alert dialog, you can set the title a heading and the body of the window and use both plain text and html for the content.

var question = imports["dialog.question"].show;

question("Editor",
    "Would you like to delete the selected items?",
    "Click Yes to delete the selected items",
    function(){
        console.log("The user clicked Yes");
    },
    function(){
        console.log("The user clicked No");
    });

Here's a more complex example enabling the yes to all buttons:

var questionDialog = imports["dialog.question"];

questionDialog.show("my-plugin",
    "The file 'blah.js' has changed.",
    "Would you like to update 'blah.js' to the latest version?",
    function(all){
        var button = "Yes" + (all ? " to All" : "");
        console.log("The user clicked " + button);
    },
    function(all){
        var button = "No" + (all ? " to All" : "");
        console.log("The user clicked " + button);
    }, {
        all: true,
        cancel: true
    });

The question dialog supports the dontAsk, similar to the dontShow in the alert dialog. The question dialog has several other features and APIs that you can find in the reference guide.

For a complex example check out how the question dialog is used in the watcher gui plugin

735735

dialog.error

Use the error dialog to notify users of an action that has failed. The error dialog display a small banner at the top of the page that can automatically hide after a while. It can also be closed by the user.

var showError = imports["dialog.error"].show;

if (err) 
    return showError("Something terrible has happened!");

You can set the 2nd argument to the amount of milliseconds that you'd like the error to be shown to the user. By default this is set to 15000 (15 seconds).

735735

dialog.notification

Use the notification dialog to notify users of a special state that the IDE is in. The notification dialog display a space at the upmost top of the UI of an arbitrary height that is very hard to miss by the user. Only use the notification dialog for very important states. For instance, we use it for the Read-Only mode and the Debug mode of the IDE. The user can optionally close the notification. You are solely responsible for the styling of the notification through css.

var notify = imports["dialog.notification"].show;

var showCloseButton = true;
notify("<div class='mybar'>Consider yourself notified!</div>", showCloseButton);
735735

notification.bubble

Another type of notification is the notification.bubble which acts similar to growl on OSX, displaying a bubble in the top right corner of the screen.

var bubble = imports["notification.bubble"];

bubble.popup("The user just came online", true, function(){
    console.log("The bubble was closed");
});
735735

Note that only 4 bubbles are allowed on the screen at one time and that the user can configure their IDE to not show the bubbles at all.

dialog.filechange

Use the filechange dialog to notify a user of changes to a file that needs updating. The dialog optionally also allows a 'to all' checkbox and a merge button. Similar to the alert dialog, you can set the title and the heading of the window.

var filechangeDialog = imports["dialog.filechange"];

filechangeDialog.show("File changed", 
    "File 'people.js' has changed", 
    function(all){
        console.log("Use local copy" + (all ? " for all" : ""));
    }, 
    function(all){
        console.log("Use remote copy" + (all ? " for all" : ""));
    }, 
    function(all){
        console.log("Merge files" + (all ? " for all" : ""));
    }, {
        all: true,
        merge: true
    });
735735

dialog.fileoverwrite

Use the fileoverwrite dialog to ask a user to overwrite a file or any other content. The dialog optionally also allows overwrite all, skip all and a cancel button. Similar to the alert dialog, you can set the title, heading and the body of the window.

var fileoverwriteDialog = imports["dialog.fileoverwrite"];

fileoverwriteDialog.show("Uploading", 
    "File 'people.js' already exists", 
    "Would you like to overwrite 'people.js'?",
    function(all){
        console.log("Overwrite" + (all ? " for all" : ""));
    }, 
    function(all){
        console.log("Skip" + (all ? " for all" : ""));
    }, {
        all: true,
        cancel: true
    });
735735

dialog.fileremove

Use the fileremove dialog to remove a set of files. Unlike the other dialogs, this dialog expect to be passed an array of stat objects and doesn't allow much configuration.

var fileremoveDialog = imports["dialog.fileremove"];

fs.readdir("/", function(err, files){
    if (err) return console.error(err);
    
    fileremoveDialog.show(files, function(file){
        fs.unlink(file.path, function(err){
            console.log("Removed ", file.path);
        });
    });
});
735735

dialog.file

Use the file dialog to have a user pick a file path or directory path. Similar to those offered by most operating systems, the file dialog allows a user to navigate the file system and find a folder and optionally a filename to open, save or otherwise. You can set the caption of the button to specify the action that is involved. The result of the dialog is a path to use in your action. Cloud9 uses this dialog for the Save As functionality as well as choosing the directory in the run panel.

var fileDialog = imports["dialog.file"];

fileDialog.show("Save something", "/example/test.js", 
    function(path, stat, done){
        console.log("Chosen path is ", path, " and is currently a ", stat.mime);
    }, 
    function(){
        console.log("Action cancelled");
    }, {
        createFolderButton: true,
        showFilesCheckbox: true,
        hideFileInput: false,
        chooseCaption: "Save"
    });
735735