Discuz提供了强大的聚合功能,网站里发布的文章日志记录和帖子里的内容都可以通过DIY模块来聚合起来集中显示。聚合起来的内容存放在单独的缓存数表里便于快速显示。但是聚合时提取的内容只是原来内容的一部分,有时会出现想要在DIY模块里显示的内容没在聚合内容里的情形。我们能不能把它们加到聚合内容里去呢?比如有些日志里有很多照片或图片,但聚合时则只能选取一张。有没有可能把日志里所有的图片都显示在DIY模块里呢?这就是本文要讨论的主题。
日志模块的组图显示
1. 首先要修改模块文件source/class/block/space/space_blog.php
1.1 把图片列加到要显示的成员名单里去:在函数fields里下面这行
'click8' => array('name' => lang('blockclass', 'blockclass_blog_field_click8'), 'formtype' => 'text', 'datatype' => 'int'),后添加
'piclist' => array('name' => lang('blockclass', 'blockclass_blog_field_piclist'), 'formtype' => 'text', 'datatype' => 'string'),
1.2 在从日志里提取聚合内容时获取日志里所有的图片:在函数getdata里的下面这行
'click8'=>$data['click8'],后添加
'piclist'=>implode('|', $this->getpiclist($data['message'])),
这里使用了接下来要引入的函数getpiclist来得到日志里的图片地址列,然后用分隔符将它们合并成一个字符串便于存放在缓存数表里。
1.3 添加上面用到的函数getpiclist的定义:
function getpiclist($message) {
$piclist = array();
if (!empty($message)) {
require_once libfile('function/blog');
$message = blog_bbcode($message);
/* include the following two lines only if the site uses the one-key-post feature explained in
http://www.bian-wang.com/discuz/home.php?mod=space&uid=10005&do=blog&id=1486
*/
require_once libfile('function/url2html');
$message = url2html($message, 0);
preg_match_all("/\s*\
\s*/is", $message, $matches);
if(!empty($matches[1])) {
foreach ($matches[1] as $value) {
$piclist[] = $value;
}
}
}
return $piclist;
}
上面函数里有两行只在使用一键贴(
链接)的网站里才需要使用。
2. 组图模板
聚合数据里有了图片列信息后,还需要有个模块模板将它显示出来。显示的办法有多种,比如可以将所有图片排成一行滚动显示,又如可以堆起来幻灯显示。下面讨论的办法是将图片从左往右再从上往下一一展示。在管理中心的门户->模块模板里添加一个关于日志模块的模板:
[loop]
< a href="home.php?mod=space&uid={uid}"{target}>{username}:< a href="{url}"{target}>{title}
< a href="{url}"{target}>
![]()
[/loop]
模板定义里用到的函数setGallery将在下面定义,它接受三个参数:
- classname:容纳显示的组图容器元素的类名
- rows:图片最多显示行数,超过部分不显示。如果值为零代表对行数没限制
- picheight:每行的高度
3. 组图显示的客户端支持
图片列是在一个字符串里,要想显示在网页上需要有javascript代码的支持。在文件static/js/common.js里加入下面的内容:
function _randomInteger() {
return Math.random().toString(36).substring(2);
}
// https://www.htmlgoodies.com/beyond/javascript/article.php/3724571/Using-Multiple-JavaScript-Onload-Functions.htm
function _addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function () {
if (oldonload) {
oldonload();
}
func();
}
}
}
// classname: class name of the container element to display images
// rows: maximum rows to display, 0 means no limit
// picheight: image display height, 0 means use the original image height
function setGallery(classname, rows, picheight) {
var gallery = $C(classname);
for (var i = 0; i < gallery.length; i++) {
_setGallery(gallery[i], rows, picheight);
}
}
function _setGallery(el, rows, picheight) {
if (el.id) return;
el.id = 'g' + _randomInteger();
el.style.position = 'relative';
el.style.overflow = 'hidden';
el.style.height = '10px';
var mainpiclist = [];
var items = $C('item-template', el);
for (var i = 0; i < items.length; i++) {
var item = items[i];
var piclist = item.getAttribute('data').split('|');
item.style.display = 'none';
item.removeAttribute('data');
for (var j = 0; j < piclist.length; j++) {
var pic = piclist[j];
if (!pic) continue;
if (mainpiclist.indexOf(pic.toUpperCase()) >= 0) continue;
mainpiclist.push(pic.toUpperCase());
var nitem = item.cloneNode(true);
nitem.style.display = '';
nitem.className = 'item';
nitem.style.position = 'absolute';
nitem.style.visibility = 'hidden';
el.appendChild(nitem);
var nimg = nitem.getElementsByTagName('img')[0];
nimg.src = pic;
}
}
_addLoadEvent(function () {
var tw = el.offsetWidth;
var th = 0;
var rw = 0;
var gutter = 10;
var row = 0;
var list = [];
var mth = 0;
var items = $C('item', el);
for (i = 0; i < items.length; i++) {
var item = items[i];
item.style.visibility = 'visible';
var img = item.getElementsByTagName('img')[0];
var ih = img.offsetHeight;
var iw = img.offsetWidth;
if (!picheight) picheight = ih;
if (ih < picheight) {
img.style.height = '0px';
img.style.width = '0px';
}
else {
if (rw == 0) {
th += picheight + gutter;
if (!rows || row < rows) mth = th;
}
list.push(item);
img.style.height = picheight + 'px';
iw *= picheight / ih;
img.style.width = iw + 'px';
item.style.left = rw + 'px';
item.style.top = (th - picheight) + 'px';
rw += iw + gutter;
if (rw >= tw) {
var c = list.length;
ratio = (tw - (c - 1) * gutter) / (rw - (c - 1) * gutter);
for (j = 0; j < list.length; j++) {
var item = list[j];
var img = item.getElementsByTagName('img')[0];
img.style.height = (img.offsetHeight * ratio) + 'px';
img.style.width = (img.offsetWidth * ratio) + 'px';
item.style.left = ((parseInt(item.style.left) - j * gutter) * ratio + j * gutter) + 'px';
};
th -= (1 - ratio) * picheight;
if (!rows || row < rows) mth = th;
row++;
rw = 0;
list = [];
}
}
}
el.style.height = (mth + gutter) + 'px';
});
}
这些代码里含有两个考量:
- 日志里常会有些小图片如表情图片,它们应该排除在组图显示里,所以在代码里我们去掉了图片高度小于规定的显示高度的图片,这个显示高度可以在DIY模块设置里设置,如果在那里不设置的话默认值为200px
- 日志里的图片有大有小尺寸不一。怎样能让图片排列整齐,既要完整显示每张图片又不留空白呢?我的做法是在一行的内容凑足之后,将它们按比例缩小到总宽度正好是DIY模块区域的宽度。这样除最后一行外,其它各行都不会有空白之处了
4. 最后还要定义上面用到的汉字字符串
在文件source/language/lang_blockclass.php里加入
'blockclass_blog_field_piclist' => '日志内所有图片',
文章模块的组图显示
首先我们要修改文章模块文件source/class/block/portal/portal_article.php,做法和1是类似的,略有不同的地方是文章可以分页,我们要提取所有分页里的图片。
在函数fields里下面这行
'commentnum' => array('name' => lang('blockclass', 'blockclass_article_field_commentnum'), 'formtype' => 'text', 'datatype' => 'int'),
后添加
'piclist' => array('name' => lang('blockclass', 'blockclass_article_field_piclist'), 'formtype' => 'text', 'datatype' => 'string'),
在函数getdata里的下面这行
'commentnum' => intval($data['commentnum']),
后添加
'piclist'=>implode('|', $this->getpiclist($data['content'], $data['aid'], $data['contents'])),
添加上面用到的函数定义:
function getpiclist($content, $aid, $pages) {
if ($pages>1) $content.= $this->getadditionalpages($aid);
$piclist = array();
if (!empty($content)) {
require_once libfile('function/blog');
$content = blog_bbcode($content);
/* include the following two lines only if the site uses the one-key-post feature explained in
http://www.bian-wang.com/discuz/home.php?mod=space&uid=10005&do=blog&id=1486
*/
require_once libfile('function/url2html');
$content = url2html($content, 0);
preg_match_all("/\s*\
\s*/is", $content, $matches);
if(!empty($matches[1])) {
foreach ($matches[1] as $value) {
$piclist[] = $value;
}
}
}
return $piclist;
}
function getadditionalpages($aid) {
$content = '';
$contents = C::t('portal_article_content')->fetch_all($aid);
foreach($contents as $value) {
if($value['pageorder']>1) $content .= ' '.$value['content'];
}
return $content;
}
然后添加一个有关文章模块的模板,内容和2几乎相同但去掉了作者名:
[loop]
< a href="{url}"{target}>{title}
< a href="{url}"{target}>
[/loop]
3里加的javascript同样适用于文章,不需另作处理。和4类似要定义个字符串在文件source/language/lang_blockclass.php里:
'blockclass_article_field_piclist' => '文章内所有图片',
记录模块的组图显示
首先我们要修改记录模块文件source/class/block/space/space_doing.php,做法和1是类似的,略有不同的地方是我们不仅提取记录里的所有图片,还提取其所有回复里的图片。
在函数fields里下面这行
'replynum' => array('name' => lang('blockclass', 'blockclass_doing_field_replynum'), 'formtype' => 'text', 'datatype' => 'int'),
后添加
'piclist' => array('name' => lang('blockclass', 'blockclass_doing_field_piclist'), 'formtype' => 'text', 'datatype' => 'string'),
在函数getdata里的下面这行
'replynum'=>$data['replynum'],
后添加
'piclist'=>implode('|', $this->getpiclist($data['doid'], $data['message'])),
添加上面用到的函数定义:
function getpiclist($doid, $message) {
$piclist = array();
$query = C::t('home_docomment')->fetch_all_by_doid($doid);
foreach($query as $data) {
$message .= ' ' . $data['message'];
}
if (!empty($message)) {
$message = strip_tags($message);
require_once libfile('function/url2html');
/* include the following two lines only if the site uses the one-key-post feature explained in
http://www.bian-wang.com/discuz/home.php?mod=space&uid=10005&do=blog&id=1486
*/
$message = url2html($message, 0);
preg_match_all("/\s*\
\s*/is", $message, $matches);
if(!empty($matches[1])) {
foreach ($matches[1] as $value) {
$piclist[] = $value;
}
}
}
return $piclist;
}
然后添加一个有关记录模块的模板,内容和2类似:
[loop]
< a href="{url}"{target}>
[/loop]
3里加的javascript同样适用于记录,不需另作处理。和4类似要定义个字符串在文件source/language/lang_blockclass.php里:
'blockclass_doing_field_piclist' => '记录下所有图片',
注:在本文中的代码中,在<符号和a字符相连的地方在两者之间加了一个不应该有的空格,以避免Discuz在保存日志时自动改变日志内容。