понедельник, 25 июня 2012 г.

«Вы уверены?» Confirmation-диалоги в SharePoint

Конечно, чаще всего обычного JavaScript’ового confirm’а вполне достаточно. Однако, иногда хочется показать более красивый диалог, предложить другие варианты выбора, добавить иллюстрацию или параграфы в текст... Многие для такой задачи используют jQuery UI, jQuery плагины или сторонние JS-библиотеки, но мне кажется, этого делать не стоит: в SharePoint’е уже есть диалоги, они прекрасно вписываются в общий дизайн и предоставляют массу настроек. Мне кажется, нет ни одной причины, чтобы их не использовать.

image

Ниже я представлю код класса Dialog, который позволяет легко отображать подобные диалоги, и выполнять какие-нибудь действия в случае, если пользовать нажал «Да». Пользоваться классом предельно просто:

My.Dialog.confirm(
'Вы уверены?',
'Вы уверены, что хотите отменить процесс подписи?',
function () {
alert(
'Пользователь нажал "Да"!');
});

При этом не потребуется создавать отдельную aspx-страницу: SharePoint’овские модальные диалоги имеют режим, в котором они создаются полностью динамически.



SP.UI.ModalDialog


За отображение модальных диалогов в SharePoint отвечает класс SP.UI.ModalDialog. Этот класс известен достаточно широко, но есть некоторые хитрости по его использованию. При отображении диалога с помощью метода showModalDialog, для указания режима отображения, можно использовать либо параметр url, либо параметр html. Первый позволяет отображать некую страницу в iframe, второй — позволяет создавать диалоги «на лету». Что интересно, параметр html, вместо строки на самом деле принимает DOM-элемент.


Причем в MSDN написано иначе, и только в комментариях можно прочитать правду. Вообще, в MSDN всегда очень рекомендую обращать особое внимание на комментарии, а также на секцию Remarks, там частенько можно обнаружить совершенно эксклюзивную информацию.


Реализация


Собственно, ниже код класса:

/// <reference name="MicrosoftAjax.js" />
/// <reference path="file://C:/Program Files/Common Files/Microsoft Shared/Web Server Extensions/14/TEMPLATE/LAYOUTS/SP.debug.js" />
/// <reference path="file://C:/Program Files/Common Files/Microsoft Shared/Web Server Extensions/14/TEMPLATE/LAYOUTS/SP.core.debug.js" />
/// <reference path="file://C:/Program Files/Common Files/Microsoft Shared/Web Server Extensions/14/TEMPLATE/LAYOUTS/SP.UI.Dialog.debug.js" />

Type.registerNamespace("My");

My._Dialog =
function () {

    this.confirm = function (title, text, confirmCallback) {
/// <summary>
/// Вывод диалога подтверждения
/// </summary>
/// <param name='title' type='String'>Заголовок окна диалога</param>
/// <param name='text' type='String'>Текст окна диалога</param>
/// <param name='confirmCallback' type='Function'>Функция, которая будет вызвана в случае нажатия на кнопка "Да"</param>

runDialog(title, text,
[
{
caption: SP.Res.buttonYes,
callback: confirmCallback
},
{
caption: SP.Res.buttonNo,
isCancel:
true
}
],
'/_layouts/images/warning32by32.gif');
}

this.show = function (title, textOrDomElement, buttons, imageUrl) {
/// <summary>
/// Вывод настраиваемого диалога
/// </summary>
/// <param name='title' type='String'>Заголовок окна диалога</param>
/// <param name='textOrDomElement' type='Object'>Текст или DOM-элемент, который будет отображаться в теле диалога. В случае DOM-элемента, желательно ему добавить padding'и 10px.</param>
/// <param name='buttons' type='Array'>Массив с описаниями кнопок диалога. Каждая кнопка имеет параметры caption, callback и isCancel. Пример можно посмотреть в реализации функции My.Dialog.confirm</param>
/// <param name='imageUrl' type='String'>Необязательный параметр, задающий URL картинки, которая будет отображена слева от текста. Если этот параметр не задан, картинка отображаться не будет.</param>

runDialog(title, textOrDomElement, buttons, imageUrl);
}

function runDialog(dialogTitle, textOrDomElement, buttons, imageUrl) {

var div = document.createElement('div');
if (imageUrl)
div.appendChild(createImage(imageUrl));
if (textOrDomElement.nodeType === 1)
div.appendChild(textOrDomElement);
else
div.appendChild(createParagraph(textOrDomElement, 10));
div.appendChild(createButtons(buttons));

SP.UI.ModalDialog.showModalDialog({
html: div,
title: dialogTitle,
width: 320,
showClose:
false,
allowMaximize:
false,
dialogReturnValueCallback:
function (dialogResult, returnValue) {
if (dialogResult == SP.UI.DialogResult.OK) {
buttons[returnValue].callback();
}
}
});

}

function createImage(imageUrl) {

var img = document.createElement('img');
img.src = imageUrl;
img.style.padding =
'10px';
img.style.border =
'0';
img.style.styleFloat =
'left';
return img;

}

function createParagraph(text, padding) {

var p = document.createElement('p');
p.style.padding = padding +
"px";
p.appendChild(document.createTextNode(text));
return p;

}

function createButtons(buttons) {

var buttonsPanel = document.createElement('div');
buttonsPanel.style.textAlign =
"right";
buttonsPanel.style.padding =
"5px";

for (var i = 0; i < buttons.length; i++) {

(
function (index) {

buttonsPanel.appendChild(
createHtmlButton(
buttons[index].caption,
function () {
if (buttons[index].isCancel)
SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.cancel);
else
SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.OK, index);
}));

})(i);
}
return buttonsPanel;
}

function createHtmlButton(text, handler) {

var button = document.createElement('input');
button.type =
'button';
if (handler)
button.onclick = handler;
button.value = text;
button.style.paddingLeft =
"5px";
button.style.paddingRight =
"5px";
button.style.margin =
"5px";
return button;

}
}

My._Dialog.registerClass(
"My._Dialog");
My.Dialog =
new My._Dialog();

Напомню, я всегда классы храню в отдельных файлах, после чего склеиваю их и минифицирую, перед тем как “подать” в браузер. В подробностях эта техника описана в одном из моих недавних постов, Разработка больших JavaScript-решений: 1 файл = 1 класс.


Также, обратите внимание на inline-документацию. Эта документация позволяет позволяет получать intellisense-подсказки в Visual Studio, что крайне удобно.


image


Также, вы наверняка заметили наличие второго метода, show. Он позволяет выводить диалоги с произвольным количеством кнопок и произвольными внутренностями. И на каждую кнопку можно назначить собственный callback.


Еще про диалоги


Год назад я выступал на конференции SharePoint Conference 2011 Russia с докладом про Ribbon и Office365, и демонстрировал несколько очень интересных примеров, как можно использовать модальные диалоги. В дополнение к докладу, был написана небольшая статья о том, как можно использовать «родные» модальные диалоги SharePoint’а. Эта статья, и мне кажется, по праву, до сих пор является одной из самых популярных в блоге.


Смысл в том, что любой диалог который вы видите в SharePoint, вы можете использовать сами.


Например, вот такой диалог:


image


Можно отобразить следующим кодом:

SP.UI.ModalDialog.showModalDialog({
url:
'/_layouts/morecolors.aspx',
args: currentColor,
// сюда поместите значение для Old color
dialogReturnValueCallback: function (dialogResult, returnValue) {
if (dialogResult == SP.UI.DialogResult.OK)
$get(
'myDiv').style.backgroundColor = returnValue;
}
});

И в returnValue после закрытия диалога вы получите значение цвета в виде строки, например '#222222'.


Больше примеров – в той статье.

2 комментария:

  1. Всё отлично вот только бы сделать, чтобы confirm чтобы пользователь нажал ок или no. А то могут быть проблемы

    ОтветитьУдалить
  2. Слегка модифицировал код выше, чтобы была возможность сделать что-то ДО закрытия диалогового с тем контролом что туда передан и результат передать "наружу".

    ОтветитьУдалить

Внимание! Реклама и прочий спам будут беспощадно удаляться.