Skip to content
This repository has been archived by the owner on May 25, 2019. It is now read-only.

Scope scrict mode to IIFE #119

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"grunt-conventional-changelog": "~1.1.0",
"grunt-karma": "~0.9.0",
"grunt-ng-annotate": "0.8.0",
"jasmine-core": "^2.4.1",
"karma": "~0.12.0",
"karma-chrome-launcher": "~0.1.1",
"karma-coffee-preprocessor": "~0.2.1",
Expand Down
243 changes: 123 additions & 120 deletions src/ui-codemirror.js
Original file line number Diff line number Diff line change
@@ -1,150 +1,153 @@
'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 needs CodeMirror to work... (o rly?)');
(function () {
'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 needs CodeMirror to work... (o rly?)');
}

return postLink;
}
};

return postLink;
}
};
function postLink(scope, iElement, iAttrs, ngModel) {

function postLink(scope, iElement, iAttrs, ngModel) {
var codemirrorOptions = angular.extend(
{ value: iElement.text() },
uiCodemirrorConfig.codemirror || {},
scope.$eval(iAttrs.uiCodemirror),
scope.$eval(iAttrs.uiCodemirrorOpts)
);

var codemirrorOptions = angular.extend(
{ value: iElement.text() },
uiCodemirrorConfig.codemirror || {},
scope.$eval(iAttrs.uiCodemirror),
scope.$eval(iAttrs.uiCodemirrorOpts)
);
var codemirror = newCodemirrorEditor(iElement, codemirrorOptions);

var codemirror = newCodemirrorEditor(iElement, codemirrorOptions);
configOptionsWatcher(
codemirror,
iAttrs.uiCodemirror || iAttrs.uiCodemirrorOpts,
scope
);

configOptionsWatcher(
codemirror,
iAttrs.uiCodemirror || iAttrs.uiCodemirrorOpts,
scope
);
configNgModelLink(codemirror, ngModel, scope);

configNgModelLink(codemirror, ngModel, scope);
configUiRefreshAttribute(codemirror, iAttrs.uiRefresh, 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');
}
});

// 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);
}
});

// 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);
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;
}

return codemirrot;
}
function configOptionsWatcher(codemirrot, uiCodemirrorAttr, scope) {
if (!uiCodemirrorAttr) { return; }

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)) {

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;
}

if (oldValue && newValues[key] === oldValue[key]) {
return;
codemirrot.setOption(key, newValues[key]);
}
});
}
}

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;
});
}
}

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);
};

// 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);
});
}
});
}

// 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; }

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();
});
}
});
}

scope.$watch(uiRefreshAttr, function(newVal, oldVal) {
// Skip the initial watch firing
if (newVal !== oldVal) {
$timeout(function() {
codeMirror.refresh();
});
}
});
}

}
})();