Недавно меня волновал вопрос Вывод списка в таблицу по четыре ячейки в строке. Тогда это был, скорее даже не список, а набор элементов, которые могут быть вложены в такие же элементы. Я получил в комментариях очень интересную ссылку (http://korchasa.livejournal.com/15533.ht ml?thread=54957#t54957) на способы решения этой проблемы. Ни один из способов не заработал, но пищу для размышлений я получил. Вот какой способ мне пришел в голову.
Допустим у нас есть xml, где в корневом элементе items лежит набор элементов item с некоторым содержимым, которое нам нужно вывести. Мы выводим каждый 4-ый элемент, сразу за ним выводим 3 соседних элемента.
Пример xml:
У этого способа есть один недостаток. При значительном росте числа столбцов он становится неудобным. Впрочем, это встречается не очень часто.
Допустим у нас есть xml, где в корневом элементе items лежит набор элементов item с некоторым содержимым, которое нам нужно вывести. Мы выводим каждый 4-ый элемент, сразу за ним выводим 3 соседних элемента.
<xsl:for-each select="/items/item[position() mod 4 = 1]">
<tr>
<td><xsl:value-of select="."/></td>
<td><xsl:value-of select="following-sibling::node()"/></td>
<td><xsl:value-of select="following-sibling::node()/following-sibling::node()"/></td>
<td>
<xsl:value-of select="following-sibling::node()/following-sibling::node()/following-sibling::node()"/>
</td>
</tr>
</xsl:for-each>
Пример xml:
<items>Ну и не забываем про <xsl:strip-space elements="*"/> он убирает все пустые текстовые узлы между тегами.
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
<item>5</item>
<item>6</item>
<item>7</item>
<item>8</item>
<item>9</item>
</items>
У этого способа есть один недостаток. При значительном росте числа столбцов он становится неудобным. Впрочем, это встречается не очень часто.
Интересное наблюдение я сделал за последнее время. Относительно работодателей и их способов выбирать себе сотрудников (программистов и верстальщиков).
( Read more... )
( Read more... )
Довольно часто при веб-разработке возникает задача определить что за браузер у пользователя. Например, если мы хотим подключить CSS файл или специфический для браузера JavaScript. Эта функция вернет краткое имя браузера и номер его версии.
Например: ie6, ff3, op9.8 и т.д. Если браузер и версию определить не удалось -1.
function getBrowserVersion() {
if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)){
return 'ff'+Number(RegExp.$1);
} else if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)){
return 'ie'+Number(RegExp.$1);
} else if (/Opera[\/\s](\d+\.\d+)/.test(navigator.userAgent)){
return 'op'+Number(RegExp.$1);
} else if (/Chrome[\/\s](\d+\.\d+)/.test(navigator.userAgent)){
return 'ch'+Number(RegExp.$1);
} else if (/Safari[\/\s](\d+\.\d+)/.test(navigator.userAgent)){
return 'sf'+Number(RegExp.$1);
} else {
return -1;
}
}
Также в эту функцию не сложно добавить определение любого другого браузера.
При написании этой функции мне помогла статья:
http://www.javascriptkit.com/javatutors/n avigator.shtml
Например: ie6, ff3, op9.8 и т.д. Если браузер и версию определить не удалось -1.
function getBrowserVersion() {
if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)){
return 'ff'+Number(RegExp.$1);
} else if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)){
return 'ie'+Number(RegExp.$1);
} else if (/Opera[\/\s](\d+\.\d+)/.test(navigator.userAgent)){
return 'op'+Number(RegExp.$1);
} else if (/Chrome[\/\s](\d+\.\d+)/.test(navigator.userAgent)){
return 'ch'+Number(RegExp.$1);
} else if (/Safari[\/\s](\d+\.\d+)/.test(navigator.userAgent)){
return 'sf'+Number(RegExp.$1);
} else {
return -1;
}
}
Также в эту функцию не сложно добавить определение любого другого браузера.
При написании этой функции мне помогла статья:
http://www.javascriptkit.com/javatutors/n
Возникла такая задачка: организовать вывод списка элементов в виде таблицы по четыре элемента в строке. Первое что приходит в голову:
<xsl:variable name="tr"><![CDATA[</tr><tr>]]></xsl:variable>
<table>
<caption>Способ 1.</caption>
<tr>
<xsl:for-each select="//item">
<td>
<xsl:value-of select="title" />
</td>
<xsl:choose>
<xsl:when test="position() = last()">
<xsl:if test="position() mod 4 = 1">
<td></td><td></td><td></td>
</xsl:if>
<xsl:if test="position() mod 4 = 2">
<td></td><td></td>
</xsl:if>
<xsl:if test="position() mod 4 = 3">
<td></td>
</xsl:if>
</xsl:when>
<xsl:when test="(position() mod 4 = 0)">
<xsl:value-of select="$tr" disable-output-escaping="yes" />
</xsl:when>
</xsl:choose>
</xsl:for-each>
</tr>
</table>
Если не брать в расчет желание сделать последнюю строчку нормальной (4 ячейки), то шаблон можно сократить.
Однако меня мучают сомнения, может быть есть еще способы? Например, вопользоваться группировкой Мюнха...
<xsl:variable name="tr"><![CDATA[</tr><tr>]]></xsl:variable>
<table>
<caption>Способ 1.</caption>
<tr>
<xsl:for-each select="//item">
<td>
<xsl:value-of select="title" />
</td>
<xsl:choose>
<xsl:when test="position() = last()">
<xsl:if test="position() mod 4 = 1">
<td></td><td></td><td></td>
</xsl:if>
<xsl:if test="position() mod 4 = 2">
<td></td><td></td>
</xsl:if>
<xsl:if test="position() mod 4 = 3">
<td></td>
</xsl:if>
</xsl:when>
<xsl:when test="(position() mod 4 = 0)">
<xsl:value-of select="$tr" disable-output-escaping="yes" />
</xsl:when>
</xsl:choose>
</xsl:for-each>
</tr>
</table>
Если не брать в расчет желание сделать последнюю строчку нормальной (4 ячейки), то шаблон можно сократить.
Однако меня мучают сомнения, может быть есть еще способы? Например, вопользоваться группировкой Мюнха...
В JS существует такое понятие, как "распространение события". Например мы щелкаем мышкой по элементу. Он первым получает событие и обрабатывает его. Далее событие идет к родителю этого элемента. И так до пра-пра-пра... родителей.
Однако тревожить предков не всегда целесообразно, а иногда и небезопасно =)
Для завершения распространения события я давным давно нашел такой кроссбраузерный способ:
if (!event) var event = window.event;
event.cancelBubble = true;
if (event.stopPropagation) event.stopPropagation();
Поправки и дополнения приветствуются =)
Однако тревожить предков не всегда целесообразно, а иногда и небезопасно =)
Для завершения распространения события я давным давно нашел такой кроссбраузерный способ:
if (!event) var event = window.event;
event.cancelBubble = true;
if (event.stopPropagation) event.stopPropagation();
Поправки и дополнения приветствуются =)
Сегодня столкнулся с такой интересной задачкой. Нужно с помощью JS подключить CSS-файл. Для решения этой задачи я нашел такой способ:
filename - имя файла
filetype - тип ресурса (js\css)
На удивление удобное и лаконичное решение.
Нашел тут:
http://www.javascriptkit.com/javatutors/l oadjavascriptcss.shtml
там, кстати, есть еще решение для контроля того, какие файлы уже загружены и еще есть решение для динамической замены ресурса:
http://www.javascriptkit.com/javatutors/l oadjavascriptcss2.shtml
C другой стороны, можно не мутить хитрое решение, а просто собрать строку и записать ее в innerHTML следом за всем остальным содержимым. Но это будет уже не так интересно.
function loadjscssfile (filename, filetype) {
if (filetype=="js"){
var fileref=document.createElement('script')
fileref.setAttribute("type","text/javascript")
fileref.setAttribute("src", filename)
}
else if (filetype=="css"){
var fileref=document.createElement("link")
fileref.setAttribute("rel", "stylesheet")
fileref.setAttribute("type", "text/css")
fileref.setAttribute("href", filename)
}
if (typeof fileref!="undefined")
document.getElementsByTagName("head")[0].appendChild(fileref)
}
на вход этой функции можно подавать:filename - имя файла
filetype - тип ресурса (js\css)
На удивление удобное и лаконичное решение.
Нашел тут:
http://www.javascriptkit.com/javatutors/l
там, кстати, есть еще решение для контроля того, какие файлы уже загружены и еще есть решение для динамической замены ресурса:
http://www.javascriptkit.com/javatutors/l
C другой стороны, можно не мутить хитрое решение, а просто собрать строку и записать ее в innerHTML следом за всем остальным содержимым. Но это будет уже не так интересно.
Недавно я писал про MinoPlayer на SilverLight. Однако, хоть SilverLight и имеет версию под Linux, пока он может оказаться далеко не у всех пользователей. Поэтому следует вспомнить про технологию Flash, которая уже давным давно развивается. Ну и плюс для проигрывания WMV можно использовать MinoPlayer, а для FLV и MP3 флешовый.
В моей жизни не было опыта работы с такими проигрывателями и поэтому я решил закрыть этот пробел в знаниях. Первое что попалось под руку: JW FLV Player. Вещица удобная и бесплатная для некоммерческих проектов.
Проигрываем видео:
<object id="player" classid="clsid:D27CDB6E-AE6D-11cf-96B8-4445535400 00" name="player" width="328" height="200">
<param name="movie" value="player-viral.swf" />
<param name="allowfullscreen" value="true" />
<param name="allowscriptaccess" value="always" />
<param name="flashvars" value="file=video.flv&image=preview.jpg" />
<embed
type="application/x-shockwave-flash"
id="player2"
name="player2"
src="player-viral.swf"
width="328"
height="200"
allowscriptaccess="always"
allowfullscreen="true"
flashvars="file=video.flv&image=preview.jpg"
/>
</object>
Проигрываем mp3:
<object id="player3" classid="clsid:D27CDB6E-AE6D-11cf-96B8-4445535400 00" name="player3" width="328" height="20">
<param name="movie" value="player-viral.swf" />
<param name="allowfullscreen" value="true" />
<param name="allowscriptaccess" value="always" />
<param name="flashvars" value="file=audio.mp3" />
<embed
type="application/x-shockwave-flash"
id="player4"
name="player4"
src="player-viral.swf"
width="328"
height="20"
allowscriptaccess="always"
allowfullscreen="true"
flashvars="file=audio.mp3"
/>
</object>
Все параметры говорящие, описывать их своими словами нет смысла.
Подробности про JW FLV Player
В моей жизни не было опыта работы с такими проигрывателями и поэтому я решил закрыть этот пробел в знаниях. Первое что попалось под руку: JW FLV Player. Вещица удобная и бесплатная для некоммерческих проектов.
Проигрываем видео:
<object id="player" classid="clsid:D27CDB6E-AE6D-11cf-96B8-4445535400
<param name="movie" value="player-viral.swf" />
<param name="allowfullscreen" value="true" />
<param name="allowscriptaccess" value="always" />
<param name="flashvars" value="file=video.flv&image=preview.jpg" />
<embed
type="application/x-shockwave-flash"
id="player2"
name="player2"
src="player-viral.swf"
width="328"
height="200"
allowscriptaccess="always"
allowfullscreen="true"
flashvars="file=video.flv&image=preview.jpg"
/>
</object>
Проигрываем mp3:
<object id="player3" classid="clsid:D27CDB6E-AE6D-11cf-96B8-4445535400
<param name="movie" value="player-viral.swf" />
<param name="allowfullscreen" value="true" />
<param name="allowscriptaccess" value="always" />
<param name="flashvars" value="file=audio.mp3" />
<embed
type="application/x-shockwave-flash"
id="player4"
name="player4"
src="player-viral.swf"
width="328"
height="20"
allowscriptaccess="always"
allowfullscreen="true"
flashvars="file=audio.mp3"
/>
</object>
Все параметры говорящие, описывать их своими словами нет смысла.
Подробности про JW FLV Player
Вот почему в почте можно указывать только тему сообщения? Так было бы удобно поставить тегов к отправляемому или полученному сообщению и потом искать по таким тегам. Эх...
Что-то я увлекся приложениями на базе SilverLight (см. Как использовать MinoPlayer). А ведь они могут оказаться действительно полезными и удобными. Например фотогалерея на SilverLight. Ее можно легко установить на любой сайт. На страницу вставляем вот такой код:
<object data="data:application/x-silverlight," type="application/x-silverlight-2" width="405" height="350">
<param name="source" value="ClientBin/SilverlightPhotoGallery.xap"/>
<param name="onerror" value="onSilverlightError" />
<param name="background" value="white" />
<param name="minRuntimeVersion" value="2.0.31005.0" />
<param name="autoUpgrade" value="true" />
<a href="http://go.microsoft.com/fwlink/?LinkID=1 24807">
<img src="http://go.microsoft.com/fwlink/?LinkId=1 08181" alt="Get Microsoft Silverlight"/>
</a>
</object>
В нем важно заменить строку ClientBin/SilverlightPhotoGallery.xap путь к приложению в виде URL. Остальное можно заменить при желании.
Далее, рядом со страницей нужно создать файл gallery.xml
Другое имя использовать не получится. Содержимое файла должно быть примерно таким:
<images>
<picture>
<thumbnail>/gallery/th_image2.jpg</thumbnail>
<image>/gallery/image2.jpg</image>
<text>test</text>
</picture>
<picture>
<thumbnail>/gallery/th_image1.jpg</thumbnail>
<image>/gallery/image1.jpg</image>
<text>test desc</text>
</picture>
</images>
В общем все теги и названия говорящие. При желании можно сделать автоматический генератор такого файла из БД или любого другого источника данных.
Архив с приложением PhotoGallery
Подробности на английском про PhotoGallery
<object data="data:application/x-silverlight," type="application/x-silverlight-2" width="405" height="350">
<param name="source" value="ClientBin/SilverlightPhotoGallery.xap"/>
<param name="onerror" value="onSilverlightError" />
<param name="background" value="white" />
<param name="minRuntimeVersion" value="2.0.31005.0" />
<param name="autoUpgrade" value="true" />
<a href="http://go.microsoft.com/fwlink/?LinkID=1
<img src="http://go.microsoft.com/fwlink/?LinkId=1
</a>
</object>
В нем важно заменить строку ClientBin/SilverlightPhotoGallery.xap путь к приложению в виде URL. Остальное можно заменить при желании.
Далее, рядом со страницей нужно создать файл gallery.xml
Другое имя использовать не получится. Содержимое файла должно быть примерно таким:
<images>
<picture>
<thumbnail>/gallery/th_image2.jpg</thumbnail>
<image>/gallery/image2.jpg</image>
<text>test</text>
</picture>
<picture>
<thumbnail>/gallery/th_image1.jpg</thumbnail>
<image>/gallery/image1.jpg</image>
<text>test desc</text>
</picture>
</images>
В общем все теги и названия говорящие. При желании можно сделать автоматический генератор такого файла из БД или любого другого источника данных.
Архив с приложением PhotoGallery
Подробности на английском про PhotoGallery
Нашел занимательный проигрыватель под названием MinoPlayer.
<object data="data:application/x-silverlight," type="application/x-silverlight-2" width="500" height="330">
<param name="source" value="ClientBin/MinoPlayer_Ver1_2.xap.xap"/>
<param name="onerror" value="onSilverlightError" />
<param name="background" value="black" />
<param name="initParams" value="VideoSource=http://silverlight.services.live.com/601 07/HD%20Future%20Markers/video.wmv,AutoPlay=false,EnableScrubbing=true,InitialVolume=1,PreviewImage=http://www.silverlight-blog.it/vid/HD_fu ture_Thumb.jpg,LogoImage=http://www.silverlight-blog.it/vid/Logo.p ng,MarkersTimeView=5" />
<param name="minRuntimeVersion" value="2.0.31005.0" />
<param name="autoUpgrade" value="true" />
<a href="http://go.microsoft.com/fwlink/?LinkID=1 24807">
<img src="http://go.microsoft.com/fwlink/?LinkId=1 08181" alt="Get Microsoft Silverlight"/>
</a>
</object>
Оранжевым подсвечены места, которые можно настраивать (ширина, высота, фон, путь к видеоролику и т.д.).
Для работы этого проигрывателя нужно его скачать, развернуть у себя на сервере и указать URL вместо строчки ClientBin/MinoPlayer_Ver1_2.xap.xap. Без этого будет просто черный прямоугольник.
Для тех, кто уверен в своих пользователях - можно убрать ссылку на получение SilverLight.
Для чего в оригинале был пустой и скрытый iframe я не понял, поэтому его убрал.
Архив с проигрывателем MinoPlayer (26 Кб)
Подробности про MinoPlayer на английском
<object data="data:application/x-silverlight," type="application/x-silverlight-2" width="500" height="330">
<param name="source" value="ClientBin/MinoPlayer_Ver1_2.xap.xap"/>
<param name="onerror" value="onSilverlightError" />
<param name="background" value="black" />
<param name="initParams" value="VideoSource=http://silverlight.services.live.com/601
<param name="minRuntimeVersion" value="2.0.31005.0" />
<param name="autoUpgrade" value="true" />
<a href="http://go.microsoft.com/fwlink/?LinkID=1
<img src="http://go.microsoft.com/fwlink/?LinkId=1
</a>
</object>
Оранжевым подсвечены места, которые можно настраивать (ширина, высота, фон, путь к видеоролику и т.д.).
Для работы этого проигрывателя нужно его скачать, развернуть у себя на сервере и указать URL вместо строчки ClientBin/MinoPlayer_Ver1_2.xap.xap. Без этого будет просто черный прямоугольник.
Для тех, кто уверен в своих пользователях - можно убрать ссылку на получение SilverLight.
Для чего в оригинале был пустой и скрытый iframe я не понял, поэтому его убрал.
Архив с проигрывателем MinoPlayer (26 Кб)
Подробности про MinoPlayer на английском
Сегодня у меня появилась интересная задачка. Нужно сделать меню у которого, при наведении курсора на отдельный пункт у него меняется фон. Все вроде бы просто, но при этом у каждого пункта должна быть своя иконка, под которой этот фон тоже должен меняться. Получается использовать псевдокласс :hover уже нельзя, т.к. иначе, при наведении курсора фон тега a будет закрывать иконку у тега li. А два фона к одному тегу применить пока нельзя.
Если на li мы повесим фон, а на a иконку - все будет работать только в FF и каких-нибудь других браузерах, но не в IE6. Дело в том, что IE6 поддерживает :hover только для тега a.
Справиться с этой бедой мне поможет JavaScript. Однако я не буду делать несемантичные onmouseover\onmouseout прямо в коде. Эффективнее и изящнее сделать так:
При решении этой задачки мне немного помогла запись Меняем класс у объекта
Проблема не нова, но встречается часто. Поэтому полезно под рукой иметь такой образец.
<ul id="menu"> <li class="first"><a href="#">Первый пункт</a></li> <li class="second"><a href="#">Второй</a></li> </ul>
Если на li мы повесим фон, а на a иконку - все будет работать только в FF и каких-нибудь других браузерах, но не в IE6. Дело в том, что IE6 поддерживает :hover только для тега a.
Справиться с этой бедой мне поможет JavaScript. Однако я не буду делать несемантичные onmouseover\onmouseout прямо в коде. Эффективнее и изящнее сделать так:
var menuitems = document.getElementById('menu').childNodes;
for (var i = 0; i < menuitems.length; i++) {
menuitems[i].onmouseover = function() {this.className = this.className + ' miover';};
menuitems[i].onmouseout = function() {this.className = this.className.replace(/ miover/, '');};
}А в CSS прописать свойства для класса miover.При решении этой задачки мне немного помогла запись Меняем класс у объекта
Проблема не нова, но встречается часто. Поэтому полезно под рукой иметь такой образец.
Прошлым летом на собеседовании мне задали такой вопрос: в чем разница между apply-templates и for-each. Тогда я не знал этого и не ответил. Но до сих пор я время от времени возвращаюсь к нему. На данный момент удалось узнать следующее:
Может еще что-нибудь есть?
| Возможность | apply-templates | for-each |
| Организовать рекурсию | + | – |
| Что нужно сделать для вывода содержимого узла | ничего, все будет выведено автоматически | использовать дополнительные средства типа value-of select="." |
| Встроенный счетчик position() | считает в том числе и пустые текстовые узлы | будет работать корректно в любом случае |
Может еще что-нибудь есть?
Мне давным давно не дает покоя одна задачка. Сделать такой обработчик XSLT, чтобы при минимуме программирования (или даже его отсутствии) можно было делать относительно простые сайты. Понятное дело, что они не будут реализовывать какой-нибудь сложный функционал типа загрузки файлов, регистрации пользователей, отправки писем или упаковки чего-нибудь в базу данных. Для программиста это все тривиально, а для простого верстальщика это сложно. Поэтому я решил сделать заготовку на PHP, языке который только ленивый не знает.
Основное требование к обработчику XSLT - получение POST и GET запросов в виде XML. На их основе можно брать XML файлы, выполнять разные преобразования. ЧПУ можно будет реализовать с помощью .htaccess.
/?template=test
будут приводить к попытке обработать файл xsl/test.xsl
туда же будут передаваться все переменные запросов GET и POST (если такие были).
Можно добавить в XML еще каких-нибудь серверных данных, но мне пока в голову ничего не приходит. Может текущее время?
Основное требование к обработчику XSLT - получение POST и GET запросов в виде XML. На их основе можно брать XML файлы, выполнять разные преобразования. ЧПУ можно будет реализовать с помощью .htaccess.
<? // error_reporting(E_ALL); // ini_set("display_errors", 1); $template = 'default'; parse_str($_SERVER['QUERY_STRING']); $xslDoc = new DOMDocument('1.0', 'UTF-8'); $xslDoc->load("xsl/$template.xsl"); $proc = new XSLTProcessor(); $proc->importStylesheet($xslDoc); $xml = '<data>'; if (isset($_POST)) { $xml .= '<post>'; foreach ($_POST as $key => $value) { $xml .= "<item name=\"$key\">$value</item>"; } $xml .= '</post>'; } elseif (isset($_GET) { $xml .= '<get>'; foreach ($_GET as $key => $value) { $xml .= "<item name=\"$key\">$value</item>"; } $xml .= '</get>'; } $xml .= '</data>'; $xml = new SimpleXMLElement($xml); echo $proc->transformToDoc($xml)->saveXML(); ?>Если положить такой файл в корень директории с именем index.php, то обращения к этой директории в духе:
/?template=test
будут приводить к попытке обработать файл xsl/test.xsl
туда же будут передаваться все переменные запросов GET и POST (если такие были).
Можно добавить в XML еще каких-нибудь серверных данных, но мне пока в голову ничего не приходит. Может текущее время?
Общеизвестно, что в XSLT 1.0 есть трудности с выводом специальных символов типа < >
До употребления их необходимо определять следующим образом:
hars.php
К сожалению, такое подключение работает не везде. В случае стандартного PHP процессора это решение отрабатывает корректно, а вот в SharePoint 2007 DVWP их подключить не получится (по соображениям безопасности).
Поэтому лучше стараться использовать и запоминать цифровые коды, а если есть большой массив данных в котором задействованы именованные сущности (спецсимволы), то можно попробовать подключить такой файл.
До употребления их необходимо определять следующим образом:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE xsl:stylesheet[Таких специальных символов может быть много и тащить такую "простыню" каждый раз бывает утомительно и неэффективно. Поэтому можно подключать их из внешнего файла вот таким образом:
<!ENTITY nbsp " ">
<!ENTITY lt "<">
<!ENTITY gt ">">
]> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!--Выводим сущности < >-->
</xsl:stylesheet>
<!DOCTYPE xsl:stylesheet[А внутри файла нужно писать так:
<!ENTITY % special PUBLIC "-//W3C//ENTITIES Special for XHTML//EN" "xhtml-special.ent">
]>
<?xml version='1.0' encoding='UTF-8'?>Туда можно по аналогии дописывать еще символы. К примеру можно воспользоваться этим справочником: http://html.manual.ru/book/info/specialc
<!DOCTYPE xsl:stylesheet[
<!ENTITY nbsp " ">
<!ENTITY lt "<">
<!ENTITY gt ">">
<!ENTITY copy "©">
<!ENTITY amp "&">
<!ENTITY raquo "»">
<!ENTITY laquo "«">
]>
К сожалению, такое подключение работает не везде. В случае стандартного PHP процессора это решение отрабатывает корректно, а вот в SharePoint 2007 DVWP их подключить не получится (по соображениям безопасности).
Поэтому лучше стараться использовать и запоминать цифровые коды, а если есть большой массив данных в котором задействованы именованные сущности (спецсимволы), то можно попробовать подключить такой файл.
Сегодня у меня возникла задачка - отсортировать набор элементов по дате. Дата подается в формате:
2009-09-23T08:41:10Z
Однако в XSLT1.0 в xsl:sort нет опции - сортировать по дате, можно только сортировать по номеру или по строке. Поэтому возникла мысль сделать сортировку по дате вот таким образом:
2009-09-23T08:41:10Z
Однако в XSLT1.0 в xsl:sort нет опции - сортировать по дате, можно только сортировать по номеру или по строке. Поэтому возникла мысль сделать сортировку по дате вот таким образом:
<xsl:sort select="substring(@Date, 1, 4)" data-type="number" />иными словами мы сортируем сперва по году, потом по месяцу и т.д.
<xsl:sort select="substring(@Date, 6, 2)" data-type="number" />
<xsl:sort select="substring(@Date, 9, 2)" data-type="number" />
<xsl:sort select="substring(@Date, 12, 2)" data-type="number" />
<xsl:sort select="substring(@Date, 15, 2)" data-type="number" /> <xsl:sort select="substring(@Date, 19, 2)" data-type="number" />
Довольно часто возникает задача аккуратно сменить один класс объекта на другой по щелчку на каком-нибудь объекте. Каждый раз искать эту функцию в старых проектах очень неудобно. Проще скопировать ее откуда-нибудь из публичного места.
Чаще всего такая задача возникает при отображении и скрытии объекта. Для этого можно воспользоваться двумя классами:
listexpanded - который отображает элемент (имеет соответствующее свойство в CSS)
listcollapsed - который скрывает свое содержимое (опять же через свойство)
function changeClass(elid) {
var element = document.getElementById(elid);
if (element != null) {
if (element.className.search(/listcollapsed/ ) == -1) {
element.className = element.className.replace(/listexpanded/ , 'listcollapsed');
}
else {
element.className = element.className.replace(/listcollapsed/ , 'listexpanded');
}
}
}
Чаще всего такая задача возникает при отображении и скрытии объекта. Для этого можно воспользоваться двумя классами:
listexpanded - который отображает элемент (имеет соответствующее свойство в CSS)
listcollapsed - который скрывает свое содержимое (опять же через свойство)
function changeClass(elid) {
var element = document.getElementById(elid);
if (element != null) {
if (element.className.search(/listcollapsed/
element.className = element.className.replace(/listexpanded/
}
else {
element.className = element.className.replace(/listcollapsed/
}
}
}
Сегодня у мну возникла задача выводить возраст человека с человечной подписью единиц измерения. Типа: 34 года, 15 лет, 41 год.
В результате размышлений возник такой шаблончик:
<xsl:template name="formatage">
<xsl:param name="age" />
<xsl:value-of select="$age"/>
<xsl:text> </xsl:text>
<xsl:choose>
<xsl:when test="($age = 11) or ($age = 12) or ($age = 13) or ($age = 14)">лет</xsl:when>
<xsl:otherwise>
<xsl:variable name="lastnum"><xsl:value-of select="substring($age, string-length($age))"/></xsl:variable>
<xsl:choose>
<xsl:when test="($lastnum = 2) or ($lastnum = 3) or ($lastnum = 4)">года</xsl:when>
<xsl:when test="($lastnum = 0) or ($lastnum = 5) or ($lastnum = 6) or ($lastnum = 7) or ($lastnum = 8) or ($lastnum = 9)">лет</xsl:when>
<xsl:otherwise>год</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Использовать его можно так:
<xsl:call-template name="formatage">
<xsl:with-param name="age">77</xsl:with-param>
</xsl:call-template>
--------------------------
Обновленный и оптимизированный вариант шаблона без ограничений величины срока (предложен
ibnteo):
В результате размышлений возник такой шаблончик:
<xsl:template name="formatage">
<xsl:param name="age" />
<xsl:value-of select="$age"/>
<xsl:text> </xsl:text>
<xsl:choose>
<xsl:when test="($age = 11) or ($age = 12) or ($age = 13) or ($age = 14)">лет</xsl:when>
<xsl:otherwise>
<xsl:variable name="lastnum"><xsl:value-of select="substring($age, string-length($age))"/></xsl:variable>
<xsl:choose>
<xsl:when test="($lastnum = 2) or ($lastnum = 3) or ($lastnum = 4)">года</xsl:when>
<xsl:when test="($lastnum = 0) or ($lastnum = 5) or ($lastnum = 6) or ($lastnum = 7) or ($lastnum = 8) or ($lastnum = 9)">лет</xsl:when>
<xsl:otherwise>год</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Использовать его можно так:
<xsl:call-template name="formatage">
<xsl:with-param name="age">77</xsl:with-param>
</xsl:call-template>
--------------------------
Обновленный и оптимизированный вариант шаблона без ограничений величины срока (предложен
<xsl:template name="formatage">
<xsl:param name="age" />
<xsl:value-of select="$age"/>
<xsl:text> </xsl:text>
<xsl:variable name="lastnum" select="substring($age, string-length($age))"/>
<xsl:variable name="last2num" select="substring($age, string-length($age) - 1)"/>
<xsl:choose>
<xsl:when test="$lastnum = 1 and not($last2num = 11 or $last2num = 12 or $last2num = 13 or $last2num = 14)">год</xsl:when>
<xsl:when test="$lastnum = 2 or $lastnum = 3 or $lastnum = 4">года</xsl:when>
<xsl:otherwise>лет</xsl:otherwise>
</xsl:choose>
</xsl:template>
Встретился на работе с такой интересной задачкой. При обработке XML в XSL нужно пометить каждую четную итерацию.
При использовании xsl:for-each все получается тривиально: берем стандартную функцию position() и делаем с ней mod 2 = 0.
Иными словами поступаем вот так:
<xsl:for-each select="items/item">
<xsl:if test="position() mod 2 = 0">четная</xsl:if>
<xsl:value-of select="." />
</xsl:for-each>
А вот когда используется xsl:apply-templates этот position() выдает черти-что. Мне в голову приходит только один вариант решения:
<xsl:template match="items/item">
<xsl:variable name="position"><xsl:number format="1" /></xsl:variable>
<xsl:if test="$position mod 2 = 0">четная</xsl:if>
<xsl:value-of select="." />
</xsl:template>
Вопрос в том, не горожу ли я огород. Может быть в при вызове шаблона нужно как-то переинициализировать счетчик или как-то по-особому его вызывать?
Впрочем, решение работает.
При использовании xsl:for-each все получается тривиально: берем стандартную функцию position() и делаем с ней mod 2 = 0.
Иными словами поступаем вот так:
<xsl:for-each select="items/item">
<xsl:if test="position() mod 2 = 0">четная</xsl:if>
<xsl:value-of select="." />
</xsl:for-each>
А вот когда используется xsl:apply-templates этот position() выдает черти-что. Мне в голову приходит только один вариант решения:
<xsl:template match="items/item">
<xsl:variable name="position"><xsl:number format="1" /></xsl:variable>
<xsl:if test="$position mod 2 = 0">четная</xsl:if>
<xsl:value-of select="." />
</xsl:template>
Вопрос в том, не горожу ли я огород. Может быть в при вызове шаблона нужно как-то переинициализировать счетчик или как-то по-особому его вызывать?
Впрочем, решение работает.
