вторник, 16 сентября 2014 г.

Боковое меню с эффектом аккордеона для SharePoint 2013

Иногда боковое меню сайта SharePoint принимает просто угрожающие размеры. При этом пользователи разбивают пункты меню на подгруппы. Что правильно и совершенно логично.

Это делает меню более понятным визуально, но его юзабилити, а главное размер, по прежнему оставляют желать лучшего. Так как по умолчанию в SharePoint не поддерживается "эффект аккордеона", когда подпункты меню схлопываются в виде гармошки.

Здесь описан пример создания "эффекта аккордеона" на одном CSS, без применения JavaScript.


Это решение работает. Оно очень простое и эффективное. Однако стоит признать, что в целом поведение такой "гармошки", не такое классное, как хотелось бы.

По сути, всё решение сводится к добавлению в master page ссылки на css файл со следующим содержимым:

.ms-core-listMenu-verticalBox li.static {
    height: 2em;
    overflow: hidden;
}
.ms-core-listMenu-verticalBox li.static:hover {
    height: auto;
}
.ms-core-listMenu-verticalBox li > span.menu-item {
    cursor: pointer;
}
/* Format the headers */
.ms-core-listMenu-verticalBox li > span.menu-item {
    cursor: pointer;
    background: #0171C6;
    color: white;
    border: solid #fff;
    border-width: 1px 0;
}
/* Format the headers */
.ms-core-listMenu-verticalBox li > span.menu-item {
    cursor: pointer;
    background: #0171C6;
    color: white;
    border: solid #fff;
    border-width: 1px 0;
}
/* Format the header hover, list item hover and currently selected item */
.ms-core-listMenu-verticalBox li > span.menu-item:hover, /*Header */
.ms-core-listMenu-verticalBox a.selected, /* Selected */
.ms-core-listMenu-verticalBox a.menu-item:hover /* List item */{
    color:#FFF;
    background:#073D7D;
}




вторник, 8 июля 2014 г.

Определение Edit Mode страницы с помощью JavaScript

В SharePoint 2013 есть такая штука как Publishing Pages. С точки зрения рядового пользователя, это веб-страницы, которые он может создавать прямо в браузере, в стиле WYSIWYG. Достаточно создать новую страницу публикации (Publishing Page), затем открыть её в режиме редактирования и можно сразу набивать контент, при этом особо не запариваясь относительно стилей и получаемой разметки. Вещь удобная и пользуются ей, как говорится, направо и налево.

Впрочем увлёкшись WISIWIG вы всё ещё можете остановиться и взглянуть на полученную HTML-разметку. И даже отредактировать её, дабы наполнить не передаваемым шармом в духе HTML5. Для чего на панели инструментов предусмотрена кнопка "Изменить источник".



А что если мы решим зайти дальше в нашем стремлении сделать контент страницы более интерактивным и насыщенным, и добавим на страницу публикации веб-часть "Редактор сценариев". А в этот редактор сценариев поместим JavaScript, который, используя jQuery и добавленную нами на страницу HTML-разметку, создаёт интерактивный и кувыркающийся Коллаж из фотографий и лозунгов, рождённый воспалённой фантазией вашего дизайнера и PR-менеджера, слившихся в творческом экстазе.

Скажу сразу, что после сохранения страницы с результатами редактирования, Коллаж не просто заработает, но будет прекрасен. Он поразит всех, начиная от бухгалтерши и заканчивая генеральным и исполнительным директорами. А финансовый директор сразу выпишет вам премию.

Вот только когда вас попросят добавить в коллаж новый лозунг, и вы вновь откроете страницу в режиме редактирования, то увидите что вся ваша HTML-разметка "пляшет" и "кувыркается" по воле JavaScript'a из веб-части "Редактор сценариев". А стоит вам сохранить страницу, как вся эта чехорда "впечатается" в контент страницы на мертво и JavaScript уже будет не в состоянии её оживить.

Дело в том, что когда вы открыли страницу на редактирования, то JavaScript в веб-части
"Редактор сценариев" начнёт выполняться, как ни в чём не бывало. При этом он будет, искать в содержимом страницы определённую HTML-структур (например, див внутри которого находится список, каждый элемент которого является сложным описанием одной из страниц слайда). Найдя её, он оживит её самым чудесным образом, динамически внося изменения в этот кусок HTML кода. Однако SharePoint понятия не имеет кто вносит изменения в разметку, Вы или ваш JavaScript. По этому когда вы сохраните страницу, он с чистой совестью сохранит всю необходимую HTML разметку, включая исковерканную вашим же JavaScript'ом. После чего она будет разительно отличаться от той, что нужна JavaScript'у для оживления коллажа.

Выход есть! Необходимо, чтобы перед тем как пытаться оживлять коллаж, JavaScript проверил в каком режиме находится страница публикации. И если страницы открыта в режиме редактирования контента, то JavaScript прекращает работу ни как не влияя на разметку.

<script type="text/javascript">
        (function ($) {

            $(document).ready(function () {
                // Проверям режим страницы
                var InEditMode = false;
                try{
                InEditMode = SP.Ribbon.PageState.Handlers.isInEditMode();
                } catch(e){}
               
                if (InEditMode) {return;}
                // Каруселить список клиентов
                // btnNext и btnPrev - указывают на кнопки вперёд/назад
                // visible - скорлько элементов карусели будет показано единовременно
                // circular - зациклить карусель по кругу
                $(".clients-list").jCarouselLite({
                    btnNext: "#gon",
                    btnPrev: "#pon",
                    visible: 5,
                    circular: true
                });

            });

        })(jQuery);

    </script>

четверг, 3 июля 2014 г.

Многострочные строки в JavaScript или аналог @ в C#.

В языке C# есть так называемые буквальные строковые литералы.

Пример буквальных строковых литералов:
// Буквальные строковые литералы воспринимают всё написанное буквально, кроме кавычек. Что бы задать кавычки необходимо воспользоваться специальной управляющей последовательностью - двойные кавычки, т.е. вот так: ""
string s = @"C:\Windows";

s = @"Роман ""Война и мир"""// Роман "Война и Мир"

Кроме того, буквальный строковый литерал позволяет отказаться от использования управляющей последовательности \n новая строка.
Т.е. вместо того чтобы писать так:

string s = "Переход на новую строку.. \n.. новая строка";

Можно записать так:

string s  = @"Переход на новую строку..
.. новая строка";

А результат будет одним и тем же.

В JavaScript нет своего буквального строкового литерала, но есть возможность задавать многозначные строки, хотя это и считается недостатком текущей реализации интерпритатора, а не возможностью языка JavaScript:

var multiLine = '\
Первая строка \
Вторая строка \
Третья строка \
';
alert(multiLine);


понедельник, 30 июня 2014 г.

Как добавить в форму создания нового элемента списка пункт "Вложить файл"

Иногда, необходимо дать пользователю дополнительный намёк, о том что он может прикрепить файл к элементу списка. Причём для этого нам даже не понадобиться сильно изгаляться над формой Создания нового элемент списка. Достаточно проделать следующие не хитрые шаги.

1) Открываем на редактирование страницу с формой создания нового элемента списка.
2) Добавляем новую веб-часть "Редактор контента". Самый простой способ сделать это, просто выбрать Insert -> Text:
3) Затем вставляем в веб-часть следующую разметку:

<div>
  <a title="Attach File" class="ms-toolbar" accesskey="I" onclick="javascript:UploadAttachment();" href="javascript:UploadAttachment()">
     <img width="16" height="16" align="absMiddle" alt="Attach File" src="/_layouts/images/attachtb.gif" style="border-width: 0px;"/>
  </a>
  <a id="ctl00_m_g_7df5d998_1390_4e67_8fc4_2da066cbcf7d_ctl00_ctl01_ctl00_toolBarTbl_RptControls_diidIOAttach{generate-id()}" href="javascript:UploadAttachment()" style="visibility: hidden;">
  </a>
  <a class="ms-toolbar" id="ctl00_m_g_7df5d998_1390_4e67_8fc4_2da066cbcf7d_ctl00_ctl01_ctl00_toolBarTbl_RptControls_diidIOAttach_LinkText" accesskey="I" onclick="javascript:UploadAttachment();" href="javascript:UploadAttachment()">
    Attach File
  </a>

</div>

Делается это через пункт меню "Изменить источник"...

... вот в таком диалоговом окне.


И в результате получаем:


4) И в итоге получаем следующий результат

вторник, 11 февраля 2014 г.

Как в тело письма, которое генерируется в SingleTask activity, добавить ссылку на задачу?

Долго искал как делается этот трюк, пока знающие люди не подсказали. :-)

Суть вопроса такова. Необходимо c помощью Visual Studio создать в SharePoint 2013 новый рабочий процесс (Workflow 4). В рамках этого рабочего процесса мы используем Single Task activity, чтобы создать новую задачу и назначить её на некоего пользователя. Single Task activity позволяет нам не только назначить задачу на сотрудника, но и тут же отправить ему на почту оповещение о том, что ему назначена новая задача. При этом мы можем отредактировать как тело письма, так и его тему.



Как видно, тело письма это обычный HTML.
Единственный минус в том, что по умолчанию, в теле письма нет ссылки на эту самую, новую назначенную задачу и пользователь несколько теряется, не понимая что же ему делать дальше.

Как оказалось, решить данную проблемы чрезвычайно просто. Достаточно добавить в тело письма вот такую вот ссылку:

 <a href='%TaskSpecial: TaskUrl%'>%Task: Title%</a>  

Вот как это будет выглядеть в итоге:

А вот так будет выглядеть письмо, пришедшее пользователю:

Тут можно найти и другие токены, которые могут вам пригодиться:

NameDescription
Public field Static memberAssignedToReplace the %Task: AssignedTo% token with the individual or group to whom the task is currently assigned.
Public field Static memberDescriptionReplace the %Task: Body% token with the description of the task.
Public field Static memberDueDateReplace the %Task: DueDate% token with the date the task is due.
Public field Static memberRegularFormatThe regular format for the token replacement.
Public field Static memberRelatedItemTitleReplace the %TaskSpecial: RelatedItemTitle% token with the title of the task’s related item.
Public field Static memberRelatedItemUrlReplace the %TaskSpecial: RelatedItemUrl% token with a link to the task’s related item.
Public field Static memberSpecialFormatThe special format for the token replacement.
Public field Static memberTaskUrlReplace the %TaskSpecial: TaskUrl% token with a link to the task.
Public field Static memberTitleReplace the %Task: Title% token with the title of the task.

четверг, 30 января 2014 г.

Как скрыть заголовок страницы SharePoint?

Иногда возникает необходимость скрыть заголовок страницы. Например,  на главной странице сайта (я имею в виду страницу приветствия, т.е. страницу сайта, которая открывается по умолчанию).

При этом у нас нет ни какого желания выпиливать заголовок ото всюду. То есть мы вовсе не хотим удалять соответствующий контрол из master page.
Наиболее простой способ решения поставленной задачи, заключается в том, чтобы найти и HTML-тег отвечающий за отображение заголовка и скрыть его с помощью CSS.
Вот правило, которое нам нужно:

<style type="text/css">
     #pageTitle {
            display: none;
     }
</style>

Остаётся придумать, как расположить его непосредственно на главной странице (т.е. на странице приветствия). Важно чтобы это CSS правило применилось только в отношении страницы приветсвия, а не всех страниц сайта.
Пожалуй самый "кошерный" способ провернуть такое, это использовать веб-часть "Редактор сценариев".

Шаг номер Раз :-)


Шаг номер два ;-)
Шаг номер три..
И результат:


понедельник, 2 декабря 2013 г.

Как зайти в SharePoint под другим пользователем?

В SharePoint 2013 отсутствует пункт меню "Войти под другим пользователем" (Sign in as Different User). Это вносит определённый дискомфорт во время создания решений для SharePoint. У разработчика очень часто возникает необходимость разлогиниться и залогиниться вновь уже под другим пользователями, чтобы проверить работу того или иного компонента.

Почему эту замечательную функцию исключили из SharePoint 2013? На этот счёт "в интернетах" говорят, что функция "Sign in as Different User" по сути не выполняет ту защитную функцию, которую ожидает получить от неё пользователь. Она скорее предназначена для использования теми пользователями, которые имеют два и более аккаунта в AD.

Дело в том, что когда пользователь вызывает функцию "Sign in as Different User", то в результате он может получить некоторые неприятные артефакты. 

Common problems are
  • Documents opened in external applications are saved with an unexpected user account because the external application runs under the windows account logged in to the machine and not the account you have chosen in SharePoint
  • Page content shows information from the previous user due to cached information
  • Session variables contain information from previous user as the cookies are not cleared
  • ...


Это неприятно, но не так страшно, если под разными аккаунтами входит фактически один и тот же человек. Однако с точки зрения обеспечения безопасности, это не лучший вариант.

Если вы хотите гарантировано добиться того, чтобы один пользователь НЕ видел данные другого пользователя, то вы должны выполнять  logoff/logon в Windows. Это особенно актуально в корпоративной среде, где люди преимущественно используют браузер IE, который как правило прозрачно выполняет авторизацию пользователя в SharePoint, используя для этого его текущую учётную запись Windows.

Если вы всё же решились использовать в своей работе возможность "Sign in as Different User", то её можно реализовать одним из следующих способов.

Использование URL-ссылки

Для того, чтобы зайти на сайт под другим пользователем, достаточно добавить в конец Url-ссылки на ваш сайт,следующую строчку:



/_layouts/closeConnection.aspx?loginasanotheruser=true



В результате вы должны получить следующую Url-ссылку:

, где <site_url> - это адрес вашего сайта (SPSite или SPWeb)

После перехода по этой ссылке текущий пользователь будет разлогинен, а вам будет предложено вновь ввести логин и пароль.


Однако каждый раз вводить URL руками не очень удобно.

Использование "Run as different user" с браузером IE.

Как известно, браузер IE использует учётную запись текущего пользователя Windows для прозрачной авторизации пользователя на сайте SharePoint.
Однако, у нас есть возможность запустить браузер IE от имени иной учётной записи (на рисунке, это команда "Run as different user")! Таким образом, когда мы зайдём на сайт SharePoint, то IE автоматически авторизует нас под иным пользователем, который отличается от нашего текущего пользователя Windows.


Возвращение пункта меню "Sign in as Different User", путём модификации файлов SharePoint.

Я не могу назвать это способ "кошерным", так как мы вносим изменения непосредственно в файлы SharePoint на сервере, что нельзя назвать хорошей идей. Однако этот способ прост и эффективен. Им можно пользоваться, если нужно чтобы пункт меню "Sign in as Different User" появился сразу на всех сайтах фермы SharePoint. Поэтому, Я рекомендую использовать данный способ на разработческой ферме.

Для этого откроем файл: C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\TEMPLATE\CONTROLTEMPLATES\Welcome.ascx (Предварительно создав его копию!)


Добавляем следующую разметку перед существующим элементом  "ID_RequestAccess".

<SharePoint:MenuItemTemplate
runat="server"
ID="ID_LoginAsDifferentUser" 
Text="<%$Resources:wss,personalactions_loginasdifferentuser%>"  
Description="<%$Resources:wss,personalactions_loginasdifferentuserdescription%>"  
MenuGroupId="100"   Sequence="100"   UseShortId="true"   />

В результате получим примерно следующее:



И, Вуаля!


Теперь на всех сайтах фермы мы получили необходимый пункт меню "Войти в качестве другого пользователя"

Создание Custom Action аналогичного "Sign in as Different User"

Практически все пункт, куда можно "всунуть" своё меню, можно найти на MSDN в статье
Default Custom Action Locations and IDs (http://msdn.microsoft.com/en-us/library/bb802730.aspx)

Но иногда встречаются и не задокументированные группы и локэйшины, которые можно использовать в своих целях!

Например, группа GroupId="PersonalActions"  расположенная в  Location="Microsoft.SharePoint.StandardMenu" позволяет добавить свой пункт меню в меню пользователя.
В качестве UrlAction для этого пункта меню можно использовать не без известную уже нам ссылку:
 /_layouts/closeConnection.aspx?loginasanotheruser=true