Skip to content

Commit b8e10f3

Browse files
committed
update
snippet fields
1 parent 7c9d276 commit b8e10f3

10 files changed

Lines changed: 376 additions & 32 deletions

File tree

build.config.js

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,6 @@ module.exports = {
1010
src:'node_modules/angular/angular.js',
1111
cdn:'https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js'
1212
},
13-
{
14-
name:'angular-ui-ace',
15-
src:'node_modules/@rokt33r/angular-ui-ace/src/ui-ace.js',
16-
cdn:'https://cdn.rawgit.com/angular-ui/ui-ace/v0.2.3/ui-ace.min.js'
17-
},
1813
{
1914
name:'angular-bootstrap',
2015
src:'node_modules/angular-bootstrap/dist/ui-bootstrap-tpls.js',

src/directives/tags.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
angular.module('codexen.directives')
2+
.directive('tags', function () {
3+
return {
4+
restrict:'A',
5+
template: '<p class="tags" ng-if="tags.length">'+
6+
'<i class="fa fa-tags"></i> '+
7+
'<a ng-repeat="tag in tags" href="#">#<span ng-bind="tag.name"></span></a>'+
8+
'</p>',
9+
scope:{
10+
tags: '='
11+
}
12+
}
13+
})

src/directives/ui-ace.js

Lines changed: 337 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
1+
'use strict';
2+
3+
/**
4+
* Binds a ACE Editor widget
5+
*/
6+
angular.module('ui.ace', [])
7+
.constant('uiAceConfig', {})
8+
.directive('uiAce', ['uiAceConfig', function (uiAceConfig) {
9+
10+
if (angular.isUndefined(window.ace)) {
11+
throw new Error('ui-ace need ace to work... (o rly?)');
12+
}
13+
14+
/**
15+
* Sets editor options such as the wrapping mode or the syntax checker.
16+
*
17+
* The supported options are:
18+
*
19+
* <ul>
20+
* <li>showGutter</li>
21+
* <li>useWrapMode</li>
22+
* <li>onLoad</li>
23+
* <li>theme</li>
24+
* <li>mode</li>
25+
* </ul>
26+
*
27+
* @param acee
28+
* @param session ACE editor session
29+
* @param {object} opts Options to be set
30+
*/
31+
var setOptions = function(acee, session, opts) {
32+
33+
// sets the ace worker path, if running from concatenated
34+
// or minified source
35+
if (angular.isDefined(opts.workerPath)) {
36+
var config = window.ace.require('ace/config');
37+
config.set('workerPath', opts.workerPath);
38+
}
39+
// ace requires loading
40+
if (angular.isDefined(opts.require)) {
41+
opts.require.forEach(function (n) {
42+
window.ace.require(n);
43+
});
44+
}
45+
// Boolean options
46+
if (angular.isDefined(opts.showGutter)) {
47+
acee.renderer.setShowGutter(opts.showGutter);
48+
}
49+
if (angular.isDefined(opts.useWrapMode)) {
50+
session.setUseWrapMode(opts.useWrapMode);
51+
}
52+
if (angular.isDefined(opts.showInvisibles)) {
53+
acee.renderer.setShowInvisibles(opts.showInvisibles);
54+
}
55+
if (angular.isDefined(opts.showIndentGuides)) {
56+
acee.renderer.setDisplayIndentGuides(opts.showIndentGuides);
57+
}
58+
if (angular.isDefined(opts.useSoftTabs)) {
59+
session.setUseSoftTabs(opts.useSoftTabs);
60+
}
61+
if (angular.isDefined(opts.showPrintMargin)) {
62+
acee.setShowPrintMargin(opts.showPrintMargin);
63+
}
64+
if (angular.isDefined(opts.maxLines)) {
65+
if(opts.maxLines < 0) opts.maxLines = Infinity
66+
acee.setOptions({
67+
maxLines: opts.maxLines
68+
})
69+
}
70+
71+
// commands
72+
if (angular.isDefined(opts.disableSearch) && opts.disableSearch) {
73+
acee.commands.addCommands([
74+
{
75+
name: 'unfind',
76+
bindKey: {
77+
win: 'Ctrl-F',
78+
mac: 'Command-F'
79+
},
80+
exec: function () {
81+
return false;
82+
},
83+
readOnly: true
84+
}
85+
]);
86+
}
87+
88+
// Basic options
89+
if (angular.isString(opts.theme)) {
90+
acee.setTheme('ace/theme/' + opts.theme);
91+
}
92+
if (angular.isString(opts.mode)) {
93+
session.setMode('ace/mode/' + opts.mode);
94+
}
95+
// Advanced options
96+
if (angular.isDefined(opts.firstLineNumber)) {
97+
if (angular.isNumber(opts.firstLineNumber)) {
98+
session.setOption('firstLineNumber', opts.firstLineNumber);
99+
} else if (angular.isFunction(opts.firstLineNumber)) {
100+
session.setOption('firstLineNumber', opts.firstLineNumber());
101+
}
102+
}
103+
104+
// advanced options
105+
var key, obj;
106+
if (angular.isDefined(opts.advanced)) {
107+
for (key in opts.advanced) {
108+
// create a javascript object with the key and value
109+
obj = { name: key, value: opts.advanced[key] };
110+
// try to assign the option to the ace editor
111+
acee.setOption(obj.name, obj.value);
112+
}
113+
}
114+
115+
// advanced options for the renderer
116+
if (angular.isDefined(opts.rendererOptions)) {
117+
for (key in opts.rendererOptions) {
118+
// create a javascript object with the key and value
119+
obj = { name: key, value: opts.rendererOptions[key] };
120+
// try to assign the option to the ace editor
121+
acee.renderer.setOption(obj.name, obj.value);
122+
}
123+
}
124+
125+
// onLoad callbacks
126+
angular.forEach(opts.callbacks, function (cb) {
127+
if (angular.isFunction(cb)) {
128+
cb(acee);
129+
}
130+
});
131+
};
132+
133+
return {
134+
restrict: 'EA',
135+
require: '?ngModel',
136+
link: function (scope, elm, attrs, ngModel) {
137+
138+
/**
139+
* Corresponds the uiAceConfig ACE configuration.
140+
* @type object
141+
*/
142+
var options = uiAceConfig.ace || {};
143+
144+
/**
145+
* uiAceConfig merged with user options via json in attribute or data binding
146+
* @type object
147+
*/
148+
var opts = angular.extend({}, options, scope.$eval(attrs.uiAce));
149+
150+
/**
151+
* ACE editor
152+
* @type object
153+
*/
154+
var acee = window.ace.edit(elm[0]);
155+
acee.$blockScrolling = Infinity
156+
157+
/**
158+
* ACE editor session.
159+
* @type object
160+
* @see [EditSession]{@link http://ace.c9.io/#nav=api&api=edit_session}
161+
*/
162+
var session = acee.getSession();
163+
164+
/**
165+
* Reference to a change listener created by the listener factory.
166+
* @function
167+
* @see listenerFactory.onChange
168+
*/
169+
var onChangeListener;
170+
171+
/**
172+
* Reference to a blur listener created by the listener factory.
173+
* @function
174+
* @see listenerFactory.onBlur
175+
*/
176+
var onBlurListener;
177+
178+
/**
179+
* Calls a callback by checking its existing. The argument list
180+
* is variable and thus this function is relying on the arguments
181+
* object.
182+
* @throws {Error} If the callback isn't a function
183+
*/
184+
var executeUserCallback = function () {
185+
186+
/**
187+
* The callback function grabbed from the array-like arguments
188+
* object. The first argument should always be the callback.
189+
*
190+
* @see [arguments]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments}
191+
* @type {*}
192+
*/
193+
var callback = arguments[0];
194+
195+
/**
196+
* Arguments to be passed to the callback. These are taken
197+
* from the array-like arguments object. The first argument
198+
* is stripped because that should be the callback function.
199+
*
200+
* @see [arguments]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments}
201+
* @type {Array}
202+
*/
203+
var args = Array.prototype.slice.call(arguments, 1);
204+
205+
if (angular.isDefined(callback)) {
206+
scope.$evalAsync(function () {
207+
if (angular.isFunction(callback)) {
208+
callback(args);
209+
} else {
210+
throw new Error('ui-ace use a function as callback.');
211+
}
212+
});
213+
}
214+
};
215+
216+
/**
217+
* Listener factory. Until now only change listeners can be created.
218+
* @type object
219+
*/
220+
var listenerFactory = {
221+
/**
222+
* Creates a change listener which propagates the change event
223+
* and the editor session to the callback from the user option
224+
* onChange. It might be exchanged during runtime, if this
225+
* happens the old listener will be unbound.
226+
*
227+
* @param callback callback function defined in the user options
228+
* @see onChangeListener
229+
*/
230+
onChange: function (callback) {
231+
return function (e) {
232+
var newValue = session.getValue();
233+
234+
if (ngModel && newValue !== ngModel.$viewValue &&
235+
// HACK make sure to only trigger the apply outside of the
236+
// digest loop 'cause ACE is actually using this callback
237+
// for any text transformation !
238+
!scope.$$phase && !scope.$root.$$phase) {
239+
scope.$evalAsync(function () {
240+
ngModel.$setViewValue(newValue);
241+
});
242+
}
243+
244+
executeUserCallback(callback, e, acee);
245+
};
246+
},
247+
/**
248+
* Creates a blur listener which propagates the editor session
249+
* to the callback from the user option onBlur. It might be
250+
* exchanged during runtime, if this happens the old listener
251+
* will be unbound.
252+
*
253+
* @param callback callback function defined in the user options
254+
* @see onBlurListener
255+
*/
256+
onBlur: function (callback) {
257+
return function () {
258+
executeUserCallback(callback, acee);
259+
};
260+
}
261+
};
262+
263+
attrs.$observe('readonly', function (value) {
264+
acee.setReadOnly(!!value || value === '');
265+
});
266+
267+
// Value Blind
268+
if (ngModel) {
269+
ngModel.$formatters.push(function (value) {
270+
if (angular.isUndefined(value) || value === null) {
271+
return '';
272+
}
273+
else if (angular.isObject(value) || angular.isArray(value)) {
274+
throw new Error('ui-ace cannot use an object or an array as a model');
275+
}
276+
return value;
277+
});
278+
279+
ngModel.$render = function () {
280+
session.setValue(ngModel.$viewValue);
281+
};
282+
}
283+
284+
// Listen for option updates
285+
var updateOptions = function (current, previous) {
286+
if (current === previous) return;
287+
opts = angular.extend({}, options, scope.$eval(attrs.uiAce));
288+
289+
opts.callbacks = [ opts.onLoad ];
290+
if (opts.onLoad !== options.onLoad) {
291+
// also call the global onLoad handler
292+
opts.callbacks.unshift(options.onLoad);
293+
}
294+
295+
// EVENTS
296+
297+
// unbind old change listener
298+
session.removeListener('change', onChangeListener);
299+
300+
// bind new change listener
301+
onChangeListener = listenerFactory.onChange(opts.onChange);
302+
session.on('change', onChangeListener);
303+
304+
// unbind old blur listener
305+
//session.removeListener('blur', onBlurListener);
306+
acee.removeListener('blur', onBlurListener);
307+
308+
// bind new blur listener
309+
onBlurListener = listenerFactory.onBlur(opts.onBlur);
310+
acee.on('blur', onBlurListener);
311+
312+
setOptions(acee, session, opts);
313+
};
314+
315+
scope.$watch(attrs.uiAce, updateOptions, /* deep watch */ true);
316+
317+
// set the options here, even if we try to watch later, if this
318+
// line is missing things go wrong (and the tests will also fail)
319+
updateOptions(options);
320+
321+
elm.on('$destroy', function () {
322+
acee.session.$stopWorker();
323+
acee.destroy();
324+
});
325+
326+
scope.$watch(function() {
327+
return [elm[0].offsetWidth, elm[0].offsetHeight];
328+
}, function() {
329+
acee.resize();
330+
acee.renderer.updateFull();
331+
}, true);
332+
333+
scope.Infinity = -1
334+
335+
}
336+
};
337+
}]);

src/index.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
<script src="vendor/angular.js"></script>
2727
<script src="vendor/angular-sanitize.js"></script>
2828
<script src="vendor/angular-ui-router.js"></script>
29-
<script src="vendor/ui-ace.js"></script>
3029
<script src="vendor/ui-bootstrap-tpls.js"></script>
3130
<script src="vendor/select.js"></script>
3231
<script src="vendor/satellizer.js"></script>

src/modals/new-snippet-modal.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@ angular.module('codexen.modals')
1818

1919
vm.submit = function () {
2020
var params = {
21-
title: vm.title,
2221
description: vm.description,
23-
prefix: vm.prefix,
22+
callSign: vm.callSign,
2423
mode: vm.mode==null?null:vm.mode.name.toLowerCase(),
2524
content: vm.content,
2625
tags: angular.isArray(vm.tags)?vm.tags.map(function (tag) { return {_id: tag._id, name: tag.name} }):[]

0 commit comments

Comments
 (0)