/** * @file * JavaScript behaviors for CodeMirror integration. */ (function ($, Drupal) { 'use strict'; // @see http://codemirror.net/doc/manual.html#config Drupal.webform = Drupal.webform || {}; Drupal.webform.codeMirror = Drupal.webform.codeMirror || {}; Drupal.webform.codeMirror.options = Drupal.webform.codeMirror.options || {}; /** * Initialize CodeMirror editor. * * @type {Drupal~behavior} */ Drupal.behaviors.webformCodeMirror = { attach: function (context) { if (!window.CodeMirror) { return; } // Webform CodeMirror editor. $(context).find('textarea.js-webform-codemirror').once('webform-codemirror').each(function () { var $input = $(this); // Open all closed details, so that editor height is correctly calculated. var $details = $(this).parents('details:not([open])'); $details.attr('open', 'open'); // #59 HTML5 required attribute breaks hack for webform submission. // https://github.com/marijnh/CodeMirror-old/issues/59 $(this).removeAttr('required'); var options = $.extend({ mode: $(this).attr('data-webform-codemirror-mode'), lineNumbers: true, c: ($(this).attr('wrap') === 'off') ? false : true, viewportMargin: Infinity, readOnly: ($(this).prop('readonly') || $(this).prop('disabled')) ? true : false, extraKeys: { // Setting for using spaces instead of tabs - https://github.com/codemirror/CodeMirror/issues/988 Tab: function (cm) { var spaces = Array(cm.getOption('indentUnit') + 1).join(' '); cm.replaceSelection(spaces, 'end', '+element'); }, // On 'Escape' move to the next tabbable input. // @see http://bgrins.github.io/codemirror-accessible/ Esc: function (cm) { // Must show and then textarea so that we can determine // its tabindex. var textarea = $(cm.getTextArea()); $(textarea).show().addClass('visually-hidden'); var $tabbable = $(':tabbable'); var tabindex = $tabbable.index(textarea); $(textarea).hide().removeClass('visually-hidden'); // Tabindex + 2 accounts for the CodeMirror's iframe. $tabbable.eq(tabindex + 2).focus(); } } }, Drupal.webform.codeMirror.options); var editor = CodeMirror.fromTextArea(this, options); // Now, close details. $details.removeAttr('open'); // Issue #2764443: CodeMirror is not setting submitted value when // rendered within a webform UI dialog. editor.on('blur', function (event) { editor.save(); }); // Update CodeMirror when the textarea's value has changed. // @see webform.states.js $input.on('change', function () { editor.getDoc().setValue($input.val()); }); // Set CodeMirror to be readonly when the textarea is disabled. // @see webform.states.js $input.on('webform:disabled', function () { editor.setOption('readOnly', $input.is(':disabled')); }); // Delay refreshing CodeMirror for 10 millisecond while the dialog is // still being rendered. // @see http://stackoverflow.com/questions/8349571/codemirror-editor-is-not-loading-content-until-clicked setTimeout(function () { // Show tab panel and open details. var $tabPanel = $input.parents('.ui-tabs-panel:hidden'); var $details = $input.parents('details:not([open])'); if (!$tabPanel.length && $details.length) { return; } $tabPanel.show(); $details.attr('open', 'open'); editor.refresh(); // Hide tab panel and close details. $tabPanel.hide(); $details.removeAttr('open'); }, 10); }); // Webform CodeMirror syntax coloring. $(context).find('.js-webform-codemirror-runmode').once('webform-codemirror-runmode').each(function () { // Mode Runner - http://codemirror.net/demo/runmode.html CodeMirror.runMode($(this).addClass('cm-s-default').text(), $(this).attr('data-webform-codemirror-mode'), this); }); } }; })(jQuery, Drupal);