| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 | 'use strict';/** * Binds a CodeMirror widget to a <textarea> element. */angular.module('ui.codemirror', [])  .constant('uiCodemirrorConfig', {})  .directive('uiCodemirror', uiCodemirrorDirective);/** * @ngInject */function uiCodemirrorDirective($timeout, uiCodemirrorConfig) {  return {    restrict: 'EA',    require: '?ngModel',    compile: function compile() {      // Require CodeMirror      if (angular.isUndefined(window.CodeMirror)) {        throw new Error('ui-codemirror need CodeMirror to work... (o rly?)');      }      return postLink;    }  };  function postLink(scope, iElement, iAttrs, ngModel) {    var codemirrorOptions = angular.extend(      { value: iElement.text() },      uiCodemirrorConfig.codemirror || {},      scope.$eval(iAttrs.uiCodemirror),      scope.$eval(iAttrs.uiCodemirrorOpts)    );    var codemirror = newCodemirrorEditor(iElement, codemirrorOptions);    configOptionsWatcher(      codemirror,      iAttrs.uiCodemirror || iAttrs.uiCodemirrorOpts,      scope    );    configNgModelLink(codemirror, ngModel, scope);    configUiRefreshAttribute(codemirror, iAttrs.uiRefresh, scope);    // Allow access to the CodeMirror instance through a broadcasted event    // eg: $broadcast('CodeMirror', function(cm){...});    scope.$on('CodeMirror', function(event, callback) {      if (angular.isFunction(callback)) {        callback(codemirror);      } else {        throw new Error('the CodeMirror event requires a callback function');      }    });    // onLoad callback    if (angular.isFunction(codemirrorOptions.onLoad)) {      codemirrorOptions.onLoad(codemirror);    }  }  function newCodemirrorEditor(iElement, codemirrorOptions) {    var codemirrot;    if (iElement[0].tagName === 'TEXTAREA') {      // Might bug but still ...      codemirrot = window.CodeMirror.fromTextArea(iElement[0], codemirrorOptions);    } else {      iElement.html('');      codemirrot = new window.CodeMirror(function(cm_el) {        iElement.append(cm_el);      }, codemirrorOptions);    }    return codemirrot;  }  function configOptionsWatcher(codemirrot, uiCodemirrorAttr, scope) {    if (!uiCodemirrorAttr) { return; }    var codemirrorDefaultsKeys = Object.keys(window.CodeMirror.defaults);    scope.$watch(uiCodemirrorAttr, updateOptions, true);    function updateOptions(newValues, oldValue) {      if (!angular.isObject(newValues)) { return; }      codemirrorDefaultsKeys.forEach(function(key) {        if (newValues.hasOwnProperty(key)) {          if (oldValue && newValues[key] === oldValue[key]) {            return;          }          codemirrot.setOption(key, newValues[key]);        }      });    }  }  function configNgModelLink(codemirror, ngModel, scope) {    if (!ngModel) { return; }    // CodeMirror expects a string, so make sure it gets one.    // This does not change the model.    ngModel.$formatters.push(function(value) {      if (angular.isUndefined(value) || value === null) {        return '';      } else if (angular.isObject(value) || angular.isArray(value)) {        throw new Error('ui-codemirror cannot use an object or an array as a model');      }      return value;    });    // Override the ngModelController $render method, which is what gets called when the model is updated.    // This takes care of the synchronizing the codeMirror element with the underlying model, in the case that it is changed by something else.    ngModel.$render = function() {      //Code mirror expects a string so make sure it gets one      //Although the formatter have already done this, it can be possible that another formatter returns undefined (for example the required directive)      var safeViewValue = ngModel.$viewValue || '';      codemirror.setValue(safeViewValue);    };    // Keep the ngModel in sync with changes from CodeMirror    codemirror.on('change', function(instance) {      var newValue = instance.getValue();      if (newValue !== ngModel.$viewValue) {        scope.$evalAsync(function() {          ngModel.$setViewValue(newValue);        });      }    });  }  function configUiRefreshAttribute(codeMirror, uiRefreshAttr, scope) {    if (!uiRefreshAttr) { return; }    scope.$watch(uiRefreshAttr, function(newVal, oldVal) {      // Skip the initial watch firing      if (newVal !== oldVal) {        $timeout(function() {          codeMirror.refresh();        });      }    });  }}uiCodemirrorDirective.$inject = ["$timeout", "uiCodemirrorConfig"];
 |