Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
835e2f8
Refactored app.js to be easier to read and alter.
May 24, 2014
d1dac37
Refactored directives.js to comment out the code.
May 25, 2014
53da962
Moved application version value definition from the services.js to th…
May 25, 2014
67c838f
Updated application version to match the one found on package.json.
May 25, 2014
8a89ebb
Fixed some comments.
May 25, 2014
5476a4c
Wrapped directives into angular dependency injection array handlers.
May 25, 2014
0d74067
Refactored services.js to comment out the code.
May 25, 2014
c08c5f2
Appended core services to the main AngularJS app, not a sub-module.
May 25, 2014
f9b9d57
Commented out filters.js file.
May 25, 2014
94ddc2c
Appended core filters to the main AngularJS app, not a sub-module.
May 25, 2014
baccddf
Improved 'keys' filter documentation and code.
May 25, 2014
4972f05
Removed deprecated filter 'interpolate', as it's goal seems to now be…
May 25, 2014
0b02b0d
Added heading JSDoc comment to controller's script.
May 25, 2014
aea75c2
Replaced block comments with inline ones for Angular service/filter d…
May 26, 2014
b59f3a6
Minor syntax adjustments.
May 26, 2014
0312275
Pull #113: Removes block comment from a callback function, for this i…
May 27, 2014
f3b160a
Minor comment adjustments.
May 27, 2014
11de1df
Issue #113: Refactored directives to dynamically include other direct…
May 27, 2014
87a4a0c
Smart ass validation of array index.
May 27, 2014
bd4fdcb
Merge branch 'dev' into fs/refactoring-ui-code-rebase
May 27, 2014
aaa0908
Avoid errors by setting a default for panels classes array.
Jun 3, 2014
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
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
<li ng-repeat="error in errors">{{error}}</li>
</ul>
</div>
<ck-replace ng-repeat="element in form.elements | orderBy:'weight'" />
<ck-replace-element ng-repeat="element in form.elements | orderBy:'weight'" />
</form>
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ <h4 ng-if="editing">Edit {{element.subform.title | lowercase}}</h4>
<li ng-repeat="error in errors">{{error}}</li>
</ul>
</div>
<ck-replace ng-repeat="element in element.subform.elements | orderBy:'weight'" />
<ck-replace-element ng-repeat="element in element.subform.elements | orderBy:'weight'" />
</div>
33 changes: 28 additions & 5 deletions applications/default/public/js/app.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,30 @@
/**
* @file Main AngularJS module for the choko application.
*/

'use strict';

// Declare app level module which depends on services, directives and filters.
angular.module('choko', ['ngRoute', 'ngResource', 'ngSanitize', 'summernote', 'angularFileUpload', 'choko.services', 'choko.directives', 'choko.filters'])
.config(['$locationProvider', function($locationProvider) {
//$locationProvider.html5Mode(true);
}]);
// Define core choko dependencies.
var dependencies = [
'ngRoute',
'ngResource',
'ngSanitize',
'summernote',
'angularFileUpload'
];

// Declare main choko module.
angular.module('choko', dependencies)

// Define current choko version.
// @todo: we should read package.json and make available not only a version
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice idea! I forgot changing this one between releases, in bin/choko I have to set this too, maybe we should read packages.json there too so we change it only once before tagging a new release.

// value but other metadata that might be used thoughout the application.
.value('version', '0.0.4')

// Location/routing configuration.
.config(['$locationProvider', function($locationProvider) {

// Use HTML5 mode to remove "#" symbols from angular-routed pages.
// $locationProvider.html5Mode(true);

}]);
6 changes: 5 additions & 1 deletion applications/default/public/js/controllers.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* @file Choko core controllers.
*/

'use strict';

function ApplicationController($scope, $location, $http, applicationState, Choko) {
Expand Down Expand Up @@ -101,7 +105,7 @@ function RegionController($scope, $location, applicationState, Choko) {
//RegionController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function NavigationController($scope, $location, $window, applicationState, Choko) {
$scope.panel.classes.unshift('nav');
($scope.panel.classes = $scope.panel.classes || []).unshift('nav');

$scope.isAbsolute = function(url) {
return /^(?:[a-z]+:)?\/\//i.test(url);
Expand Down
138 changes: 120 additions & 18 deletions applications/default/public/js/directives.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,144 @@
/**
* @file Choko core directives.
*/

'use strict';

/* Directives */
// Append directives to main choko module.
angular.module('choko')

angular.module('choko.directives', [])
// Directive to return the application's version.
.directive('appVersion', ['version', function(version) {
return function(scope, elm, attrs) {
elm.text(version);
};
}])
.directive('ckReplace', function($http, $compile) {

// Directive to replace any tag with overridable templates from the server.
.directive('ckReplace', ['$http', '$compile', function($http, $compile) {
return {
restrict: 'E',
scope: true,
restrict: 'EA',

// As this directive will replace the existing markup, it's better that
// we run it previously to most other directives, to avoid dumb processing.
priority: 100,
compile: function(element, attrs) {
return function(scope, element, attrs) {
scope.element.template = scope.element.template || 'templates/' + scope.element.type + '.html';
$http({method: 'GET', url: scope.element.template, cache: true}).then(function(result) {
var template = angular.element($compile(result.data)(scope));
element.replaceWith(template);

// Request the template content.
var loadTemplate = $http({
method: 'GET',
// If the directive is an element, "src" should be available.
url: attrs.ckReplace || attrs.src,
cache: true
});

// When ready, compile the retrieved template.
loadTemplate.then(function(result) {

// Compile the returned template.
var compiled = $compile(result.data)(scope);

// Replace old element with compiled one.
element.replaceWith(angular.element(compiled));

});
};
}
};
})
.directive('ckButton', function($http, $compile) {
}])

// A helper service to handle re-compiling of directives.
.factory('ckReplaceAndRecompile', ['$compile', function ($compile) {
/**
* Creates a new element from the given, copying attributes but removing
* the old directive to avoid running it again. Recompiles the new
* element and replaces the old with it.
*/
return function (element, directiveToRemove, scope, newTag) {

// Handle multiple removals using a array of removing directives.
var directives = directiveToRemove.length ? directiveToRemove : [];
var tagName = element.prop('localName');
var replacement;

// Replace the directive, be it a tag name or attribute.
directives.forEach(function (directive) {
if (tagName == directive) {
replacement = angular.element(document.createElement(newTag || 'div'));
angular.element.each(element[0].attributes, function (i, attr) {
replacement.attr(attr.name, attr.value);
});
element.replaceWith(replacement);
element = replacement;
} else {
element.removeAttr(directive);
}
});

// Recompile the element.
$compile(element)(scope || {});
}
}])

// Directive to replace form elements with overridable templates from
// the server.
.directive('ckReplaceElement', ['ckReplaceAndRecompile', function(ckReplaceAndRecompile) {
return {
restrict: 'EA',
// This directive will insert other directives dynamically. We set
// priority=999 (high number) to make it run first, but nor before core
// Angular directives, as we need their data. (ng-repeat runs at 1000
// priority).
priority: 999,
terminal: true,
compile: function (tElement, attrs) {
return function(scope, element, attrs) {

// Allow for custom templates but fallback to default one based
// on element type.
scope.element.template = scope.element.template || 'templates/' + scope.element.type + '.html';

// Append the ck-replace directive.
element.attr('ck-replace', scope.element.template);

ckReplaceAndRecompile(element, ['ck-replace-element', 'ng-repeat'], scope);
}
}
};
}])

// Handles button or button groups for navigation bars.
// @todo This directive is specifically used by the navigation extension.
// Therefore it should be moved to this extension's directory.
.directive('ckButton', ['ckReplaceAndRecompile', function(ckReplaceAndRecompile) {
return {
restrict: 'E',
restrict: 'EA',
scope: true,
// This directive will insert other directives dynamically. We set
// priority=999 (high number) to make it run first, but nor before core
// Angular directives, as we need their data. (ng-repeat runs at 1000
// priority).
priority: 999,
terminal: true,
compile: function(element, attrs) {
return function(scope, element, attrs) {

// Add bootstrap button class.
scope.item.classes = scope.item.classes || [];
if (scope.item.classes.indexOf('btn-default')+1) {
scope.item.classes.push('btn-default');
}

// @todo: we should probably allow for custom templates, as we do in
// ckReplaceElement directive above.
var template = scope.item.items ? '/templates/btn-group-dropdown.html' : '/templates/btn-group-button.html';
scope.item.classes = scope.item.classes || ['btn-default'];

// Append the replacement directive.
element.attr('ck-replace', template);

$http({method: 'GET', url: template, cache: true}).then(function(result) {
var template = angular.element($compile(result.data)(scope));
element.replaceWith(template);
});
ckReplaceAndRecompile(element, ['ck-button', 'ng-repeat'], scope);
};
}
};
});
}]);
29 changes: 17 additions & 12 deletions applications/default/public/js/filters.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
/**
* @file Choko core filters.
*/

'use strict';

/* Filters */
angular.module('choko')

angular.module('choko.filters', [])
.filter('interpolate', ['version', function(version) {
return function(text) {
return String(text).replace(/\%VERSION\%/mg, version);
}
}])
// Filter to get an array of keys for an object.
.filter('keys', function() {
return function(input) {
if (!input) {
return [];
}
return Object.keys(input);

/**
* Returns the keys of a given acceptable value/object.
* @param {object|array|function} input
* @return {array}
*/
function objectKeysFilter(input) {
return ~['object', 'function'].indexOf(typeof input) ? Object.keys(input) : [];
}

return objectKeysFilter;
});

37 changes: 23 additions & 14 deletions applications/default/public/js/services.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,45 @@
/**
* @file Choko core services.
*/

'use strict';

/* Services */
angular.module('choko.services', [])
// Single value service for Choko version.
.value('version', '0.0.1')
// Append services to main choko module.
angular.module('choko')

// Choko main REST factory.
.factory('Choko', ['$resource', function($resource) {

.factory('Choko', function($resource) {
return $resource('/rest/:type/:key', {
var url = '/rest/:type/:key';
var defaultParams = {
type: '@type',
key: '@key'
},
{
};
var actions = {
'get': {
method: 'GET',
transformResponse: function (data) {
return angular.fromJson(data).data;
},
// Data is an Object, not an Array.
// Server will always return an object containing at least a 'data'
// property to hold the actual data and a status property.
isArray: false
}
});
})
}

// Shared server with application state.
.factory('applicationState', function($rootScope) {
return $resource(url, defaultParams, actions);
}])

// Application state wrapper, to be shared across controllers.
// P.s.: States are actual scope objects.
.factory('applicationState', function() {
var state = {};
return {
get: function() {
return state;
},
set: function(newState) {
return state = newState;
},
}
};
});