<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<!------ Include the above in your HEAD tag ---------->
<div class="direction-wrapper" id="app">
</div>
<div id="jsCreateLinkForm" class="input-form js-create-form" style="display: none;" >
<p>
<label>Ссылка: <input type="text" class="js-link-url" value="http://" /></label>
</p>
<p class="js-link-title-wrapper">
<label>Название <input type="text" class="js-link-title" value="" disabled="disabled"/></label>
</p>
<p class="js-link-error-wrapper">
Введенный адрес имеет не верный формат
</p>
<div class="clear"></div>
<button type="button" class="js-btn" data-action="create-link-cancel">Назад</button>
<button type="button" class="js-btn" data-action="create-link-accept">Добавить</button>
<div class="clear"></div>
</div>
<div id="jsChangeImage" class="input-form js-change-image-form" style="display: none;" >
<div class="image-wrapper js-direction-image">
<img id="imageSource" scr=""/>
</div>
<input type="file" name="file" id="fileuploader" style="display: none;" accept="image/jpg, image/jpeg, image/gif, image/png"/>
<button type="button" class="js-btn" data-action="change-image-cancel">Назад</button>
<button type="button" class="js-btn" data-action="change-image-load">Загрузить другое изображение</button>
<button type="button" class="js-btn" data-action="change-image-accept">Сохранить</button>
</div>
<script type="text/x-handlebars-template" id="allDirectionsTemplate">
<h1 class="module-title">Структура компании</h1>
<ul class="directions-overview">
{{#each this}}
<div class="direction-summary">
<a href="#!/{{ ID }}" class="direction-title">{{ Title }}</a>
<a href="#!/{{ ID }}" class="direction-image">
<img src="{{ Cover }}" /></a>
<p class="direction-text">{{ Text }}</p>
</div>
{{/each}}
</ul>
</script>
<script type="text/x-handlebars-template" id="directionTemplate">
<div class="direction">
<div class="left-col">
<div class="direction-info">
<h2 class="module-title">{{ Title }}</h2>
<div class="direction-image">
<img src="{{ Cover }}" />
{{#if CanEdit}}
<a href="#jsChangeImage" class="js-btn change-image">Изменить изображение</a>
{{/if}}
</div>
<p class="direction-text">{{ Text }}</p>
</div>
<div class="direction-hierarchy js-hierarchy">
<div class="hierarchy-root">
<p class="root-title">{{ Title }}</p>
<a class="direction-link" href="<%= _Consts.UrlToAddressBook %>?defDep={{ ID }}">a</a>
</div>
{{> children Children}}
</div>
</div>
<div class="right-col">
{{#condition Links.length "||" CanEdit }}
<div class="direction-data direction-links-wrapper">
<h3>Полезные ссылки:</h3>
<ul class="direction-links js-links-list">
{{#each Links}}
{{> link this}}
{{/each}}
{{#if CanEdit }}
<li><a href="#jsCreateLinkForm" class="js-btn" data-action="create-link" type="button">Новая ссылка</a></li>
{{/if}}
</ul>
</div>
{{/condition}}
<div class="direction-data direction-managers-wrapper">
<h3>Руководитель:</h3>
{{> employee Manager }}
</div>
{{#if Assistants}}
<div class="direction-data direction-managers-wrapper">
<h3>Административная поддержка:</h3>
{{#each Assistants}}
{{> employee this }}
{{/each}}
</div>
{{/if}}
</div>
</div>
</script>
<script type="text/x-handlebars-template" id="employeeTemplate">
<div class="employee-wrapper">
<a class="employee-photo" href="<%= _Consts.UrlToProfile %>?user={{ ID }}">
<img src="{{ Photo }}" />
</a>
<div class="employee-info">
<a class="employee-title" href="<%= _Consts.UrlToProfile %>?user={{ ID }}">{{ Lastname }} {{ Firstname }}</a>
{{#if Position}}
<p class="employee-position">{{ Position }}</p>
{{/if}}
{{#if Phone}}
<p class="employee-phone">{{ Phone }}</p>
{{/if}}
{{#if Email}}
<a class="employee-mail" href="mailto:{{ Email }}">{{ Email }}</a>
{{/if}}
</div>
</div>
</script>
<script type="text/x-handlebars-template" id="departmentTemplate">
<div class="hierarchy-item" data-id="{{ ID }}">
<div class="department-info">
<a class="department-info-title" href="#!/{{ ID }}">{{ Title }}</a>
{{#if HasChildren}}
<button type="button" class="hierarchy-action js-btn" data-action="hierarchy-action"></button>
{{/if}}
<a class="direction-link" href="<%= _Consts.UrlToAddressBook %>?defDep={{ ID }}"></a>
</div>
</div>
</script>
<script type="text/x-handlebars-template" id="departmentChildrenTemplate">
<div class="heirarchy-children {{#if this }}hierarchy-not-empty {{/if}}">
{{#each this}}
{{> department this}}
{{/each}}
</div>
</script>
<script type="text/x-handlebars-template" id="linkTemplate">
<li class="direction-link" data-id="{{ ID }}"><a href="{{ Url }}"{{#if InNewWindow}} target="_blank"{{/if}}>{{ Title }}</a><button type="button" class="remove-link js-btn" data-action="remove-link"></button></li>
</script>
@import '../../../../WSSC.PRT.PNT6.Core/Layouts/WSSC.PRT.PNT6.Core/styles/props';
.module-title {
margin-bottom: 30px;
margin-right: 30px;
}
.direction-wrapper {
.direction {
.left-col {
float: left;
width: 70%;
.direction-image {
position: relative;
.change-image {
display: none;
position: absolute;
bottom: 0;
width: 100%;
padding: 10px 0;
background: rgba(0, 0, 0, 0.5);
}
&:hover {
.change-image {
display: block;
}
}
}
.direction-hierarchy {
text-align: center;
.hierarchy-root {
display: inline-block;
width: 335px;
height: 120px;
margin-bottom: 37px;
box-shadow: 0 0 0 1px @baseRed, 0 0 0 6px #ffa9a9;
position: relative;
}
.hierarchy-children {
text-align: center;
}
.hierarchy-item {
display: inline-block;
vertical-align: top;
.department-info {
width: 185px;
height: 135px;
position: relative;
}
}
}
.root-title {
.webpart-title();
word-break: break-word;
.vertical-block-center-height-unknown();
width: 100%;
display: block;
text-align: center;
}
.direction-link {
position: absolute;
color: transparent;
bottom: 10px;
right: 10px;
width: 23px;
height: 15px;
display: inline-block;
background: @structurePplIcon;
}
.employee-wrapper {
.employee-photo {
display: inline-block;
width: 55px;
height: 55px;
overflow: hidden;
img {
width: 100%;
}
}
}
}
.right-col {
float: right;
width: 30%;
padding-left: 30px;
.box-sizing;
}
}
}
.hierarchy-root {
/*&:before {
content: '';
position: absolute;
bottom: -34px;
left: 50%;
border-left: 1px solid #ccc;
width: 0;
height: 28px;
}*/
}
.heirarchy-children {
.hierarchy-item {
box-shadow: 0 0 0 1px #e1e1e1, 0 0 0 6px #eeeeee;
margin-right: 35px;
margin-bottom: 40px;
position: relative;
&:nth-child(3n) {
margin-right: 0;
}
&:last-child {
margin-right: 0;
}
}
> .hierarchy-item {
&:first-child {
&:before {
content: '';
position: absolute;
top: -20px;
right: -50%;
border-left: 1px solid #ccc;
width: 100%;
height: 14px;
}
}
&:nth-child(2) {
&:before {
content: '';
position: absolute;
top: -20px;
left: -71%;
border-top: 1px solid #ccc;
border-right: 1px solid #ccc;
width: 120.5%;
height: 14px;
}
}
&:nth-child(3) {
&:before {
content: '';
position: absolute;
top: -20px;
left: -71%;
border-top: 1px solid #ccc;
border-right: 1px solid #ccc;
border-left: 1px solid #ccc;
width: 120%;
height: 14px;
}
/*&:after {
content: '';
position: absolute;
top: -34px;
left: -70%;
border-left: 1px solid #ccc;
width: 120%;
height: 15px;
}*/
}
}
.hierarchy-opened {
box-shadow: none;
margin: 0 auto;
> .department-info {
box-shadow: 0 0 0 1px #e1e1e1, 0 0 0 6px #eeeeee;
margin: 0 auto 40px;
}
> .department-info .hierarchy-action {
background-position: 0 -16px;
}
&.hierarchy-item:before {
display: none !important;
}
&.hierarchy-item:after {
content: '';
position: absolute;
top: -20px;
left: -71%;
border-right: 1px solid #ccc;
width: 120.8%;
height: 14px;
}
}
}
.department-info-title {
text-transform: uppercase;
font-size: 15px;
color: @black;
display: block;
.vertical-block-center-height-unknown();
width: 100%;
text-align: center;
}
.hierarchy-action {
border: 0;
min-width: 1px;
display: inline-block;
position: absolute;
bottom: 10px;
right: 40px;
background: transparent @structureArrowIcon;
width: 17px;
height: 13px;
cursor: pointer;
outline: none;
&:hover {
background-color: transparent;
}
}
.hierarchy-not-empty {
position: relative;
&:before {
height: 14px;
border-left: 1px solid #ccc;
content: '.';
color: transparent;
position: absolute;
left: 49.8%;
top: -34px;
}
}
/*.hierarchy-opened {
.heirarchy-children {
&:before {
width: 100%;
height: 28px;
margin-bottom: 20px;
border: 1px solid #000000;
border-bottom: 0;
content: '.';
color: transparent;
position: absolute;
left: 0;
top: -7px;
}
}
}*/
.directions-overview {
padding: 0;
margin: 0;
font-size: 0;
.direction-summary {
width: 433px;
height: 223px;
display: inline-block;
font-size: 14px;
vertical-align: top;
box-shadow: 0 0 0 1px #e1e1e1, 0 0 0 6px #eeeeee;
padding: 22px;
.box-sizing;
margin-bottom: 40px;
&:nth-child(odd) {
margin-right: 40px;
margin-left: 6px;
}
}
.direction-title {
.webpart-title();
width: 100%;
display: inline-block;
max-height: 33px;
min-height: 33px;
overflow: hidden;
vertical-align: middle;
margin-bottom: 18px;
}
.direction-text,
.direction-image {
vertical-align: top;
}
.direction-image {
.img-mask();
display: inline-block;
}
.direction-text {
width: 255px;
min-height: 125px;
max-height: 125px;
overflow: hidden;
display: inline-block;
}
}
.direction-info {
margin-bottom: 65px;
.module-title {
margin-right: 0;
}
.direction-image {
.img-mask(160px, 30px);
display: inline-block;
}
.direction-text {
width: ~"calc(100% - 195px)";
min-height: 160px;
max-height: 160px;
overflow: hidden;
display: inline-block;
}
}
.direction-data {
margin-bottom: 25px;
h3 {
border-bottom: 2px solid @baseRed;
.webpart-title();
padding: 10px 0 12px;
margin-bottom: 10px;
}
.direction-links {
display: block;
width: 218px;
overflow: hidden;
position: relative;
font-family: Roboto, Arial, sans-serif;
list-style-type: none;
padding: 0;
li {
background: url(/_layouts/15/WSSC.PRT.PNT6.Design/Icons/link-icon.png) no-repeat 2px 50%;
line-height: 17px;
padding-left: 47px;
position: relative;
min-height: 30px;
}
a {
text-decoration: underline;
display: inline-block;
margin-top: 8px;
max-width: 155px;
}
.remove-link {
cursor: pointer;
border: 0;
min-width: 1px;
position: absolute;
display: inline-block;
top: 45%;
right: -10px;
width: 8px;
height: 8px;
background: url(/_layouts/15/WSSC.PRT.PNT6.Design/Icons/cancel-icon.png) no-repeat;
outline: none;
}
}
.employee-wrapper {
margin: 20px 0;
.employee-photo {
.img-mask(90px, 12px);
display: inline-block;
vertical-align: top;
}
.employee-info {
display: inline-block;
padding: 0;
width: 110px;
vertical-align: top;
}
.employee-title {
color: #000000;
text-decoration: underline;
font-weight: bold;
font-size: 13px;
margin-bottom: 8px;
display: block;
}
.employee-position, .employee-phone, .employee-mail {
font-weight: 100;
font-size: 10px;
}
.employee-mail {
margin-top: 8px;
display: inline-block;
color: @baseRed;
text-decoration: underline;
}
}
}
.remove-link {
}
var AJAX_URL = '/_layouts/15/wssc.prt.pnt6.core/handlers/ajax.ashx',
NAMESPACE = 'WSSC.PRT.PNT6.Structure:Direction:';
Handlebars.registerHelper('condition', function (v1, operator, v2, options) {
switch (operator) {
case '==':
return (v1 == v2) ? options.fn(this) : options.inverse(this);
case '===':
return (v1 === v2) ? options.fn(this) : options.inverse(this);
case '!=':
return (v1 != v2) ? options.fn(this) : options.inverse(this);
case '!==':
return (v1 !== v2) ? options.fn(this) : options.inverse(this);
case '<':
return (v1 < v2) ? options.fn(this) : options.inverse(this);
case '<=':
return (v1 <= v2) ? options.fn(this) : options.inverse(this);
case '>':
return (v1 > v2) ? options.fn(this) : options.inverse(this);
case '>=':
return (v1 >= v2) ? options.fn(this) : options.inverse(this);
case '&&':
return (v1 && v2) ? options.fn(this) : options.inverse(this);
case '||':
return (v1 || v2) ? options.fn(this) : options.inverse(this);
default:
return options.inverse(this);
}
});
var directions = (function () {
var allDirectionsTemplate = Handlebars.compile($('#allDirectionsTemplate').html()),
directionTemplate = Handlebars.compile($('#directionTemplate').html()),
linkTemplate = Handlebars.compile($('#linkTemplate').html()),
departmentChildrenTemplate = Handlebars.compile($('#departmentChildrenTemplate').html()),
currentDirectionID = null,
createLinkDebounce = null,
$uploader = null,
jcropApi = null;
Handlebars.registerPartial('link', $('#linkTemplate').html());
Handlebars.registerPartial('employee', $('#employeeTemplate').html());
Handlebars.registerPartial('department', $('#departmentTemplate').html());
Handlebars.registerPartial('children', $('#departmentChildrenTemplate').html());
Handlebars.registerHelper('groupEach', function (every, context, options) {
var out = "", subcontext = [], i;
if (context && context.length > 0) {
for (i = 0; i < context.length; i++) {
if (i > 0 && i % every === 0) {
out += options.fn(subcontext);
subcontext = [];
}
subcontext.push(context[i]);
}
out += options.fn(subcontext);
}
return out;
});
function createLink() {
$.getJSON(AJAX_URL, {
method: NAMESPACE + 'AjaxAddDirectionLink',
direction: currentDirectionID,
url: $('.js-create-form .js-link-url').val(),
title: $('.js-create-form .js-link-title').val(),
rand: Math.random()
}).then(function (response) {
if (response.Error) {
console.log(response);
} else {
$('.js-create-form .js-link-url').val('http://');
$('.js-create-form .js-link-title').val('')
.disable();
var $link = $(linkTemplate(response)).css('display', 'none');
if ($('.js-btn[data-action="create-link"]').length) {
$('.js-btn[data-action="create-link"]').before($link);
} else {
$('.js-links-list').append($link);
}
$link.fadeIn(200);
$('.js-btn[data-action="create-link-cancel"]').trigger('click');
}
});
}
function removeLink($el) {
var linkId = $el.data('id');
$.getJSON(AJAX_URL, {
method: NAMESPACE + 'AjaxRemoveDirectionLink',
id: linkId,
rand: Math.random()
}).then(function (response) {
if (response.Error) {
console.log(response);
} else {
$el.fadeOut(200, function () {
$el.remove();
});
}
})
}
function onUrlInput(url) {
url = url.trim();
createLinkDebounce = clearTimeout(createLinkDebounce);
if (!url) {
return;
}
if ($('.js-create-form .js-link-title-wrapper').css('display') === 'none') {
$('.js-create-form .js-link-error-wrapper').fadeOut(200);
$('.js-create-form .js-link-title-wrapper').fadeIn(200);
}
$('.js-create-form .js-link-title').disable();
$('.js-create-form .js-btn[data-action="create-link-accept"]').disable();
$('.js-create-form .js-link-title').val('');
createLinkDebounce = setTimeout(function () {
$('.js-create-form .js-link-title').spin();
$.getJSON(AJAX_URL, {
method: 'WSSC.PRT.PNT6.PersonalInfo:LinkActions:GetTitleByUrl',
fullUrl: url,
rand: Math.random()
}).then(function (response) {
$('.js-create-form .js-link-title').spin();
if (response.IsSuccess) {
$('.js-create-form .js-link-title').val(response.Message);
$('.js-create-form .js-link-title').enable();
$('.js-create-form .js-btn[data-action="create-link-accept"]').enable();
} else {
$('.js-create-form .js-link-title-wrapper').fadeOut(200);
$('.js-create-form .js-link-error-wrapper').fadeIn(200);
}
});
}, 350);
}
function showUploader() {
if (!$uploader) {
$uploader = $('#fileuploader').fileupload({
url: AJAX_URL,
replaceFileInput: false,
dataType: 'json',
formData: {
method: NAMESPACE + 'AjaxUploadFile'
},
done: function (e, data) {
if (data.result.Error) {
console.log(data.result);
} else {
onImageRecieved(data.result.Path);
}
}
});
}
$uploader.trigger('click');
}
function onImageRecieved(img) {
jcropApi.setImage(img, function () {
$('#imageSource').attr('src', img);
setCropSelection();
});
}
function setCropSelection() {
var $image = $('#imageSource'),
w = $image.width(),
h = $image.height(),
wC = w / 2,
hC = h / 2,
maxSelectionSize = Math.min(w, h),
sC = maxSelectionSize / 2;
jcropApi.setSelect([wC - sC, hC - sC, wC + sC, hC + sC]);
}
function getChildren(id) {
return $.getJSON(AJAX_URL, {
method: NAMESPACE + 'AjaxGetDepartmentChildren',
depId: id
});
}
function changeCover() {
var selected = jcropApi.tellSelect();
$.getJSON(AJAX_URL, {
method: NAMESPACE + 'AjaxChangeDirectionCover',
direction: currentDirectionID,
coverPath: $('#imageSource').attr('src'),
x: selected.x,
y: selected.y,
w: selected.w,
h: selected.h
}).then(function (response) {
if (response.Error) {
console.log(response);
} else {
$('.direction-image img').attr('src', response.Path);
$('.js-change-image-form .js-btn[data-action="change-image-cancel"]').trigger('click');
}
});
}
function renderChildren($el, children) {
var childHtml = departmentChildrenTemplate(children);
$el.closest('.heirarchy-children').children().hide();
$el.show();
$el.append(childHtml);
$el.addClass('hierarchy-opened');
}
function expandChildren($el) {
getChildren($el.data('id')).then(function (response) {
if (response.Error) {
console.log(response);
} else {
renderChildren($el, response);
}
});
}
function collapseChildren($el) {
$el.children('.heirarchy-children').remove();
$el.closest('.heirarchy-children').children().show();
$el.removeClass('hierarchy-opened');
}
function getRootDirections() {
$('#app').spin('large');
return $.getJSON(AJAX_URL, {
method: NAMESPACE + 'AjaxGetDirections'
}).then(function (response) {
$('#app').spin();
if (response.Error) {
console.log(response);
} else {
return response;
}
});
}
function renderRootDirections(directions) {
if (!directions) {
return;
}
var html = allDirectionsTemplate(directions);
$('#app').html(html);
}
function showAllDirections() {
getRootDirections().then(renderRootDirections);
}
function getDirectionInfo(id) {
$('#app').spin('large');
return $.getJSON(AJAX_URL, {
method: NAMESPACE + 'AjaxGetDirection',
id: id
}).then(function (response) {
$('#app').spin();
if (response.Error) {
console.log(response);
} else {
currentDirectionID = response.ID;
return response;
}
});
}
function renderDirection(direction) {
if (!direction) {
return;
}
var html = directionTemplate(direction);
$('#app').html(html);
$('.js-create-form, .js-links-list, .js-hierarchy, .js-change-image-form').off()
.on('click', '.js-btn', function () {
var $src = $(this),
action = $src.data('action');
switch (action) {
case 'create-link-accept':
createLink();
break;
case 'remove-link':
removeLink($src.parent());
break;
case 'hierarchy-action':
var $item = $src.closest('.hierarchy-item');
if ($item.hasClass('hierarchy-opened')) {
collapseChildren($item);
} else {
expandChildren($item);
}
break;
case 'change-image-load':
showUploader();
break;
case 'change-image-accept':
changeCover();
break;
}
})
.on('keyup', '.js-link-url', function () {
var val = $(this).val();
onUrlInput(val);
});
$('a[href="#jsCreateLinkForm"]').unbind()
.leanModal({
closeButton: '.js-create-form .js-btn[data-action="create-link-cancel"]',
top: 300
});
$('a[href="#jsChangeImage"]').unbind()
.leanModal({
closeButton: '.js-change-image-form .js-btn[data-action="change-image-cancel"]',
top: 300,
onShow: function ($el) {
var $img = $el.find('#imageSource');
$img.attr('src', direction.Cover);
if (jcropApi) {
jcropApi.destroy();
}
$img.Jcrop({
aspectRatio: 1
}, function () {
jcropApi = this;
setCropSelection();
});
}
});
}
function showDirection(id) {
getDirectionInfo(id).then(renderDirection);
}
function onHashChanged() {
function getHashValue(hash) {
if (hash[0] === '#') {
hash = hash.substring(1);
}
hash = hash.replace('!/', '');
return hash;
}
var hash = getHashValue(window.location.hash);
if (hash.length) {
showDirection(hash);
} else {
showAllDirections();
}
}
$(window).on('hashchange', onHashChanged);
onHashChanged();
})();