Removed temp committed files for belle, added build scripts

This commit is contained in:
Shannon
2013-06-10 14:46:49 -02:00
parent 6b6dfceda0
commit b12e59cbac
319 changed files with 16 additions and 81605 deletions

View File

@@ -1,16 +0,0 @@
/*! umbraco - v0.0.1-SNAPSHOT - 2013-06-10
* http://umbraco.github.io/Belle
* Copyright (c) 2013 Per Ploug, Anders Stenteberg & Shannon Deminick;
* Licensed MIT
*/
'use strict';
define(['angular'], function (angular) {
var app = angular.module('umbraco', [
'umbraco.filters',
'umbraco.directives',
'umbraco.mocks.resources',
'umbraco.services'
]);
return app;
});

View File

@@ -1,70 +0,0 @@
require.config({
waitSeconds: 120,
paths: {
jquery: '../lib/jquery/jquery-1.8.2.min',
jqueryCookie: '../lib/jquery/jquery.cookie',
umbracoExtensions: "../lib/umbraco/extensions",
bootstrap: '../lib/bootstrap/js/bootstrap',
underscore: '../lib/underscore/underscore',
angular: '../lib/angular/angular.min',
angularResource: '../lib/angular/angular-resource',
codemirror: '../lib/codemirror/js/lib/codemirror',
codemirrorJs: '../lib/codemirror/js/mode/javascript/javascript',
codemirrorCss: '../lib/codemirror/js/mode/css/css',
codemirrorXml: '../lib/codemirror/js/mode/xml/xml',
codemirrorHtml: '../lib/codemirror/js/mode/htmlmixed/htmlmixed',
tinymce: '../lib/tinymce/tinymce.min',
text: '../lib/require/text',
async: '../lib/require/async',
css: '../lib/require/css'
},
shim: {
'angular' : {'exports' : 'angular'},
'angular-resource': { deps: ['angular'] },
'bootstrap': { deps: ['jquery'] },
'jqueryCookie': { deps: ['jquery'] },
'underscore': {exports: '_'},
'codemirror': {exports: 'CodeMirror'},
'codemirrorJs':{deps:['codemirror']},
'codemirrorCss':{deps:['codemirror']},
'codemirrorXml':{deps:['codemirror']},
'codemirrorHtml':{deps:['codemirrorXml','codemirrorCss','codemirrorJs'], exports: 'mixedMode'},
'tinymce': {
exports: 'tinyMCE',
init: function () {
this.tinymce.DOM.events.domLoaded = true;
return this.tinymce;
}
}
},
priority: [
"angular"
],
urlArgs: 'v=1.1'
});
require( [
'angular',
'app',
'jquery',
'jqueryCookie',
'bootstrap',
'umbracoExtensions',
'umbraco.mocks',
'umbraco.directives',
'umbraco.filters',
'umbraco.services',
'umbraco.controllers',
'routes'
], function(angular, app, jQuery) {
//This function will be called when all the dependencies
//listed above are loaded. Note that this function could
//be called before the page is loaded.
//This callback is optional.
jQuery(document).ready(function () {
angular.bootstrap(document, ['umbraco']);
});
});

View File

@@ -1,579 +0,0 @@
'use strict';
/*! umbraco - v0.0.1-SNAPSHOT - 2013-06-10
* http://umbraco.github.io/Belle
* Copyright (c) 2013 Per Ploug, Anders Stenteberg & Shannon Deminick;
* Licensed MIT
*/
define(['app', 'angular'], function (app, angular) {
//Handles the section area of the app
angular.module('umbraco').controller("NavigationController",
function ($scope, navigationService) {
//load navigation service handlers
$scope.changeSection = navigationService.changeSection;
$scope.showTree = navigationService.showTree;
$scope.hideTree = navigationService.hideTree;
$scope.hideMenu = navigationService.hideMenu;
$scope.showMenu = navigationService.showMenu;
$scope.hideDialog = navigationService.hideDialog;
$scope.hideNavigation = navigationService.hideNavigation;
$scope.ui = navigationService.ui;
$scope.selectedId = navigationService.currentId;
$scope.sections = navigationService.sections();
//events
$scope.$on("treeOptionsClick", function(ev, args){
$scope.currentNode = args.node;
args.scope = $scope;
navigationService.showMenu(ev, args);
});
$scope.openDialog = function(currentNode,action,currentSection){
navigationService.showDialog({
scope: $scope,
node: currentNode,
action: action,
section: currentSection});
};
});
angular.module('umbraco').controller("SearchController", function ($scope, searchService, $log, navigationService) {
var currentTerm = "";
$scope.deActivateSearch = function(){
currentTerm = "";
};
$scope.performSearch = function (term) {
if(term != undefined && term != currentTerm){
if(term.length > 3){
$scope.ui.selectedSearchResult = -1;
navigationService.showSearch();
currentTerm = term;
$scope.ui.searchResults = searchService.search(term, $scope.currentSection);
}else{
$scope.ui.searchResults = [];
}
}
};
$scope.hideSearch = navigationService.hideSearch;
$scope.iterateResults = function (direction) {
if(direction == "up" && $scope.ui.selectedSearchResult < $scope.ui.searchResults.length)
$scope.ui.selectedSearchResult++;
else if($scope.ui.selectedSearchResult > 0)
$scope.ui.selectedSearchResult--;
};
$scope.selectResult = function () {
navigationService.showMenu($scope.ui.searchResults[$scope.ui.selectedSearchResult], undefined);
};
});
angular.module('umbraco').controller("DashboardController", function ($scope, $routeParams) {
$scope.name = $routeParams.section;
});
//handles authentication and other application.wide services
angular.module('umbraco').controller("MainController",
function ($scope, $routeParams, $rootScope, notificationsService, userService, navigationService) {
//also be authed for e2e test
var d = new Date();
var weekday = new Array("Super Sunday", "Manic Monday", "Tremendous Tuesday", "Wonderfull Wednesday", "Thunder Thursday", "Friendly Friday", "Shiny Saturday");
$scope.today = weekday[d.getDay()];
$scope.signin = function () {
$scope.authenticated = userService.authenticate($scope.login, $scope.password);
if($scope.authenticated){
$scope.user = userService.getCurrentUser();
}
};
$scope.signout = function () {
userService.signout();
$scope.authenticated = false;
};
//subscribes to notifications in the notification service
$scope.notifications = notificationsService.current;
$scope.$watch('notificationsService.current', function (newVal, oldVal, scope) {
if (newVal) {
$scope.notifications = newVal;
}
});
$scope.removeNotification = function(index) {
notificationsService.remove(index);
};
$scope.closeDialogs = function(event){
$rootScope.$emit("closeDialogs");
if(navigationService.ui.stickyNavigation && $(event.target).parents(".umb-modalcolumn").size() == 0){
navigationService.hideNavigation();
}
};
if (userService.authenticated) {
$scope.signin();
}
});
//used for the media picker dialog
angular.module("umbraco").controller("Umbraco.Dialogs.ContentPickerController",
function ($scope) {
$scope.$on("treeNodeSelect", function(event, args){
args.event.preventDefault();
$(args.event.target.parentElement).find("i.umb-tree-icon").attr("class", "icon umb-tree-icon sprTree icon-check blue");
$scope.select(args.node);
});
});
//used for the macro picker dialog
angular.module("umbraco").controller("Umbraco.Dialogs.MacroPickerController", function ($scope, macroFactory) {
$scope.macros = macroFactory.all(true);
$scope.dialogMode = "list";
$scope.configureMacro = function(macro){
$scope.dialogMode = "configure";
$scope.dialogData.macro = macroFactory.getMacro(macro.alias);
};
});
//used for the media picker dialog
angular.module("umbraco")
.controller("Umbraco.Dialogs.MediaPickerController",
function($scope, mediaResource) {
mediaResource.rootMedia()
.then(function(data) {
$scope.images = data;
});
$scope.selectMediaItem = function(image) {
if (image.contentTypeAlias.toLowerCase() == 'folder') {
mediaResource.getChildren(image.id)
.then(function(data) {
$scope.images = data;
});
} else if (image.contentTypeAlias.toLowerCase() == 'image') {
$scope.select(image);
}
};
});
angular.module("umbraco").controller("Umbraco.Common.LegacyController",
function($scope, $routeParams){
$scope.legacyPath = decodeURI($routeParams.p);
});
angular.module('umbraco')
.controller("Umbraco.Editors.ContentCreateController",
function ($scope, $routeParams,contentTypeResource) {
$scope.allowedTypes = contentTypeResource.getAllowedTypes($scope.currentNode.id);
});
angular.module("umbraco")
.controller("Umbraco.Editors.ContentEditController",
function ($scope, $routeParams, contentResource, notificationsService) {
if($routeParams.create)
$scope.content = contentResource.getContentScaffold($routeParams.id, $routeParams.doctype);
else
$scope.content = contentResource.getContent($routeParams.id);
$scope.saveAndPublish = function (cnt) {
cnt.publishDate = new Date();
contentResource.publishContent(cnt);
notificationsService.success("Published", "Content has been saved and published");
};
$scope.save = function (cnt) {
cnt.updateDate = new Date();
contentResource.saveContent(cnt);
notificationsService.success("Saved", "Content has been saved");
};
});
angular.module("umbraco").controller("Umbraco.Editors.CodeMirrorController", function ($scope, $rootScope) {
require(
[
'css!../lib/codemirror/js/lib/codemirror.css',
'css!../lib/codemirror/css/umbracoCustom.css',
'codemirrorHtml'
],
function () {
var editor = CodeMirror.fromTextArea(
document.getElementById($scope.model.alias),
{
mode: CodeMirror.modes.htmlmixed,
tabMode: "indent"
});
editor.on("change", function(cm) {
$rootScope.$apply(function(){
$scope.model.value = cm.getValue();
});
});
});
});
//this controller simply tells the dialogs service to open a mediaPicker window
//with a specified callback, this callback will receive an object with a selection on it
angular.module('umbraco')
.controller("Umbraco.Editors.ContentPickerController",
function($scope, dialogService){
$scope.openContentPicker =function(value){
var d = dialogService.contentPicker({scope: $scope, callback: populate});
};
function populate(data){
$scope.model.value = data.selection;
}
});
angular.module("umbraco").controller("Umbraco.Editors.DatepickerController",
function ($scope, notificationsService) {
require(
[
'views/propertyeditors/umbraco/datepicker/bootstrap.datepicker.js',
'css!/belle/views/propertyeditors/umbraco/datepicker/bootstrap.datepicker.css'
],
function () {
//The Datepicker js and css files are available and all components are ready to use.
// Get the id of the datepicker button that was clicked
var pickerId = $scope.model.alias;
// Open the datepicker and add a changeDate eventlistener
$("#" + pickerId).datepicker({
format: "dd/mm/yyyy",
autoclose: true
}).on("changeDate", function (e) {
// When a date is clicked the date is stored in model.value as a ISO 8601 date
$scope.model.value = e.date.toISOString();
});
}
);
});
angular.module("umbraco")
.controller("Umbraco.Editors.GoogleMapsController",
function ($rootScope, $scope, notificationsService, $timeout) {
require(
[
'async!http://maps.google.com/maps/api/js?sensor=false'
],
function () {
//Google maps is available and all components are ready to use.
var valueArray = $scope.model.value.split(',');
var latLng = new google.maps.LatLng(valueArray[0], valueArray[1]);
var mapDiv = document.getElementById($scope.model.alias + '_map');
var mapOptions = {
zoom: $scope.model.config.zoom,
center: latLng,
mapTypeId: google.maps.MapTypeId[$scope.model.config.mapType]
};
var map = new google.maps.Map(mapDiv, mapOptions);
var marker = new google.maps.Marker({
map: map,
position: latLng,
draggable: true
});
google.maps.event.addListener(marker, "dragend", function(e){
var newLat = marker.getPosition().lat();
var newLng = marker.getPosition().lng();
//here we will set the value
$scope.model.value = newLat + "," + newLng;
//call the notication engine
$rootScope.$apply(function () {
notificationsService.warning("Your dragged a marker to", $scope.model.value);
});
});
//hack to hook into tab switching for map resizing
$('a[data-toggle="tab"]').on('shown', function (e) {
google.maps.event.trigger(map, 'resize');
});
}
);
});
'use strict';
//this controller simply tells the dialogs service to open a mediaPicker window
//with a specified callback, this callback will receive an object with a selection on it
angular.module("umbraco").controller("Umbraco.Editors.GridController",
function($rootScope, $scope, dialogService, $log){
//we most likely will need some iframe-motherpage interop here
//we most likely will need some iframe-motherpage interop here
$scope.openMediaPicker =function(){
var d = dialogService.mediaPicker({scope: $scope, callback: renderImages});
};
$scope.openPropertyDialog =function(){
var d = dialogService.property({scope: $scope, callback: renderProperty});
};
$scope.openMacroDialog =function(){
var d = dialogService.macroPicker({scope: $scope, callback: renderMacro});
};
function renderProperty(data){
$scope.currentElement.html("<h1>boom, property!</h1>");
}
function renderMacro(data){
// $scope.currentElement.html( macroFactory.renderMacro(data.macro, -1) );
}
function renderImages(data){
var list = $("<ul class='thumbnails'></ul>")
$.each(data.selection, function(i, image) {
list.append( $("<li class='span2'><img class='thumbnail' src='" + image.src + "'></li>") );
});
$scope.currentElement.html( list[0].outerHTML);
}
$(window).bind("umbraco.grid.click", function(event){
$scope.$apply(function () {
$scope.currentEditor = event.editor;
$scope.currentElement = $(event.element);
if(event.editor == "macro")
$scope.openMacroDialog();
else if(event.editor == "image")
$scope.openMediaPicker();
else
$scope.propertyDialog();
});
})
});
angular.module("umbraco")
.controller("Umbraco.Editors.ListViewController",
function ($rootScope, $scope, contentResource, contentTypeResource) {
$scope.options = {
take: 10,
offset: 0,
filter: '',
sortby: 'id',
order: "desc"
};
$scope.pagination = new Array(100);
$scope.listViewAllowedTypes = contentTypeResource.getAllowedTypes($scope.content.id);
$scope.next = function(){
if($scope.options.offset < $scope.listViewResultSet.pages){
$scope.options.offset++;
$scope.reloadView();
}
};
$scope.goToOffset = function(offset){
$scope.options.offset = offset;
$scope.reloadView();
};
$scope.sort = function(field){
$scope.options.sortby = field;
if(field !== $scope.options.sortby){
if($scope.options.order === "desc"){
$scope.options.order = "asc";
}else{
$scope.options.order = "desc";
}
}
$scope.reloadView();
};
$scope.prev = function(){
if($scope.options.offset > 0){
$scope.options.offset--;
$scope.reloadView();
}
};
/*Loads the search results, based on parameters set in prev,next,sort and so on*/
/*Pagination is done by an array of objects, due angularJS's funky way of monitoring state
with simple values */
$scope.reloadView = function(){
$scope.listViewResultSet = contentResource.getChildren($scope.content.id, $scope.options);
$scope.pagination = [];
for (var i = $scope.listViewResultSet.pages - 1; i >= 0; i--) {
$scope.pagination[i] = {index: i, name: i+1};
};
if($scope.options.offset > $scope.listViewResultSet.pages){
$scope.options.offset = $scope.listViewResultSet.pages;
}
};
$scope.reloadView();
});
//this controller simply tells the dialogs service to open a mediaPicker window
//with a specified callback, this callback will receive an object with a selection on it
angular.module('umbraco').controller("Umbraco.Editors.MediaPickerController",
function($rootScope, $scope, dialogService, $log){
$scope.openMediaPicker =function(value){
var d = dialogService.mediaPicker({scope: $scope, callback: populate});
};
function populate(data){
$log.log(data.selection);
$scope.model.value = data.selection;
}
});
angular.module("umbraco")
.controller("Umbraco.Editors.RTEController",
function($rootScope, $scope, dialogService, $log){
require(
[
'tinymce'
],
function (tinymce) {
tinymce.DOM.events.domLoaded = true;
tinymce.init({
selector: "#" + $scope.model.alias + "_rte",
skin: "umbraco",
menubar : false,
statusbar: false,
height: 340,
toolbar: "bold italic | styleselect | alignleft aligncenter alignright | bullist numlist | outdent indent | link image mediapicker",
setup : function(editor) {
editor.on('blur', function(e) {
$scope.$apply(function() {
//$scope.model.value = e.getBody().innerHTML;
$scope.model.value = editor.getContent();
});
});
editor.addButton('mediapicker', {
icon: 'media',
tooltip: 'Media Picker',
onclick: function(){
dialogService.mediaPicker({scope: $scope, callback: function(data){
//really simple example on how to intergrate a service with tinyMCE
$(data.selection).each(function (i, img) {
var imageProperty = _.find(img.properties, function(item) {
return item.alias == 'umbracoFile';
});
var data = {
src: imageProperty != null ? imageProperty.value : "nothing.jpg",
style: 'width: 100px; height: 100px',
id: '__mcenew'
};
editor.insertContent(editor.dom.createHTML('img', data));
var imgElm = editor.dom.get('__mcenew');
editor.dom.setAttrib(imgElm, 'id', null);
});
}});
}
});
}
});
$scope.openMediaPicker =function(value){
var d = dialog.mediaPicker({scope: $scope, callback: populate});
};
function bindValue(inst){
$log.log("woot");
$scope.$apply(function() {
$scope.model.value = inst.getBody().innerHTML;
});
}
function myHandleEvent(e){
$log.log(e);
}
function populate(data){
$scope.model.value = data.selection;
}
});
});
angular.module("umbraco")
.controller("Umbraco.Editors.TagsController",
function($rootScope, $scope, $log, tagsResource) {
require(
[
'/belle/views/propertyeditors/umbraco/tags/bootstrap-tags.custom.js',
'css!/belle/views/propertyeditors/umbraco/tags/bootstrap-tags.custom.css'
],function(){
// Get data from tagsFactory
$scope.tags = tagsResource.getTags("group");
// Initialize bootstrap-tags.js script
var tags = $('#' + $scope.model.alias + "_tags").tags({
tagClass: 'label-inverse'
});
$.each($scope.tags, function(index, tag) {
tags.addTag(tag.label);
});
});
}
);
//this controller simply tells the dialogs service to open a mediaPicker window
//with a specified callback, this callback will receive an object with a selection on it
angular.module('umbraco').controller("Umbraco.Editors.EmbeddedContentController",
function($rootScope, $scope, $log){
$scope.showForm = false;
$scope.fakeData = [];
$scope.create = function(){
$scope.showForm = true;
$scope.fakeData = angular.copy($scope.model.config.fields);
};
$scope.show = function(){
$scope.showCode = true;
};
$scope.add = function(){
$scope.showForm = false;
if ( !($scope.model.value instanceof Array)) {
$scope.model.value = [];
}
$scope.model.value.push(angular.copy($scope.fakeData));
$scope.fakeData = [];
};
});
return angular;
});

View File

@@ -1,690 +0,0 @@
/*! umbraco - v0.0.1-SNAPSHOT - 2013-06-10
* http://umbraco.github.io/Belle
* Copyright (c) 2013 Per Ploug, Anders Stenteberg & Shannon Deminick;
* Licensed MIT
*/
'use strict';
define(['app','angular','underscore'], function (app, angular,_) {
angular.module("umbraco.directives", []);
angular.module("umbraco.directives")
.directive('autoScale', function ($window) {
return function (scope, el, attrs) {
var totalOffset = 0;
var offsety = parseInt(attrs.autoScale, 10);
var window = angular.element($window);
if (offsety !== undefined){
totalOffset += offsety;
}
setTimeout(function () {
el.height(window.height() - (el.offset().top + totalOffset));
}, 300);
window.bind("resize", function () {
el.height(window.height() - (el.offset().top + totalOffset));
});
};
});
/**
* @ngdoc directive
* @name umbraco.directive:umbFileUpload
* @description A directive applied to a file input box so that outer scopes can listen for when a file is selected
**/
function umbFileUpload() {
return {
scope: true, //create a new scope
link: function (scope, el, attrs) {
el.bind('change', function (event) {
var files = event.target.files;
//emit event upward
scope.$emit("filesSelected", { files: files });
});
}
};
}
angular.module('umbraco.directives').directive("umbFileUpload", umbFileUpload);
angular.module("umbraco.directives")
.directive('umbHeader', function($parse, $timeout){
return {
restrict: 'E',
replace: true,
transclude: 'true',
templateUrl: 'views/directives/umb-header.html',
//create a new isolated scope assigning a tabs property from the attribute 'tabs'
//which is bound to the parent scope property passed in
scope: {
tabs: "="
},
link: function (scope, iElement, iAttrs) {
if (!iAttrs.tabs){
throw "a 'tabs' attribute must be set for umbHeader which represents the collection of tabs";
}
//var hasProcessed = false;
//when the tabs change, we need to hack the planet a bit and force the first tab content to be active,
//unfortunately twitter bootstrap tabs is not playing perfectly with angular.
scope.$watch("tabs", function (newValue, oldValue) {
//don't process if we cannot or have already done so
if (!newValue) {return;}
//if (hasProcessed || !newValue.length || newValue.length == 0) return;
if (!newValue.length || newValue.length === 0){return;}
//set the flag
//hasProcessed = true;
var $panes = $('div.tab-content');
var activeTab = _.find(newValue, function (item) {
return item.active;
});
//we need to do a timeout here so that the current sync operation can complete
// and update the UI, then this will fire and the UI elements will be available.
$timeout(function () {
$panes.find('.tab-pane').each(function (index) {
var $this = angular.element(this);
if ($this.attr("rel") === String(activeTab.id)) {
$this.addClass('active');
}
else {
$this.removeClass('active');
}
});
});
});
}
};
});
angular.module("umbraco.directives")
.directive('headline', function ($window) {
return function (scope, el, attrs) {
var h1 = $("<h1 class='umb-headline-editor'></h1>").hide();
el.parent().prepend(h1);
el.addClass("umb-headline-editor");
if (el.val() !== '') {
el.hide();
h1.text(el.val());
h1.show();
} else {
el.focus();
}
el.on("blur", function () {
el.hide();
h1.html(el.val()).show();
});
h1.on("click", function () {
h1.hide();
el.show().focus();
});
};
});
/**
* @ngdoc directive
* @name umbraco.directive:leftColumn
* @restrict E
**/
function leftColumnDirective() {
return {
restrict: "E", // restrict to an element
replace: true, // replace the html element with the template
template: '<div ng-include="leftColumnViewFile"></div>',
link: function (scope, el, attrs) {
//set the loginViewFile
scope.leftColumnViewFile = "views/directives/umb-leftcolumn.html";
}
};
}
angular.module('umbraco.directives').directive("umbLeftColumn", leftColumnDirective);
/**
* @ngdoc directive
* @name umbraco.directive:login
* @restrict E
**/
function loginDirective() {
return {
restrict: "E", // restrict to an element
replace: true, // replace the html element with the template
template: '<div ng-include="loginViewFile"></div>',
link: function (scope, el, attrs) {
//set the loginViewFile
scope.loginViewFile = "views/directives/umb-login.html";
}
};
}
angular.module('umbraco.directives').directive("umbLogin", loginDirective);
/**
* @ngdoc directive
* @name umbraco.directive:notifications
* @restrict E
**/
function notificationDirective() {
return {
restrict: "E", // restrict to an element
replace: true, // replace the html element with the template
template: '<div ng-include="notificationViewFile"></div>',
link: function (scope, el, attrs) {
//set the notificationViewFile
scope.notificationViewFile = "views/directives/umb-notifications.html";
}
};
}
angular.module('umbraco.directives').directive("umbNotifications", notificationDirective);
angular.module("umbraco.directives")
.directive('umbPanel', function(){
return {
restrict: 'E',
replace: true,
transclude: 'true',
templateUrl: 'views/directives/umb-panel.html'
};
});
angular.module("umbraco.directives")
.directive('preventDefault', function () {
return function (scope, element, attrs) {
$(element).click(function (event) {
event.preventDefault();
});
};
});
angular.module("umbraco.directives")
.directive('umbProperty', function(){
return {
scope: true,
restrict: 'E',
replace: true,
templateUrl: 'views/directives/umb-property.html',
link: function (scope, element, attrs) {
//let's make a requireJs call to try and retrieve the associated js
// for this view, only if its an absolute path, meaning its external to umbraco
if (scope.model.view && scope.model.view !== "" && scope.model.view.startsWith('/')) {
//get the js file which exists at ../Js/EditorName.js
var lastSlash = scope.model.view.lastIndexOf("/");
var fullViewName = scope.model.view.substring(lastSlash + 1, scope.model.view.length);
var viewName = fullViewName.indexOf(".") > 0 ? fullViewName.substring(0, fullViewName.indexOf(".")) : fullViewName;
var jsPath = scope.model.view.substring(0, lastSlash + 1) + "../Js/" + viewName + ".js";
require([jsPath],
function () {
//the script loaded so load the view
//NOTE: The use of $apply because we're operating outside of the angular scope with this callback.
scope.$apply(function () {
scope.model.editorView = scope.model.view;
});
}, function (err) {
//an error occurred... most likely there is no JS file to load for this editor
//NOTE: The use of $apply because we're operating outside of the angular scope with this callback.
scope.$apply(function () {
scope.model.editorView = scope.model.view;
});
});
}
else {
scope.model.editorView = scope.model.view;
}
}
};
});
angular.module("umbraco.directives")
.directive('umbTab', function(){
return {
restrict: 'E',
replace: true,
transclude: 'true',
templateUrl: 'views/directives/umb-tab.html'
};
});
angular.module("umbraco.directives")
.directive('umbTabView', function(){
return {
restrict: 'E',
replace: true,
transclude: 'true',
templateUrl: 'views/directives/umb-tab-view.html'
};
});
angular.module("umbraco.directives")
.directive('umbTree', function ($compile, $log, $q, treeService) {
return {
restrict: 'E',
replace: true,
terminal: false,
scope: {
section: '@',
showoptions: '@',
showheader: '@',
cachekey: '@'
},
compile: function (element, attrs) {
//config
var hideheader = (attrs.showheader === 'false') ? true : false;
var hideoptions = (attrs.showoptions === 'false') ? "hide-options" : "";
var template = '<ul class="umb-tree ' + hideoptions + '">' +
'<li class="root">';
if(!hideheader){
template +='<div>' +
'<h5><a class="root-link">{{tree.name}}</a><i class="umb-options"><i></i><i></i><i></i></i></h5>' +
'</div>';
}
template += '<ul>' +
'<umb-tree-item ng-repeat="child in tree.children" node="child" section="{{section}}"></umb-tree-item>' +
'</ul>' +
'</li>' +
'</ul>';
var newElem = $(template);
element.replaceWith(template);
return function (scope, element, attrs, controller) {
function loadTree(){
if(scope.section){
$q.when(treeService.getTree({ section: scope.section, cachekey: scope.cachekey }))
.then(function (data) {
//set the data once we have it
scope.tree = data;//.children;
}, function (reason) {
alert(reason);
return;
});
// scope.tree = treeService.getTree({section:scope.section, cachekey: scope.cachekey});
}
}
//watch for section changes
if(scope.node === undefined){
scope.$watch("section",function (newVal, oldVal) {
if(!newVal){
scope.tree = undefined;
scope.node = undefined;
}else if(newVal !== oldVal){
loadTree();
}
});
}
//initial change
loadTree();
};
}
};
});
angular.module("umbraco.directives")
.directive('umbTreeItem', function($compile, $http, $templateCache, $interpolate, $log, treeService) {
return {
restrict: 'E',
replace: true,
scope: {
section: '@',
cachekey: '@',
node:'='
},
template: '<li><div ng-style="setTreePadding(node)">' +
'<ins ng-class="{\'icon-caret-right\': !node.expanded, \'icon-caret-down\': node.expanded}" ng-click="load(node)"></ins>' +
'<i class="{{node | umbTreeIconClass:\'icon umb-tree-icon sprTree\'}}" style="{{node | umbTreeIconStyle}}"></i>' +
'<a ng-click="select(this, node, $event)" ng-href="#{{node.view}}">{{node.name}}</a>' +
'<i class="umb-options" ng-click="options(this, node, $event)"><i></i><i></i><i></i></i>' +
'</div>'+
'</li>',
link: function (scope, element, attrs) {
scope.options = function(e, n, ev){
scope.$emit("treeOptionsClick", {element: e, node: n, event: ev});
};
scope.select = function(e,n,ev){
scope.$emit("treeNodeSelect", {element: e, node: n, event: ev});
};
scope.load = function (node) {
if (node.expanded){
node.expanded = false;
node.children = [];
}else {
treeService.getChildren( { node: node, section: scope.section } )
.then(function (data) {
node.children = data;
node.expanded = true;
}, function (reason) {
alert(reason);
return;
});
}
};
scope.setTreePadding = function(node) {
return { 'padding-left': (node.level * 20) + "px" };
};
var template = '<ul ng-class="{collapsed: !node.expanded}"><umb-tree-item ng-repeat="child in node.children" node="child" section="{{section}}"></umb-tree-item></ul>';
var newElement = angular.element(template);
$compile(newElement)(scope);
element.append(newElement);
}
};
});
/**
* @description Utillity directives for key and field events
**/
angular.module('umbraco.directives')
.directive('onKeyup', function () {
return function (scope, elm, attrs) {
elm.bind("keyup", function () {
scope.$apply(attrs.onKeyup);
});
};
})
.directive('onKeyDown', function ($key) {
return {
link: function (scope, elm, attrs) {
$key('keydown', scope, elm, attrs);
}
};
})
.directive('onBlur', function () {
return function (scope, elm, attrs) {
elm.bind("blur", function () {
scope.$apply(attrs.onBlur);
});
};
})
.directive('onFocus', function () {
return function (scope, elm, attrs) {
elm.bind("focus", function () {
scope.$apply(attrs.onFocus);
});
};
});
/**
* @ngdoc directive
* @name umbraco.directive:valBubble
* @restrict A
* @description This directive will bubble up a notification via an emit event (upwards)
describing the state of the validation element. This is useful for
parent elements to know about child element validation state.
**/
function valBubble(umbFormHelper) {
return {
require: 'ngModel',
restrict: "A",
link: function (scope, element, attr, ctrl) {
if (!attr.name) {
throw "valBubble must be set on an input element that has a 'name' attribute";
}
var currentForm = umbFormHelper.getCurrentForm(scope);
if (!currentForm || !currentForm.$name){
throw "valBubble requires that a name is assigned to the ng-form containing the validated input";
}
//watch the current form's validation for the current field name
scope.$watch(currentForm.$name + "." + ctrl.$name + ".$valid", function (isValid, lastValue) {
if (isValid !== undefined) {
//emit an event upwards
scope.$emit("valBubble", {
isValid: isValid, // if the field is valid
element: element, // the element that the validation applies to
expression: this.exp, // the expression that was watched to check validity
scope: scope, // the current scope
ctrl: ctrl // the current controller
});
}
});
}
};
}
angular.module('umbraco.directives').directive("valBubble", valBubble);
/**
* @ngdoc directive
* @name umbraco.directive:valRegex
* @restrict A
* @description A custom directive to allow for matching a value against a regex string.
* NOTE: there's already an ng-pattern but this requires that a regex expression is set, not a regex string
**/
function valRegex() {
return {
require: 'ngModel',
restrict: "A",
link: function (scope, elm, attrs, ctrl) {
var regex = new RegExp(scope.$eval(attrs.valRegex));
var patternValidator = function (viewValue) {
//NOTE: we don't validate on empty values, use required validator for that
if (!viewValue || regex.test(viewValue)) {
// it is valid
ctrl.$setValidity('valRegex', true);
//assign a message to the validator
ctrl.errorMsg = "";
return viewValue;
}
else {
// it is invalid, return undefined (no model update)
ctrl.$setValidity('valRegex', false);
//assign a message to the validator
ctrl.errorMsg = "Value is invalid, it does not match the correct pattern";
return undefined;
}
};
ctrl.$formatters.push(patternValidator);
ctrl.$parsers.push(patternValidator);
}
};
}
angular.module('umbraco.directives').directive("valRegex", valRegex);
/**
* @ngdoc directive
* @name umbraco.directive:valServer
* @restrict A
* @description This directive is used to associate a field with a server-side validation response
* so that the validators in angular are updated based on server-side feedback.
**/
function valServer() {
return {
require: 'ngModel',
restrict: "A",
link: function (scope, element, attr, ctrl) {
if (!scope.model || !scope.model.alias){
throw "valServer can only be used in the scope of a content property object";
}
var parentErrors = scope.$parent.serverErrors;
if (!parentErrors) {
return;
}
var fieldName = scope.$eval(attr.valServer);
//subscribe to the changed event of the element. This is required because when we
// have a server error we actually invalidate the form which means it cannot be
// resubmitted. So once a field is changed that has a server error assigned to it
// we need to re-validate it for the server side validator so the user can resubmit
// the form. Of course normal client-side validators will continue to execute.
element.keydown(function () {
if (ctrl.$invalid) {
ctrl.$setValidity('valServer', true);
}
});
element.change(function () {
if (ctrl.$invalid) {
ctrl.$setValidity('valServer', true);
}
});
//TODO: DO we need to watch for other changes on the element ?
//subscribe to the server validation changes
parentErrors.subscribe(scope.model, fieldName, function (isValid, propertyErrors, allErrors) {
if (!isValid) {
ctrl.$setValidity('valServer', false);
//assign an error msg property to the current validator
ctrl.errorMsg = propertyErrors[0].errorMsg;
}
else {
ctrl.$setValidity('valServer', true);
//reset the error message
ctrl.errorMsg = "";
}
}, true);
}
};
}
angular.module('umbraco.directives').directive("valServer", valServer);
/**
* @ngdoc directive
* @name umbraco.directive:valSummary
* @restrict E
* @description This directive will display a validation summary for the current form based on the
content properties of the current content item.
**/
function valSummary() {
return {
scope: true, // create a new scope for this directive
replace: true, // replace the html element with the template
restrict: "E", // restrict to an element
template: '<ul class="validation-summary"><li ng-repeat="model in validationSummary">{{model}}</li></ul>',
link: function (scope, element, attr, ctrl) {
//create properties on our custom scope so we can use it in our template
scope.validationSummary = [];
//create a flag for us to be able to reference in the below closures for watching.
var showValidation = false;
//add a watch to update our waitingOnValidation flag for use in the below closures
scope.$watch("$parent.ui.waitingOnValidation", function (isWaiting, oldValue) {
showValidation = isWaiting;
if (scope.validationSummary.length > 0 && showValidation) {
element.show();
}
else {
element.hide();
}
});
//if we are to show field property based errors.
//this requires listening for bubbled events from valBubble directive.
scope.$parent.$on("valBubble", function (evt, args) {
var msg = "The value assigned for the property " + args.scope.model.label + " is invalid";
var exists = _.contains(scope.validationSummary, msg);
//we need to check if the entire property is valid, even though the args says this field is valid there
// may be multiple values attached to a content property. The easiest way to do this is check the DOM
// just like we are doing for the property level validation message.
var propertyHasErrors = args.element.closest(".content-property").find(".ng-invalid").length > 0;
if (args.isValid && exists && !propertyHasErrors) {
//it is valid but we have a val msg for it so we'll need to remove the message
scope.validationSummary = _.reject(scope.validationSummary, function (item) {
return item === msg;
});
}
else if (!args.isValid && !exists) {
//it is invalid and we don't have a msg for it already
scope.validationSummary.push(msg);
}
//show the summary if there are errors and the form has been submitted
if (showValidation && scope.validationSummary.length > 0) {
element.show();
}
});
//listen for form invalidation so we know when to hide it
scope.$watch("contentForm.$error", function (errors) {
//check if there is an error and hide the summary if not
var hasError = _.find(errors, function (err) {
return (err.length && err.length > 0);
});
if (!hasError) {
element.hide();
}
}, true);
}
};
}
angular.module('umbraco.directives').directive("valSummary", valSummary);
/**
* @ngdoc directive
* @name umbraco.directive:valToggleMsg
* @restrict A
* @description This directive will show/hide an error based on: is the value + the given validator invalid? AND, has the form been submitted ?
**/
function valToggleMsg(umbFormHelper) {
return {
restrict: "A",
link: function (scope, element, attr, ctrl) {
if (!attr.valToggleMsg){
throw "valToggleMsg requires that a reference to a validator is specified";
}
if (!attr.valMsgFor){
throw "valToggleMsg requires that the attribute valMsgFor exists on the element";
}
//create a flag for us to be able to reference in the below closures for watching.
var showValidation = false;
var hasError = false;
var currentForm = umbFormHelper.getCurrentForm(scope);
if (!currentForm || !currentForm.$name){
throw "valToggleMsg requires that a name is assigned to the ng-form containing the validated input";
}
//add a watch to the validator for the value (i.e. $parent.myForm.value.$error.required )
scope.$watch(currentForm.$name + "." + attr.valMsgFor + ".$error." + attr.valToggleMsg, function (isInvalid, oldValue) {
hasError = isInvalid;
if (hasError && showValidation) {
element.show();
}
else {
element.hide();
}
});
//add a watch to update our waitingOnValidation flag for use in the above closure
scope.$watch("$parent.ui.waitingOnValidation", function (isWaiting, oldValue) {
showValidation = isWaiting;
if (hasError && showValidation) {
element.show();
}
else {
element.hide();
}
});
}
};
}
angular.module('umbraco.directives').directive("valToggleMsg", valToggleMsg);
return angular;
});

View File

@@ -1,69 +0,0 @@
/*! umbraco - v0.0.1-SNAPSHOT - 2013-06-10
* http://umbraco.github.io/Belle
* Copyright (c) 2013 Per Ploug, Anders Stenteberg & Shannon Deminick;
* Licensed MIT
*/
'use strict';
define([ 'app','angular'], function (app,angular) {
angular.module('umbraco.filters', []);
/**
* @ngdoc filter
* @name umbraco.filters:propertyEditor
* @description This will ensure that the view for the property editor is rendered correctly, meaning it will check for an absolute path, otherwise load it in the normal umbraco path
**/
function propertyEditorFilter($log) {
return function (input) {
//if its not defined then return undefined
if (!input){
return input;
}
//Added logging here because this fires a ton of times and not sure that it should be!
//$log.info("Filtering property editor view: " + input);
var path = String(input);
if (path.startsWith('/')) {
return path;
}
else {
return "views/propertyeditors/" + path.replace('.', '/') + "/editor.html";
}
};
}
angular.module("umbraco.filters").filter('propertyEditor', propertyEditorFilter);
/**
* @ngdoc filter
* @name umbraco.filters:umbTreeIconClass
* @restrict E
* @description This will properly render the tree icon class based on the tree icon set on the server
**/
function treeIconClassFilter() {
return function (treeNode, standardClasses) {
if (treeNode.iconIsClass) {
return standardClasses + " " + treeNode.icon;
}
return standardClasses;
};
}
angular.module('umbraco.filters').filter("umbTreeIconClass", treeIconClassFilter);
/**
* @ngdoc filter
* @name umbraco.filters:umbTreeIconImage
* @restrict E
* @description This will properly render the tree icon image based on the tree icon set on the server
**/
function treeIconImageFilter() {
return function (treeNode) {
if (treeNode.iconIsClass) {
return "";
}
return "<img src='" + treeNode.iconFilePath + "'></img>";
};
}
//angular.module('umbraco.filters').filter("umbTreeIconImage", treeIconImageFilter);
return app;
});

View File

@@ -1,6 +1,6 @@
var app = angular.module('umbraco', [
'umbraco.filters',
'umbraco.directives',
'umbraco.mocks.resources',
'umbraco.resources',
'umbraco.services'
]);

View File

@@ -0,0 +1,6 @@
var app = angular.module('umbraco', [
'umbraco.filters',
'umbraco.directives',
'umbraco.mocks.resources',
'umbraco.services'
]);

View File

@@ -47,7 +47,7 @@ require.config({
require( [
'angular',
'app',
'app_dev',
'jquery',
'jqueryCookie',
'bootstrap',