Небольшой сниппет вместо модуля tagadelic (Облако тэгов)

Главные вкладки

Аватар пользователя olk olk 30 сентября 2008 в 17:59

Небольшой сниппет, показывающее облако тэгов по заданному (через код vid) словарю ...
Конечно он не покрывает все возможности и настройки модуля tagadelic, но в некоторых случаях может оказаться полезным
Для темизации всего блока можно использовать стилизацию tags.voc-номер-словоря,
для темизации терминов a.tags-voc-номер-словоря ...
PS.Данный код выводит только «реальные» термины словоря, т.е. термины которые «привязаны» к нодам (просто мне показалось не логичным выводить «пустые» тэги, не связанные с материалом)
Обновление:
Добавил сортировку терминов в сниппет, переменная $order может принимать следующие значения
0 - сортировка по ид термина
1 - сортировка по весу по убыванию (с наибольшим весом выше)
2 - сортировка по весу по возрастанию (с наибольшим весом ниже)
другое значение - сортировка по имени термина


<?php
$max_fontsize 
150// Размер шрифта для тэга с максимальным весом
$min_fontsize 90;  // Размер шрифта для тэга с минимальным весом
$metrics '%';      // в чем измеряется размер px,pt,em,%
$voc 3;            // vid словаря
$order 1;          // сортировка терминов
// 0 - сортировка по ид термина
// 1 - сортировка по весу по убыванию (с наибольшим весом выше)
// 2 - сортировка по весу по возрастанию (с наибольшим весом ниже)
// другое значение - сортировка по имени термина
// получим максимальны и минимальный вес терминов в словаре
$result db_query(db_rewrite_sql("SELECT max(cnt) AS maxcnt,min(cnt) AS mincnt 
FROM {term_data} td  INNER JOIN 
(SELECT tn.tid,COUNT(tn.nid) as cnt  FROM {term_node} tn 
INNER JOIN {node} n ON n.nid=tn.nid GROUP BY tn.tid) n 
ON n.tid=td.tid AND td.vid=%d"
),$voc);
$term db_fetch_object($result);
$min_weight $term->mincnt;
$max_weight $term->maxcnt;
// вычислим коэффициент для размера шрифта
if ($min_weight == $max_weight ) {
    
$font_metric_koof 0
}
else {
    
$font_metric_koof = ($max_fontsize $min_fontsize) / ($max_weight $min_weight);
}
$ord '';
switch(
$order){
 case 
0
       
$ord 'ORDER BY td.tid'
       break;
 case 
1
       
$ord 'ORDER BY n.cnt DESC'
       break;
 case 
2
       
$ord 'ORDER BY n.cnt'
       break;
 default: 
       
$ord 'ORDER BY td.name';
}
$result db_query(db_rewrite_sql("SELECT td.tid,td.name,n.cnt 
FROM {term_data} td  INNER JOIN 
(SELECT tn.tid,COUNT(tn.nid) as cnt  FROM {term_node} tn 
INNER JOIN {node} n ON n.nid=tn.nid GROUP BY tn.tid) n 
ON n.tid=td.tid AND td.vid=%d "
.$ord),$voc);
$tags '';
while(
$term db_fetch_object($result)) {
 
$size $min_fontsize + ($term->cnt $min_weight) * $font_metric_koof;
 
$style 'font-size: '.$size.$metrics.';'
 
$tags .= l($term->name,'taxonomy/term/'.$term->tid,
   array(
'attributes' => array('style' => $style,'class' => 'tags-voc-'.$voc))).' ';

if (!empty(
$tags)) {
  print 
'<tags class="voc-'.$voc.'">'.$tags.'</tags>';
}
?>

Комментарии

Аватар пользователя VladSavitsky VladSavitsky 30 сентября 2008 в 21:43

Отличная работа!
Уже не раз задумывался о такой штучке. Очень полезно, если нужно выводить блок с облаком в разных местах (регионах) на разных страницах сайта...
Спасибо.

Аватар пользователя worona worona 30 сентября 2008 в 22:48

user warning: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECTG max(cnt) AS maxcnt,min(cnt) AS mincnt FROM term_data td INNER JOIN (S' at line 1 query: SELECTG max(cnt) AS maxcnt,min(cnt) AS mincnt FROM term_data td INNER JOIN (SELECT tn.tid,COUNT(tn.nid) as cnt FROM term_node tn INNER JOIN node n ON n.nid=tn.nid GROUP BY tn.tid) n ON n.tid=td.tid AND td.vid=3 in Z:\home\dru\www\includes\common.inc(1537) : eval()'d code on line 12

Не силен в этом, такая вот ошибка???

Аватар пользователя olk olk 1 октября 2008 в 9:55

Да ладно - застыдили Lol «Папа у Васи силен в математике» :),а не в русском языке , хотя я с этим борюсь Smile

Аватар пользователя T-34 T-34 22 ноября 2008 в 17:31

olk wrote:
Данный код выводит только «реальные» термины словоря, т.е. термины которые «привязаны» к нодам (просто мне показалось не логичным выводить «пустые» тэги, не связанные с материалом)

Если не трудно, подскажите пожалуйста, где в коде это условие записано.

Аватар пользователя olk olk 24 ноября 2008 в 10:54

SELECT tn.tid,COUNT(tn.nid) as cnt FROM {term_node} tn
INNER JOIN {node} n ON n.nid=tn.nid GROUP BY tn.tid

Данный вложенный запрос отбирает только те термины которые связаны с какой либо нодой, так как применен INNER JOIN (если убрать INNER JOIN {node} n ON n.nid=tn.nid , то будут отбираться все термины)

Аватар пользователя T-34 T-34 10 января 2009 в 15:39

А как ограничить количество выводимых терминов (чтобы например выводилось 50 самых популярных)?

Аватар пользователя olk olk 10 января 2009 в 15:56

Данный сниппет будет выводить 20 (см. переменную $max_tags) наиболее популярных и «свежих» тэгов
<?php
$max_fontsize = 18; // Размер шрифта для тэга с максимальным весом
$min_fontsize = 9; // Размер шрифта для тэга с минимальным весом
$metrics = 'pt'; // в чем измеряется размер px,pt,em, (с установкой в процентном отношении Flash облоко глючит )
$voc = array(3); // массив (vid) словарей
$max_tags = 20; // максимальное количество показываемых тэгов
$vocs = implode(',',$voc);
$class_voc = implode('-',$voc);
$result = db_query(db_rewrite_sql("SELECT max(cnt) AS maxcnt,min(cnt) AS mincnt
FROM {term_data} td INNER JOIN
(SELECT tn.tid,COUNT(tn.nid) as cnt FROM {term_node} tn
INNER JOIN {node} n ON n.nid=tn.nid GROUP BY tn.tid) n
ON n.tid=td.tid AND td.vid IN (".$vocs.")"));
$term = db_fetch_object($result);
$min_weight = $term->mincnt;
$max_weight = $term->maxcnt;
// вычислим коэффициент для размера шрифт
if ($min_weight == $max_weight ) {
$font_metric_koof = 0;
}
else {
$font_metric_koof = ($max_fontsize - $min_fontsize) / ($max_weight - $min_weight);
}
$result = db_query_range(db_rewrite_sql("SELECT td.tid,td.name,n.cnt
FROM {term_data} td INNER JOIN
(SELECT tn.tid,COUNT(tn.nid) as cnt,MAX(n.created) as created FROM {term_node} tn
INNER JOIN {node} n ON n.nid=tn.nid GROUP BY tn.tid) n
ON n.tid=td.tid AND td.vid IN (".$vocs.") ORDER BY n.cnt DESC,n.created DESC"),0,$max_tags);
$tags = '';
while($term = db_fetch_object($result)) {
$size = $min_fontsize + ($term->cnt - $min_weight) * $font_metric_koof;
$style = 'font-size: '.$size.$metrics.';';
$tags .= l($term->name,'taxonomy/term/'.$term->tid,
array('attributes' => array('style' => $style,'class' => 'tags-voc-'.$class_voc))).' ';
}
if (!empty($tags)) {
$output = ''.$tags.'';
echo $output;
}
?>

Аватар пользователя Valeratal Valeratal 3 марта 2009 в 14:34

а чем отличается от этого снипета (я использую у себя, нашел где то тут)

<?php
    $vocs = array(1, 2, 3); //номера словарей
    $tags = tagadelic_get_weighted_tags($vocs, 6, 50);
    $tags = tagadelic_sort_tags($tags);
    $output = theme('tagadelic_weighted',$tags);
    print $output;
?>
Аватар пользователя T-34 T-34 4 марта 2009 в 2:38

"Valeratal" wrote:
а чем отличается от этого снипета

Как я понял, этот сниппет использует функции модуля tagadelic, а olk предложил сниппет БЕЗ использования модуля Smile

Аватар пользователя Dana Dana 18 марта 2009 в 11:36

Вопрос. А как надо изменить сниппет чтобы:
1. Выводились все термины словаря?
2. Термины словаря к которым не прикреплены ноды были другого цвета?

Зарание спасибо за помощь.

Аватар пользователя Dan Dan 19 марта 2009 в 1:32

"Valeratal" wrote:
я тож так подумал. а чем плох тагаделик?

Да, чем плох, если учитывать, что у него есть API и он кэширует данные?

"beerman" wrote:
спасибо. поставил вместо тормознутого тагаделика. работает.

В чём выражается тормознутость? Может из-за кэша (см. tagadelic_get_weighted_tags)?

Аватар пользователя zdoba zdoba 11 января 2010 в 18:54

"olk" wrote:
Данный сниппет будет выводить 20 (см. переменную $max_tags) наиболее популярных и «свежих» тэгов

Действительно выводит.
Однако, если указать сортировку по имени тэга (ORDER BY td.name), тогда сортировка по алфавиту обрезает популярные тэги. У кого-нибудь есть готовое решение? Т.е. чтобы сортировка производилась после того, как сформирован массив популярных тегов, ограниченный переменной $max_tags.

Аватар пользователя onexdrk onexdrk 5 марта 2011 в 18:04

Спустя год решение появилось Smile
Собственно доработал данный сниппет.
--
Исправления и доработки:

  1. Добавлена возможность вывода облака для разных типов материалов.
  2. Добавлена возможность случайной сортировки.
  3. Исправлен баг с обрезанием популярных терминов при различных вариантах сортировки.
  4. Исправлен баг с неверным назначением максимального и минимального размера шрифтов при выводимом количестве меньшем чем общее количество терминов.
  5. Доработаны запросы (запросов стало на 1 меньше).

<?php
$max_fontsize 
18;  // Размер шрифта для тэга с максимальным весом
$min_fontsize 8;   // Размер шрифта для тэга с минимальным весом
$metrics 'pt';     // в чем измеряется размер px,pt,em, (с установкой в процентном отношении Flash  облоко глючит )
$voc = array(8);     // массив (vid) словарей
$nodetype = array('vacancy');    //массив типов материала
$max_tags 10;      // максимальное количество показываемых тэгов
$order=3;    // сортировка терминов
// 0 - сортировка по ид термина
// 1 - сортировка по весу по убыванию (с наибольшим весом выше)
// 2 - сортировка по весу по возрастанию (с наибольшим весом ниже)
// 3 - сортировка в случайном порядке
// другое значение - сортировка по имени термина

$vocs implode(',',$voc);
$class_voc implode('-',$voc);

foreach(

$nodetype as &$value){
$value="'".$value."'";
}
$nodetypes implode(',',$nodetype);

$result db_query("SELECT td.tid,td.name,n.cnt
FROM {term_data} td  INNER JOIN
(SELECT tn.tid,COUNT(tn.nid) as cnt,MAX(n.created) as created  FROM {term_node} tn
INNER JOIN {node} n ON n.nid=tn.nid AND n.type in ("
.$nodetypes.")  GROUP BY tn.tid) n
ON n.tid=td.tid AND td.vid IN ("
.$vocs.") ORDER BY n.cnt DESC LIMIT 0, %d",$max_tags);

$mincnt=-1;
while(
$term db_fetch_array($result)) {
//Определение максимального и минимального коэффициентов 
$term['cnt']>$maxcnt?$maxcnt=$term['cnt']:FALSE;
$mincnt==-1?$mincnt=$maxcnt:FALSE;
$term['cnt']<$mincnt?$mincnt=$term['cnt']:FALSE;
//Для разных сортировок
$i++;
$termscnt[$term['cnt'].'-'.$i]=$term;
$termstid[$term['tid']]=$term;
$termsname[$term['name']]=$term;
}

// вычислим коэффициент для размера шрифт
if ($mincnt == $maxcnt) {
    
$font_metric_koof 0;
}
else {
    
$font_metric_koof = ($max_fontsize $min_fontsize) / ($maxcnt $mincnt);
}

switch(

$order){
 case 
0
       
ksort($termstid);
       
$terms=$termstid;
       break;
 case 
1
       
krsort($termscnt);
       
$terms=$termscnt;  
       break;
 case 
2
       
ksort($termscnt);
       
$terms=$termscnt;
       break;
 case 
3:
       
shuffle($termscnt);
       
$terms=$termscnt;
       break;
 default: 
       
ksort($termsname);
       
$terms=$termsname;
}

$tags '';

foreach(

$terms as $term) {
 
$size  $min_fontsize + ($term['cnt'] - $mincnt) * $font_metric_koof;
 
$style 'font-size: '.$size.$metrics.';';
 
$tags .= l($term['name'],'taxonomy/term/'.$term['tid'],
  array(
'attributes' => array('style' => $style,'class' => 'tags-voc-'.$class_voc))).' ';
}
if (!empty(
$tags)) {
$output '<tags class="voc-'.$class_voc.'">'.$tags.'</tags>';
echo 
$output;
}
?>

Удачного использования.

Аватар пользователя Dan Dan 5 марта 2011 в 15:56
  1. По-хорошему, надо написать мини-модуль, дописав hook_block и вынести настройки в настройки блока
  2. Вместо использования LIMIT, надо юзать db_query_range
  3. Подумать про db_rewrite_sql - если будут выводить термины, доступ к которым ограничен.
  4. Кэширования для подобных модулей прям таки обязательно.
Аватар пользователя onexdrk onexdrk 5 марта 2011 в 18:54

"Dan" wrote:

  1. По-хорошему, надо написать мини-модуль, дописав hook_block и вынести настройки в настройки блока
  2. Вместо использования LIMIT, надо юзать db_query_range
  3. Подумать про db_rewrite_sql - если будут выводить термины, доступ к которым ограничен.
  4. Кэширования для подобных модулей прям таки обязательно.


1. Незнаю, мне кажется нет смысла выделять в модуль т.к. потеряется основная идея сниппета. Да и когда делал, основная цель была другой - позволить выводить термины для разных типом ватериалов:
на сайте есть 2 логических/тематических разделения, на которых вывожу 2 разных блока (1-популярные должности в резюме. 2-популярные должности в вакансиях).
2,3 - поправлю, выложу. Не подскажите, лучше запостить в эту тему или выделить в отдельную? (1й раз публикую наработки)
4. - не подскажите где почитать про риализацию?
-
Спасибо.

Аватар пользователя Dan Dan 6 марта 2011 в 16:22

1. А какова идея сниппета? Я всегда считал, "зачем делать сниппеты, если можно сделать модуль". Модуль можно включить/выключить, он может хранить настройки, его легко передать другим, он чудно лежит в системе контроля версий, для него не надо включать PHP-фильтр (а на рабочем сайте этот фильтр должен быть отключен в обязательном порядке).
4. [ru-api=cache_set] и [ru-api=cache_get] - посмотрите использование в ядре, там всё просто. Таблицу для хранения советую использовать "cache_filter".

Аватар пользователя Valeratal Valeratal 8 марта 2011 в 11:56

чтобы не быть голословным

есть вывод модулем тагаделик, есть такой же вывод - сниппетом

вывод сниппетом я легко оберну в див клас (какой надо)

вывод модулем - придется заморочится (привязываться к примеру к блоку или еще к чему ни будь)

Другой пример. Отображение 10 последних материалов определенного вида (пусть будет page)

сниппет легко, можно изменить ul на dd , или на p, div

Этот же вывод с помощью вьюс - да вот не получится, нет такой гибкости

(зато вьюсом можно вывести сеткой) Smile

Аватар пользователя Ильич Рамирес Санчес Ильич Рамирес Санчес 8 марта 2011 в 11:57

"Valeratal" wrote:
вывод сниппетом я легко оберну в див клас (какой надо)

вывод модулем - придется заморочится (привязываться к примеру к блоку или еще к чему ни будь


сделать ОДИН файлик шаблона блока и сделать это там.

а да. с 23 февраля с 8 марта, пацаны!

Аватар пользователя Dan Dan 8 марта 2011 в 13:25

"Valeratal" wrote:

Во-первых, различай _свой_ модуль от чужого - свой ты так же легко можешь поменять как и сниппет. А если делать правильно, то и модуль менять не нужно - делай в шаблоне модуля.

Во-вторых, для правильно написанных модулей (тот же views), изменение шаблонов вывода - пятиминутное дело, просто копи-паст без включения мозгов.

Аватар пользователя direqtor direqtor 8 марта 2011 в 17:54

"Valeratal" wrote:
вывод сниппетом я легко оберну в див клас (какой надо)

вывод модулем - придется заморочится (привязываться к примеру к блоку или еще к чему ни будь)

А разве делая свои модули, вы не используете темизацию?

Аватар пользователя Valeratal Valeratal 9 марта 2011 в 9:45

я не про свои модули

и сравните что проще, переопределять блок
или добавить один div

"Dan" wrote:
именение шаблонов вывода - пятиминутное дело, просто копи-паст без включения мозгов.

Да, и давно, переделка вывода вьюс стала простым делом?

можно ссылку?

Аватар пользователя Valeratal Valeratal 9 марта 2011 в 12:21

это пусть Толя смотрит касты
я только текст воспринимаю

и еще, вот вывод, сделаете мне это вьюсом? (также просто) . Вопрос же не в том, что "нельзя сделать". Вопрос в том, что проще.
http://www.hr-portal.ru/page/novosti-5

Аватар пользователя Dan Dan 9 марта 2011 в 19:59

Не замучаюсь. Если надо извратиться с выводом, можно вызвать views ручками и построить вывод самому. Такое нужно очень редко.

Аватар пользователя Valeratal Valeratal 10 марта 2011 в 17:45

а разве вопрос сделать или нет, часто или редко
я утверждал что быстрее. И не более того.

Я более чем уверен, что Dan при необходимости напишет свой модуль свой. И не только он.

Аватар пользователя lopata24 lopata24 29 августа 2011 в 15:44

друзья, подскажите, как быть с мультиязычностью?

чтобы на русском выводились теги в облаке на русском, а на английском крутилось английское облачко?

заранее спасибо!

Аватар пользователя olk olk 31 мая 2012 в 9:38

"Smoliannikoff" wrote:

Подскажите как отключить линки на теги в облаке ?


строку

<?php
$tags 
.= l($term->name,'taxonomy/term/'.$term->tid,
   array(
'attributes' => array('style' => $style,'class' => 'tags-voc-'.$voc))).' ';?>

меняешь на

<?php
$tags 
.= '<span style="' $style ">' . $term->name . '</span> ';?>
Аватар пользователя Smoliannikoff Smoliannikoff 12 июня 2012 в 12:27

"olk" wrote:

А возможно вывести в облако выборочные иерархии?

Как отдельно от других терминов вывести термины из иерархии --Термин1 ?
------ из иерархии --Термин1.1 ?

Словарь
-Термин1
--Термин1.1
---термин
---термин
---термин
--Термин1.2
-Термин2
--Термин2.1
--Термин2.2
-Термин3
--Термин3.1
--Термин3.2

Аватар пользователя Faceless Faceless 12 июня 2012 в 16:08

"Smoliannikoff" wrote:
А возможно вывести в облако выборочные иерархии?
Как отдельно от других терминов вывести термины из иерархии --Термин1 ?
------ из иерархии --Термин1.1 ?

Тогда нужно в коде явно указывать из каких иерархий нужно брать термины и будет вам счастье.