add un-text, un-boxes & un-figure directives

This commit is contained in:
2019-08-30 15:40:22 +02:00
parent 6b0496af4b
commit 26f587766d
3 changed files with 440 additions and 29 deletions
@@ -89,7 +89,7 @@
line-height: 20px;
position: relative;
margin-top: 1px;
padding: 20px 5px;
padding: 20px 0;
color: #1b264f;
border-radius: 3px 3px 0 0;
border-bottom: none;
@@ -157,7 +157,30 @@
overflow: hidden;
margin-top: 4px;
display: block;
line-height: 18px;
line-height: 20px;
}
.unesting-item-header.no-label .unesting-item-header-content-name
{
display: none;
}
.unesting-item-header.no-label .unesting-item-header-content-text
{
margin-top: 0;
}
.unesting-item-header.as-columns .unesting-item-header-content-text
{
display: flex;
flex-direction: row;
align-items: center;
grid-gap: 12px;
}
un-config
{
display: none !important;
}
/* icons */
@@ -303,6 +326,7 @@
/* media */
.unesting-media
{
display: flex;
@@ -334,7 +358,7 @@
.unesting-media-item-text
{
padding: 0 15px;
max-width: 100px;
max-width: 140px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
@@ -346,8 +370,8 @@
max-width: 100%;
height: auto;
vertical-align: middle;
width: 50px;
height: 50px;
width: 60px;
height: 60px;
background: #f6f4f4;
display: inline-flex;
justify-content: center;
@@ -356,6 +380,101 @@
border-radius: 4px;
}
[unesting-size="large"] .unesting-media-more,
[unesting-size="high"] .unesting-media-more
{
width: 100px;
height: 100px;
}
/* text partial */
.unesting-text
{
white-space: normal;
max-width: 800px;
display: box;
display: -webkit-box;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
.unesting-text-partial:before
{
content: ' ';
}
.unesting-text-partial:first-child:before
{
display: none;
}
/* boxes */
.unesting-boxes
{
display: flex;
flex-direction: row;
flex-wrap: wrap;
flex-shrink: 0;
grid-gap: 12px;
margin-top: 4px;
white-space: normal;
}
.unesting-boxes-item,
.unesting-boxes-more
{
background: #f6f4f4;
border-radius: 4px;
width: 180px;
min-height: 60px;
max-height: 65px;
padding: 10px 15px;
display: block;
}
.unesting-boxes-item-headline
{
display: block;
font-weight: 600;
font-size: 14px;
white-space: nowrap;
text-overflow: ellipsis;
color: #1b264f;
height: 20px;
overflow: hidden;
margin-bottom: 5px;
}
.unesting-boxes-item-text
{
display: -webkit-box;
text-overflow: ellipsis;
overflow: hidden;
-webkit-line-clamp: 2;
max-height: 40px;
}
.unesting-boxes-more
{
width: 50px;
vertical-align: middle;
display: inline-flex;
justify-content: center;
align-items: center;
}
[unesting-size="large"] .unesting-boxes-item,
[unesting-size="large"] .unesting-boxes-more
{
min-height: 120px;
max-height: 125px;
}
/* footer */
.unesting-footer
@@ -369,11 +488,53 @@
}
/* figure */
.unesting-figure
{
display: flex;
flex-direction: row;
align-items: center;
grid-gap: 12px;
max-width: 800px;
}
.unesting-figure un-media
{
flex-shrink: 0;
}
.unesting-figure-content
{
margin-top: 2px;
max-width: 800px;
}
.unesting-figure-headline
{
display: block;
font-size: 14px;
color: #1b264f;
font-weight: 600;
margin-bottom: 4px;
}
.unesting-figure-text
{
display: -webkit-box;
text-overflow: ellipsis;
overflow: hidden;
-webkit-line-clamp: 2;
max-height: 40px;
white-space: normal;
}
/* doctypepicker */
.unesting-doctype-textarea
{
width: 100%;
height: 32px;
height: 64px;
max-height: 200px;
min-height: 32px;
padding-top: 6px;
@@ -390,9 +551,31 @@
/* data type overrides */
.unesting-item .umb-sortable-thumbnails li
.unesting-item[unesting-alias="headline"] .unesting-text-partial[unesting-index="0"],
.unesting-item[unesting-alias="newsletterHeadline"] .unesting-text-partial[unesting-index="0"]
{
/*background: none;*/
font-size: 16px;
color: #1b264f;
font-weight: 600;
}
.unesting-item[unesting-alias="offset"] .unesting-item-header-content-name,
.unesting-item[unesting-alias="newsletterOffset"] .unesting-item-header-content-name
{
color: #817f85;
font-size: 13px;
font-weight: 400;
}
.unesting-item[unesting-alias="citation"] .unesting-figure-headline:before
{
content: '„';
}
.unesting-item[unesting-alias="citation"] .unesting-figure-headline:after
{
content: '“';
}
@@ -14,12 +14,14 @@
<div class="unesting-items" ng-hide="nodes.length === 0" ng-class="{ 'is-hidden': nodes.length === 0 }" ui-sortable="sortableOptions" ng-model="nodes">
<div class="unesting-item" ng-repeat="node in nodes" ng-class="{ 'is-active' : $parent.realCurrentNode.key === node.key, 'umb-nested-content__item--single' : $parent.singleMode, 'is-hidden': !!model.value[$index]['uNestingHide'] === '1' }">
<div class="unesting-item" ng-repeat="node in nodes"
unesting-alias="{{node.documentType.alias}}"
ng-class="{ 'is-active' : $parent.realCurrentNode.key === node.key, 'umb-nested-content__item--single' : $parent.singleMode, 'is-hidden': !!model.value[$index]['uNestingHide'] === '1' }">
<div class="unesting-item-header" ng-click="$parent.editNode($index)" ng-hide="$parent.singleMode">
<div class="umb-nested-content__header-bar unesting-item-header-inner">
<i ng-if="showIcons" class="icon" ng-class="$parent.getIcon($index)"></i>
<i ng-if="showIcons" class="icon" ng-class="$parent.getIcon($index)" title="{{node.contentTypeName}}"></i>
<div class="unesting-item-header-content" ng-class="{'--has-icon': showIcons}">
<span class="unesting-item-header-content-iconbg" ng-if="showIcons"></span>
<div class="unesting-item-header-content-name" ng-bind="node.contentTypeName"></div>
@@ -81,7 +83,7 @@
</div>
<div class="unesting-footer" ng-hide="hasContentTypes === false || nodes.length >= maxItems">
<button type="button" class="btn btn-info" ng-class="{ '--disabled': !scaffolds.length }" ng-click="openNodeTypePicker($event)">
<button type="button" class="btn btn-action" ng-class="{ '--disabled': !scaffolds.length }" ng-click="openNodeTypePicker($event)">
<localize key="grid_addElement"></localize>
</button>
</div>
@@ -108,49 +108,69 @@ angular.module('umbraco.directives').directive('unContent', function ($compile)
angular.module('umbraco.directives').directive('unMedia', function ($http, $compile, umbRequestHelper)
{
var sizes = {
small: 'width=30&height=30&mode=crop&quality=60',
medium: 'width=60&height=60&mode=crop&quality=60',
large: 'width=100&height=100&mode=crop&quality=60',
wide: 'width=100&height=60&mode=crop&quality=60',
high: 'width=60&height=100&mode=crop&quality=60'
};
return {
restrict: 'E',
scope: {
items: '=',
model: '=',
key: '@',
titleKey: '@',
limit: '@'
limit: '@',
size: '@',
hideLabel: '@'
},
template: '' +
'<div class="unesting-media">' +
'<div class="unesting-media-item" ng-repeat="item in media" ng-class="{\'has-title\': !!item.title}">' +
'<img src="{{item.src}}" title="{{item.title}}" class="unesting-media-item-image" />' +
'<span class="unesting-media-item-text" ng-if="item.title">{{item.title | unHtml }}</span>' +
'</div>' +
'<span class="unesting-media-more" ng-if="count > media.length">+{{count - media.length}}</span>' +
'</div>',
template: '<div class="unesting-media" unesting-size="{{_size}}">' +
'<div class="unesting-media-item" ng-repeat="item in media" ng-class="{\'has-title\': !!item.title}">' +
'<img src="{{item.src}}" title="{{item.title}}" class="unesting-media-item-image" />' +
'<span class="unesting-media-item-text" ng-if="item.title">{{item.title | unHtml }}</span>' +
'</div>' +
'<span class="unesting-media-more" ng-if="count > media.length">+{{count - media.length}}</span>' +
'</div>',
link: function (scope, element)
{
var resize = 'width=50&height=50&mode=crop&quality=60';
scope._size = sizes[scope.size] ? scope.size : 'medium';
var resize = sizes[scope._size];
var limit = scope.limit || 5;
scope.media = [];
var titleCache = {};
// compile & render template
function render()
{
var ids = scope.items;
var ids = scope.model;
if (!scope.items)
if (!scope.model)
{
return;
}
if (_.isArray(scope.items))
if (_.isArray(scope.model))
{
if (!scope.key)
if (typeof scope.model[0] !== 'string' && !scope.key)
{
console.error("You need the <un-media key='my_key' /> property for nested media");
return;
}
ids = _.map(scope.items, function (item)
ids = _.map(scope.model, function (item)
{
if (typeof item === 'string')
{
return item;
}
var value = item[scope.key];
if (scope.titleKey)
@@ -162,7 +182,7 @@ angular.module('umbraco.directives').directive('unMedia', function ($http, $comp
}).join(',');
}
ids = ids.split(',');
ids = _.filter(ids.split(','), function (id) { return !!id; });
scope.count = ids.length;
var query = "ids=" + ids.slice(0, limit).join('&ids=');
@@ -178,6 +198,12 @@ angular.module('umbraco.directives').directive('unMedia', function ($http, $comp
title: titleCache[id]
});
});
// hide label if requested
if (scope.media.length > 0 && (scope.hideLabel === true || scope.hideLabel === 'true' || scope.hideLabel === '1'))
{
element.closest('.unesting-item-header').addClass('no-label');
}
});
}
@@ -188,6 +214,206 @@ angular.module('umbraco.directives').directive('unMedia', function ($http, $comp
angular.module('umbraco.directives').directive('unText', function ($filter)
{
return {
restrict: 'E',
scope: {
model: '=',
maxLines: '@',
hideLabel: '@'
},
template: '<div class="unesting-text" ng-if="items.length" ng-style="{ \'-webkit-line-clamp\': {{maxLines}}, \'max-height\': \'{{maxLines * 20}}px\' }">' +
'<span class="unesting-text-partial" unesting-index="{{$index}}" ng-repeat="text in items" ng-bind-html="text"></span>' +
'</div>',
link: function (scope, element)
{
scope.maxLines = +scope.maxLines || 2;
scope.items = [];
if (!scope.model)
{
return;
}
// hide label if requested
if (scope.hideLabel === true || scope.hideLabel === 'true' || scope.hideLabel === '1')
{
element.closest('.unesting-item-header').addClass('no-label');
}
var partials = _.filter(!_.isArray(scope.model) ? [scope.model] : scope.model, function (text) { return !!text; });
scope.items = _.map(partials, function (text)
{
return $filter('unHtml')(text, 1000);
});
}
};
});
angular.module('umbraco.directives').directive('unBoxes', function ($compile)
{
return {
restrict: 'E',
scope: {
model: '=',
key: '@',
titleKey: '@',
limit: '@',
size: '@',
hideLabel: '@'
},
template: '<div class="unesting-boxes" unesting-size="{{size}}">' +
'<div class="unesting-boxes-item" ng-repeat="item in items" ng-class="{\'has-title\': !!item.title}">' +
'<span class="unesting-boxes-item-headline" ng-if="item.headline">{{item.headline | unHtml }}</span>' +
'<span class="unesting-boxes-item-text" ng-if="item.text" ng-style="{ \'max-height\': \'{{item.maxLines * 20}}px\', \'-webkit-line-clamp\': {{item.maxLines}} }">{{item.text | unHtml:200 }}</span>' +
'</div>' +
'<span class="unesting-boxes-more" ng-if="count > items.length">+{{count - items.length}}</span>' +
'</div>',
link: function (scope, element)
{
var maxLines = {
medium: 3,
large: 6
};
scope.size = maxLines[scope.size] ? scope.size : 'medium';
var limit = +scope.limit || 3;
scope.items = [];
if (!scope.model)
{
return;
}
// hide label if requested
if (scope.hideLabel === true || scope.hideLabel === 'true' || scope.hideLabel === '1')
{
element.closest('.unesting-item-header').addClass('no-label');
}
if (!_.isArray(scope.model))
{
console.error("The <un-boxes model='my_array' /> model has to be an array");
return;
}
if (_.isObject(scope.model[0]) && !scope.key)
{
console.error("You need the <un-boxes key='my_key' /> property for nested elements");
return;
}
var items = [];
_.each(scope.model, function (item)
{
var max = maxLines[scope.size];
if (item)
{
if (typeof item === 'string')
{
items.push({
maxLines: max,
text: item
});
}
var headline = item[scope.titleKey];
items.push({
maxLines: headline ? max - 1 : max,
headline: headline,
text: item[scope.key]
});
}
});
scope.items = items.slice(0, limit);
scope.count = items.length;
}
};
});
angular.module('umbraco.directives').directive('unFigure', function ($filter)
{
return {
restrict: 'E',
scope: {
image: '=',
text: '=',
headline: '=',
size: '@',
maxLines: '@',
hideLabel: '@'
},
template: '<div class="unesting-figure" ng-if="hasContent">' +
'<un-media ng-if="image" model="image" size="{{size}}" />' +
'<div class="unesting-figure-content">' +
'<span class="unesting-figure-headline" ng-if="headline">{{headline | unHtml }}</span>' +
'<span class="unesting-figure-text" ng-if="text" ng-style="{ \'max-height\': \'{{maxLines * 20}}px\', \'-webkit-line-clamp\': {{maxLines}} }">{{text | unHtml:800 }}</span>' +
'</div>' +
'</div>',
link: function (scope, element)
{
scope.hasContent = !!(scope.text || scope.headline || scope.image);
// hide label if requested
if (scope.hideLabel === true || scope.hideLabel === 'true' || scope.hideLabel === '1')
{
element.closest('.unesting-item-header').toggleClass('no-label', scope.hasContent);
}
// calculate max lines
scope.maxLines = +scope.maxLines || 3;
if (scope.headline)
{
scope.maxLines -= 1;
}
}
};
});
angular.module('umbraco.directives').directive('unConfig', function ($filter)
{
return {
restrict: 'E',
scope: {
hideLabel: '@',
asColumns: '@'
},
template: '',
link: function (scope, element)
{
if (scope.hideLabel === true || scope.hideLabel === 'true' || scope.hideLabel === '1')
{
element.closest('.unesting-item-header').addClass('no-label');
}
if (scope.asColumns === true || scope.asColumns === 'true' || scope.asColumns === '1')
{
element.closest('.unesting-item-header').addClass('as-columns');
}
}
};
});
angular.module('umbraco').filter('unHtml', function ()
{
return function (html, maxLength)
@@ -201,7 +427,7 @@ angular.module('umbraco').filter('unHtml', function ()
maxLength = 120;
}
var stripped = html.replace('<br>', ' ').replace('<br />', ' ').replace('<br/>', ' ').replace(/<[^>]+>/gm, '');
var stripped = html.replace('<br>', ' ').replace('<br />', ' ').replace('<br/>', ' ').replace(/<[^>]+>/gm, ' ');
return stripped.length > maxLength ? (stripped.substring(0, maxLength) + '...') : stripped;
};