Skip to content

Commit

Permalink
Merge branch 'development'
Browse files Browse the repository at this point in the history
  • Loading branch information
Tihomir-Petrov committed Jan 9, 2015
2 parents f3eec0e + 9e1e06b commit a666004
Show file tree
Hide file tree
Showing 33 changed files with 1,294 additions and 547 deletions.
8 changes: 5 additions & 3 deletions Gruntfile.js
Expand Up @@ -12,7 +12,7 @@ module.exports = function (grunt) {
'Telerik.Sitefinity.Frontend/Designers/Scripts/*.js',
'Telerik.Sitefinity.Frontend/MVC/Scripts/*.js',
'Telerik.Sitefinity.Frontend/MVC/Scripts/Designer/*.js',
'Telerik.Sitefinity.Frontend/client=components/selectors/**/*.js'
'Telerik.Sitefinity.Frontend/client-components/selectors/**/*.js'
]
},

Expand All @@ -27,6 +27,7 @@ module.exports = function (grunt) {
'Telerik.Sitefinity.Frontend/client-components/selectors/common/sf-selectors.js',
'Telerik.Sitefinity.Frontend/client-components/selectors/common/sf-list-selector.js',
'Telerik.Sitefinity.Frontend/client-components/selectors/common/sf-items-tree.js',
'Telerik.Sitefinity.Frontend/client-components/selectors/common/sf-selected-items-view.js',
'Telerik.Sitefinity.Frontend/client-components/selectors/news/sf-news-item-service.js',
'Telerik.Sitefinity.Frontend/client-components/selectors/news/sf-news-selector.js',
'Telerik.Sitefinity.Frontend/client-components/selectors/dynamic-modules/sf-data-service.js',
Expand All @@ -45,8 +46,9 @@ module.exports = function (grunt) {
'Tests/Telerik.Sitefinity.Frontend.ClientTest/helpers/angular-resource.js',
'Tests/Telerik.Sitefinity.Frontend.ClientTest/helpers/angular-route.js',
'Tests/Telerik.Sitefinity.Frontend.ClientTest/helpers/angular-mocks.js',
'Tests/Telerik.Sitefinity.Frontend.ClientTest/helpers/kendo.web.min.js',
'Tests/Telerik.Sitefinity.Frontend.ClientTest/helpers/angular-kendo.js',
'Tests/Telerik.Sitefinity.Frontend.ClientTest/helpers/kendo.all.min.js',
'Tests/Telerik.Sitefinity.Frontend.ClientTest/helpers/common-methods.js',
'Tests/Telerik.Sitefinity.Frontend.ClientTest/helpers/jasmine-matchers.js',
'Telerik.Sitefinity.Frontend/MVC/Scripts/Bootstrap/js/*.js',
'!Telerik.Sitefinity.Frontend/Mvc/Scripts/Angular/**'
],
Expand Down
118 changes: 62 additions & 56 deletions Telerik.Sitefinity.Frontend/Mvc/Scripts/Kendo/kendo.all.min.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Telerik.Sitefinity.Frontend/Properties/AssemblyInfo.cs
Expand Up @@ -30,8 +30,8 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.1.20.3")]
[assembly: AssemblyFileVersion("1.1.20.3")]
[assembly: AssemblyVersion("1.1.30.1")]
[assembly: AssemblyFileVersion("1.1.30.1")]

[assembly: ControllerContainer]

Expand Down
Expand Up @@ -35,7 +35,7 @@ protected override bool CurrentExists(PathDefinition definition, string virtualP
{
var controlPresentation = this.GetControlPresentation(definition, virtualPath);
result = controlPresentation != null && !controlPresentation.Data.IsNullOrEmpty();

cacheManager.Add(key, result, Microsoft.Practices.EnterpriseLibrary.Caching.CacheItemPriority.Normal, null, this.GetControlPresentationsCacheExpirations());
}
}
Expand Down Expand Up @@ -100,16 +100,7 @@ protected override IEnumerable<string> GetCurrentFiles(PathDefinition definition
if (controllers == null)
return null;

var dynamicType = ControllerExtensions.GetDynamicContentType(controllerName);
var areaName = definition.ResolverName;

// case for dynamic type
if (dynamicType != null)
{
var moduleProvider = Telerik.Sitefinity.DynamicModules.Builder.ModuleBuilderManager.GetManager().Provider;
var dynamicModule = moduleProvider.GetDynamicModule(dynamicType.ParentModuleId);
areaName = this.GetDynamicTypeAreaName(dynamicModule.Title, dynamicType.DisplayName);
}
string areaName = this.GetAreaName(controllerName);

result = this.GetViewPaths(path, controllers, areaName);

Expand Down Expand Up @@ -156,21 +147,7 @@ protected virtual ControlPresentation GetControlPresentation(PathDefinition virt
else
controllerName = string.Empty;

var dynamicType = ControllerExtensions.GetDynamicContentType(controllerName);

string areaName;

// case for dynamic types
if (dynamicType != null)
{
var moduleProvider = Telerik.Sitefinity.DynamicModules.Builder.ModuleBuilderManager.GetManager().Provider;
var dynamicModule = moduleProvider.GetDynamicModule(dynamicType.ParentModuleId);
areaName = this.GetDynamicTypeAreaName(dynamicModule.Title, dynamicType.DisplayName);
}
else
{
areaName = virtualPathDefinition.ResolverName;
}
string areaName = this.GetAreaName(controllerName);

return this.GetControlPresentationItem(controllers, name, areaName);
}
Expand Down Expand Up @@ -230,6 +207,27 @@ private ControlPresentation GetControlPresentationItem(IEnumerable<string> contr
return returnResult;
}

/// <summary>
/// Gets the name of the area.
/// </summary>
/// <param name="controllerName">Name of the controller.</param>
/// <returns></returns>
private string GetAreaName(string controllerName)
{
var dynamicType = ControllerExtensions.GetDynamicContentType(controllerName);
string areaName = controllerName;

// case for dynamic types
if (dynamicType != null)
{
var moduleProvider = Telerik.Sitefinity.DynamicModules.Builder.ModuleBuilderManager.GetManager().Provider;
var dynamicModule = moduleProvider.GetDynamicModule(dynamicType.ParentModuleId);
areaName = this.GetDynamicTypeAreaName(dynamicModule.Title, dynamicType.DisplayName);
}

return areaName;
}

/// <summary>
/// Gets the area name for dynamic content MVC widget.
/// </summary>
Expand Down
@@ -1,5 +1,4 @@
 <div kendo-tree-view="treeView"
k-data-source="itemsDataSource"
k-template="itemTemplate"
k-checkboxes="sfMultiselect ? checkboxes : false"
k-load-on-demand="true"
Expand Down
Expand Up @@ -79,11 +79,68 @@
constructPredecessorsTree: constructPredecessorsTree
};
});

/**
* Wrapper that extends the kendo's HierarchicalDataSource
* with ability to fetch tree levels from both already constructed tree and a web service.
*/
module.factory('sfHybridHierarchicalDataSource', function () {
function getFromAvailableItems(data, id) {
if (!id) {
return data;
}
else if(data) {
for (var i = 0; i < data.length; i++) {
if (data[i].Id === id) {
return data[i].items;
}
else if (data[i].items) {
var result = getFromAvailableItems(data[i].items, id);
if (result) return result;
}
}
}
}

function createDataSource(model, tree, getChildren) {
return new kendo.data.HierarchicalDataSource({
schema: {
model: model
},
transport: {
read: function (options) {
var id = options.data.Id;
var availableItems = getFromAvailableItems(tree, id);
if (availableItems) {
options.success(availableItems);
}
else if(id) {
getChildren(id).then(function (children) {
options.success(children);
});
}
}
}
});
}

module.directive('sfItemsTree', ['serverContext', 'sfTreeHelper', '$q', function (serverContext, sfTreeHelper, $q) {
return {
getDataSource: function (model, tree, getChildren) {
var dataSource = createDataSource(model, tree, getChildren);
dataSource.data(tree);

return dataSource;
}
};
});

module.directive('sfItemsTree', ['serverContext', 'sfTreeHelper', 'sfHybridHierarchicalDataSource', '$q',
function (serverContext, sfTreeHelper, sfHybridHierarchicalDataSource, $q) {
return {
restrict: 'E',
scope: {
// The class indicating the element with max-height and overflow-y:auto.
sfScrollContainerClass: '@',
sfMultiselect: '=',
sfExpandSelection: '=',
sfItemsPromise: '=',
Expand All @@ -102,9 +159,19 @@
},
link: function (scope, element, attrs) {
/* Helper methods */
var predecessorsTree;
var predecessorsTreePromise = $q.defer();

var kendoTreeCreatedPromise = $q.defer();

var model = {
id: 'Id',
hasChildren: 'HasChildren'
};

/**
* Retrieves collection of predecessors and constructs a tree.
* @param {String} selectedIds the Id of the selected item
* @return {Promise} a promise for the tree
*/
var constructPredecessorsTree = function (selectedIds) {
var selectedId = selectedIds[0];
return scope.sfGetPredecessors({ itemId: selectedId })
Expand All @@ -113,84 +180,95 @@
});
};

var getFromAvailableItems = function (data, id) {
if (!id) {
return data;
}
else if(data) {
for (var i = 0; i < data.length; i++) {
if (data[i].Id === id) {
return data[i].items;
}
else if (data[i].items) {
var result = getFromAvailableItems(data[i].items, id);
if (result) return result;
}
}
}
};

/**
* Determines whether the tree should be expanded to the selected item.
*/
var shouldExpandTree = function (scope) {
return scope.sfSelectedIds &&
scope.sfSelectedIds.length > 0 &&
!scope.sfMultiselect &&
scope.sfExpandSelection
scope.sfExpandSelection;
};

/* Scope properties */
scope.itemsDataSource = new kendo.data.HierarchicalDataSource({
schema: {
model: {
id: 'Id',
hasChildren: 'HasChildren'
}
},
transport: {
read: function (options) {
var id = options.data.Id;
var availableItems = getFromAvailableItems(predecessorsTree && predecessorsTree.items, id);
if (availableItems) {
options.success(availableItems);
}
else if(id) {
scope.sfGetChildren({ parentId: id })
.then(function (children) {
options.success(children);
});
}
}
}
});
var getChildrenCallback = function (id) {
return scope.sfGetChildren({ parentId: id });
};

scope.sfItemsPromise.then(function (newValue) {
if (shouldExpandTree(scope)) {
// We have to expand only in single selection mode and when there is selected item.
// The user of the directive can also disable this behaviour.
constructPredecessorsTree(scope.sfSelectedIds)
.then(function (constructedTree) {
predecessorsTree = constructedTree;
/**
* Creates a hybrid data source and sets it to the tree.
*/
var bindDataSource = function (items) {
var itemsDataSource = sfHybridHierarchicalDataSource
.getDataSource(model, items, getChildrenCallback);

scope.itemsDataSource.data(predecessorsTree.items);
scope.treeView.setDataSource(itemsDataSource);
};

predecessorsTreePromise.resolve();
});
}
else {
scope.itemsDataSource.data(newValue);
}
});
/**
* Expand the tree after the items are loaded and the kendo tree widget is created.
*/
var expandTreeToSelectedItem = function () {
$q.all([
constructPredecessorsTree(scope.sfSelectedIds),
kendoTreeCreatedPromise.promise])
.then(function (promiseResults) {
var predecessorsTree = promiseResults[0];
bindDataSource(predecessorsTree.items);

return predecessorsTree;
})
.then(function (predecessorsTree) {
scope.treeView.expandPath(predecessorsTree.parentsIds);
})
.then(scrollToSelectedItem);
};

/**
* Bind the provided from the user items into the tree.
*/
var setItemsIntoTree = function () {
$q.all([
scope.sfItemsPromise,
kendoTreeCreatedPromise.promise])
.then(function (promiseResults) {
var items = promiseResults[0];
bindDataSource(items);
});
};

/**
* Scrolls the items list in order to show the selected item.
*/
var scrollToSelectedItem = function () {
if (!scope.sfScrollContainerClass) return;

//scroll to the selected element
var selectedId = scope.sfSelectedIds[0],
selectedDataNode = scope.treeView.dataSource.get(selectedId),
selectedTreeNode = scope.treeView.findByUid(selectedDataNode.uid),
container = $('.' + scope.sfScrollContainerClass),
scrollTop = container.scrollTop() - container.offset().top + selectedTreeNode.offset().top,
middleOffset = container.height() /2 + selectedTreeNode.height() /2;

container.animate({
scrollTop: scrollTop - middleOffset
}, 600);
};

scope.$on("kendoWidgetCreated", function(event, widget){
// the event is emitted for every widget
// if we have multiple widgets, we need to check that the event
// is for the one we're interested in.
if (widget === scope.treeView && shouldExpandTree(scope)) {
predecessorsTreePromise.promise.then(function () {
scope.treeView.expandPath(predecessorsTree.parentsIds);
});
// check if the event is emmited from our widget
if (widget === scope.treeView) {
kendoTreeCreatedPromise.resolve();
}
});

if (shouldExpandTree(scope)) {
expandTreeToSelectedItem();
}
else {
setItemsIntoTree();
}

scope.checkboxes = {
template: '<input type="checkbox" ng-click="sfSelectItem({ dataItem: dataItem })" ng-checked="sfItemSelected({dataItem: dataItem})" ng-hide="sfItemDisabled({dataItem: dataItem})">'
};
Expand Down

0 comments on commit a666004

Please sign in to comment.