вторник, 20 ноября 2012 г.

SharePoint и XSLT: область ссылок «быстрого доступа»

Все вы помните ссылку «Добавить новый элемент» внизу представлений списков SharePoint:
image

В связи с наличием этой ссылки возникает два вопроса:
  1. Как поменять текст этой ссылки? (например вместо “Добавить новый элемент”, я хочу текст “Добавить товар” или “Добавить продукт” и т.д.)
  2. Как добавить еще пару ссылок рядом со ссылкой для создания нового элемента?
Все это можно. Например, некий список с заявками может иметь вот такие ссылки быстрого доступа:

image

, где ссылка Configure application route открывает редактор маршрута заявки (т.е. можно определить, кто и в каком порядке должен одобрять эту заявку).

В этой статье я расскажу, как реализовать такие изменения. Рассмотрим два способа:
  1. no-code — для частных решений
  2. программно – что может потребоваться для создания коробочных решений

No code

Как обычно в случае XSLT, самый простой и быстрый способ найти нужный шаблон и произвести нужные изменения — это использовать SharePoint Designer 2010 (далее SPD). Откройте ваш список в SPD, щелкните по названию нужного представления, и вы увидите визуальный дизайнер страницы.

Однако, ссылки «Add new item» вы не увидите, даже несмотря на то, что на исходной странице в браузере она присутствует.

Чтобы её увидеть, необходимо сделать следующее: щелкнуть куда-нибудь внутрь таблицы, в контекстной ленте в группе вкладок List View Tools щелкнуть Design, и выбрать Options –> Summary Toolbar.

image

Дальше всё очень просто, щелкаем на надпись “Add new item”:

image

, и в правой панели в списке свойств видим:

image

В это свойство можно вписать ваш текст (обратите внимание на апострофы):

image

Жмем Enter, сохраняем страницу (кнопка image сверху слева), переходим в браузер, обновляем страницу с представлением списка, вуаля!

image

Чтобы добавить еще одну ссылку рядом с New memo, желательно всё-таки использовать XSLT-разметку.

Для этого, давайте выделим всю строку, содержащую ссылку New memo. Кстати, вместо того чтобы тыкать 10 раз и пытаться попасть в нужный тэг <tr>, существует простой способ выделить строку, к которой принадлежит текущее выделение:

image

Теперь, не снимая выделения, переключаемся на вкладку Code:

image

Нам будет отображен фрагмент XSL-преобразования, ответственный за отображение как раз той самой строки с ссылкой.

Соответственно, этот кусок можно скопировать, вставить копию чуть ниже, и подкорректировать.

Во-первых, нужно заменить картинку, за которую ответственен вот этот кусок кода:
< span style="height:10px;width:10px;position:relative;display:inline-block;overflow:hidden;" class="s4-clust">

  <img src="/_layouts/images/fgimg.png" alt="" style="left:-0px !important;top:-128px !important;position:absolute;"  />
</span>
Подойдет любая картинка 10х10 пикселов. Если вы берете картинку не из спрайта, код можно упростить примерно до такого вида:

<img src="/_layouts/images/wpedit.gif" alt="" style="height:10px;width:10px;" />
Далее, нужно подкорректировать саму ссылку, за которую ответственен вот этот кусок XSLT-кода:

  <a class="ms-addnew" id="{$ID}"
     href="{$Url}"
     onclick="javascript:NewItem2(event, &quot;{$Url}&quot;);javascript:return false;"
     target="_self">
    <xsl:value-of select="'New memo'" />
  </a>
Здесь совет: когда это возможно, используйте JavaScript, и открывайте модальный диалог с нужной вам страницей. Это более привычное поведение для пользователей, т.к. ссылка New item открывает именно модальный диалог.

В остальных случаях, очень полезно использовать функцию GoToPage, которая описана у Alejo El Norte. Она добавит параметр Source к адресу целевой страницы, и позволит вам по нажатию кнопки «Отмена» или «Назад» на целевой странице, легко вернуться туда, откуда пользователь пришел.

В любом случае, открываете ли вы некую страницу в модальном диалоге или напрямую, как правило для формирования ссылки требуются некоторые типовые сведения:


  • GUID текущего списка
  • Url текущего Web’а
  • и т.д.

  • Все эти сведения можно взять из глобальных параметров XSLT. Они довольно хорошо описаны на MSDN.

    Чтобы не искать, самые интересные параметры:

    $ListGUID списка
    $ListUrlDirАдрес корневого каталога списка, аналог SPList.RootFolder.ServerRelativeUrl
    $ServerRelativeUrlАдрес текущего узла относительно адреса сервера, аналог SPWeb.ServerRelativeUrl
    $RootSiteUrlАдрес коллекции узлов, которой принадлежит текущий узел
    $LCIDСтрока, содержащая номер текущей локали, аналог Thread.CurrentThread.CurrentUICulture.LCID
    $UseridID текущего пользователя

    Также, иногда хочется отобразить ту или иную ссылку по некоему условию. Наиболее частое условие — наличие у пользователя каких-либо прав. В этом случае пригодится функция ddwrt:IfHasRights.

    Например, если я хочу отобразить ссылку на переход на некую страницу с дополнительными настройками списка, только если у пользователя есть права на управление списками ( SPBasePermissions.ManageLists), то я должен обернуть соответствующий <tr> в тег <xsl:if>, и передать в ddwrt:IfHasRights числовое значение, соответствующее ManageLists, т.е. 2048:

    <xsl:if test="ddwrt:IfHasRights(2048)">
      <!-- 2048 = SPBasePermissions.ManageLists -->
      <tr>
        <td class="ms-addnew" style="padding-bottom: 3px">
          <img src="/_layouts/images/wpedit.gif" alt="" style="height:10px;width:10px;" />
          <xsl:text disable-output-escaping="yes" ddwrt:nbsp-preserve="yes">&amp;nbsp;</xsl:text>
          <a class="ms-addnew" href="javascript:GoToPage('{$HttpVDir}/_layouts/My/MyPage.aspx?List={$List}');">
            Advanced settings
          </a>
        </td>
      </tr>
    </xsl:if>

    Соответствие строковых значений перечисления числовым, можно легко узнать, написав в Visual Studio “SPBasePermissions”, и нажав F12.

    Программный способ

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

    Имея готовый отлаженный код, перейдите во вкладку Code в SPD, и скопируйте полностью содержимое тега <Xsl>. Этот код вставьте в отдельный xslt-файл, который нужно будет задеплоить куда-нибудь в Layouts.

    Если вы всё-таки не хотите копаться в SPD, но хорошо чувствуете себя с XSLT… Что ж, минималистичный пример преобразования, которое заменяет стандартное “New item” на “New product”, приведен ниже:

    <xsl:stylesheet
      xmlns:x="http://www.w3.org/2001/XMLSchema"
      xmlns:d="http://schemas.microsoft.com/sharepoint/dsp"
      version="1.0"
      exclude-result-prefixes="xsl msxsl ddwrt"
      xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime"
      xmlns:asp="http://schemas.microsoft.com/ASPNET/20"
      xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:msxsl="urn:schemas-microsoft-com:xslt"
      xmlns:SharePoint="Microsoft.SharePoint.WebControls"
      xmlns:ddwrt2="urn:frontpage:internal"
      xmlns:o="urn:schemas-microsoft-com:office:office">
    
      <xsl:include href="/_layouts/xsl/main.xsl" />
      <xsl:include href="/_layouts/xsl/internal.xsl" />
    
      <xsl:template name="Freeform">
        <xsl:param name="AddNewText"/>
        <xsl:param name="ID"/>
        <xsl:variable name="Url" select="$ENCODED_FORM_NEW"/>
    
        <xsl:if test="$ListRight_AddListItems = '1' and (not($InlineEdit) or $IsDocLib)">
          <table id="Hero-{$WPQ}" width="100%" cellpadding="0" cellspacing="0" border="0">
            <tr>
              <td colspan="2" class="ms-partline">
                <img src="/_layouts/images/blank.gif" width="1" height="1" alt="" />
              </td>
            </tr>
            <tr>
              <td class="ms-addnew">
                <span style="height:10px;width:10px;position:relative;display:inline-block;overflow:hidden;" class="s4-clust">
                  <img src="/_layouts/images/fgimg.png" alt="" style="left:-0px !important;top:-128px !important;position:absolute;"  />
                </span>
                <xsl:text disable-output-escaping="yes" ddwrt:nbsp-preserve="yes">&amp;nbsp;</xsl:text>
                <a class="ms-addnew" id="{$ID}"
                    href="{$Url}"
                    onclick="javascript:NewItem2(event, &quot;{$Url}&quot;);javascript:return false;"
                    target="_self">
                  <xsl:value-of select="New memo" />
                </a>
              </td>
            </tr>
            <tr>
              <td>
                <img src="/_layouts/images/blank.gif" width="1" height="5" alt="" />
              </td>
            </tr>
          </table>
        </xsl:if>
      </xsl:template>
    
    </xsl:stylesheet>

    Как и в случае с SDP, этот код нужно положить в отдельный файл, и задеплоить куда-нибудь в Layouts.

    Файл есть, теперь XSLT-преобразование к представлению списка подключаются очень просто, например при активации вашей фичи:

    public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {
        var web = properties.Feature.Parent as SPWeb;
        var list = web.Lists["My list title"];
        var view = list.DefaultView;
        view.XslLink = @"../My/MyTransform.xsl";    view.Update();
    }

    Здесь я предполагаю, что фича имеет Scope=Web, XSLT-преобразование лежит в файле Layouts/My/MyTransform.xsl (путь указывается относительно папки Layouts/Xsl), а у списка заголовок “My list title” (хотя получать списки по заголовку нежелательно, лучше по Url или по Guid).

    Комментариев нет:

    Отправить комментарий