TMCWebClient.editor = function (container, exercise) {

    var _template = {

            editor: Handlebars.templates.Editor

        },

        _container = container,
        _editor,
        _output,
        _intervalId,
        _exercise = exercise;

    function configure(editor) {

        // Editor
        editor.setPrintMarginColumn(false);
        editor.setDisplayIndentGuides(false);
        editor.getSession().setFoldStyle('markbeginend');

        // Text
        editor.setTheme('ace/theme/light');
        editor.setFontSize(12);
        editor.getSession().setTabSize(4);
        editor.getSession().setUseWrapMode(true);
        editor.getSession().setWrapLimitRange(100, 100);
        editor.getSession().setMode('ace/mode/java');
    }

    function initialise() {

        // Create container for editor
        var editorContainer = $('<div/>');

        // Add editor container to container
        $(_container).hide();
        $(_container).append(editorContainer);

        // Create editor
        _editor = ace.edit(editorContainer.get(0));
        configure(_editor);

        // Fetch exercise
        _exercise.fetchZip(function () {

            var files = _exercise.getFilesFromSource(),
                content = files[0].asText();

            // Render
            render(files);
            show(content);

            // Set active tab
            $(_container).find('.tab-bar li').first().addClass('active');
        });

        createOutputContainer();
    }

    function createOutputContainer() {

        _output = new TMCWebClient.output(_container);
    }

    function createSubmitHandler() {

        $(_container).find('.actions .submit').first().click(submitOnClickHandler);
    }

    function submitOnClickHandler() {

        clearInterval(_intervalId);
        saveActiveFile();

        _output.processing();

        _exercise.submit(function (data) {

            /* jshint camelcase:false */
            submissionPoller(data.submission_url);
            /* jshint camelcase:true */
        });
    }

    function submissionPoller(submissionUrl) {

        var intervalId = setInterval(function () {

            $.ajax(submissionUrl, {

                beforeSend: TMCWebClient.xhrBasicAuthentication,
                dataType: 'json',

                error: function (data) {

                    clearInterval(intervalId);
                    console.log(data);
                },

                success: function (data) {

                    if (data.status !== 'processing') {
                        clearInterval(intervalId);
                        showResults(data);
                    } else {
                        console.log(data.status);
                    }
                }
            });
        }, 3000);

        _intervalId = intervalId;
    }

    function showResults(data) {

        console.log(data);
        _output.showResults(data);
    }

    function createLastSubmissionHandler() {

        $(_container).find('.actions .submission').first().click(function () {

            _output.processing();
            _exercise.fetchLastSubmission(function (data) {

                showResults(data);
            });
        });
    }

    function render(files) {

        var attributes = {

            title: _exercise.getName(),
            files: files

        }

        // Render editor
        $(_container).prepend(_template.editor(attributes));

        // Add click events to tabs
        $(_container).find('.tab-bar li').click(changeFile);

        createSubmitHandler();
        createLastSubmissionHandler();
    }

    function show(content) {

        // Show container
        $(_container).show();

        _editor.setValue(content);

        // Clear selection
        _editor.getSelection().clearSelection();
        _editor.moveCursorTo(0, 0);
        _editor.getSession().setScrollTop(0);
    }

    function changeFile() {

        saveActiveFile();

        var element = $(this);

        // Clear previous active tab
        $(_container).find('.tab-bar li').removeClass('active');

        // Set active tab
        element.addClass('active');

        // File
        var filename = element.attr('data-id'),
            content = _exercise.getFile(filename).asText();

        show(content);
    }

    function saveActiveFile() {

        var filename = $('.tmc-exercise .tab-bar li.active').attr('data-id');
        _exercise.saveFile(filename, _editor.getValue());
    }

    initialise();
}

@@ -1311,24 +1311,64 @@
 der(files);%0A
+            setFileMode(files%5B0%5D.name);%0A
             
@@ -4340,27 +4340,951 @@
        s
-how(content
+etFileMode(filename);%0A%0A        show(content);%0A    %7D%0A%0A    function setFileMode(filename) %7B%0A        var modes = %7B%0A%0A            'c':    'c_cpp',%0A            'css':  'css',%0A            'h':    'c_cpp',%0A            'htm':  'html',%0A            'html': 'html',%0A            'java': 'java',%0A            'js':   'javascript',%0A            'json': 'json',%0A            'rb':   'ruby',%0A            'xml':  'xml',%0A            'yml':  'yaml'%0A%0A        %7D,%0A        // Fallback to text%0A        mode = 'text';%0A%0A        // Can determine filename extension%0A        var lastDotIndex = filename.lastIndexOf('.');%0A        if (lastDotIndex !== -1 && lastDotIndex !== 0) %7B%0A%0A            var filenameExtension = filename.substring(lastDotIndex + 1);%0A%0A            // Set mode or fallback to text if no mode is specified for the filename extension%0A            mode = modes%5BfilenameExtension%5D %7C%7C mode;%0A        %7D%0A%0A        _editor.getSession().setMode('ace/mode/' + mode
 );%0A    %7D

Set file mode according to the filename