Typecho 无插件实现即时搜索

Typecho教程 typecho 搜索 javascript 即时搜索 2019-09-17

functions.php最后面添加以下,通过每次访问判断文件间隔时间来达到更新缓存的目的。上方js里的search_a路径需要填写完整路径+/caches/cache.json

/**
 * 静态缓存类
 */
class cacheFile
{
    private $_dir;
    const EXT = '.json';
    public function __construct()
    {
        $this->_dir = dirname(__FILE__).'/caches/';
    }
    public function cacheData($key, $value = '', $path = '')
    {
        $filePath = $this->_dir.$path.$key.self::EXT;
        if ($value !== '') {
            // 如果设置为 null,则删除缓存文件
            if (is_null($value)) {
                return unlink($filePath);
            }
            $dir = dirname($filePath);
            if (!is_dir($dir)) {
                mkdir($dir, 0777);
            }
            // 该函数将返回写入到文件内数据的字节数,失败时返回FALSE 
            return file_put_contents($filePath, $value);
        }
        // 如果已经存在该文件,直接返回文件里面的内容
        if (!is_file($filePath)) {
            return false;
        } else {
            echo $filePath;
            // The function returns the read data 或者在失败时返回 FALSE. 
            return json_decode(file_get_contents($filePath), true);
        }
    }
}
if(!file_exists($flag)) {
touch($flag);
$TheFile = dirname(__FILE__).'/caches/cache.json';
$cacheFile = new cacheFile();
$vowels = array("[", "{","]","}","<",">","\r\n", "\r", "\n","-","'",'"','`'," ",":",";",'\\',"    ");
Typecho_Widget::widget('Widget_Contents_Post_Recent','pageSize=10000')->to($archives);
    while($archives->next()):
    $output .= '{"this":"post","link":"'.$archives->permalink.'","title":"'.$archives->title.'","comments":"'.$archives->commentsNum0.'","text":"'.str_replace($vowels, "",$archives->text).'"},';
    endwhile;
Typecho_Widget::widget('Widget_Contents_Page_List')->to($pages);
    while($pages->next()):
    $output .= '{"this":"page","link":"'.$pages->permalink.'","title":"'.$pages->title.'","comments":"'.$pages->commentsNum0.'","text":"'.str_replace($vowels, "",$pages->text).'"},';
    endwhile;
Typecho_Widget::widget('Widget_Metas_Tag_Cloud','ignoreZeroCount=1&limit=10000')->to($tags); 
    while ($tags->next()):
    $output .= '{"this":"tag","link":"'.$tags->permalink.'","title":"'.$tags->name.'","comments":"0","text":"'.str_replace($vowels, "",$tags->description).'"},';
    endwhile;
Typecho_Widget::widget('Widget_Metas_Category_List')->to($category); 
    while ($category->next()):
    $output .= '{"this":"category","link":"'.$category->permalink.'","title":"'.$category->name.'","comments":"0","text":"'.str_replace($vowels, "",$category->description).'"},';
    endwhile;
    $output = substr($output,0,strlen($output)-1);
$data = '['.$output.']';
if (file_exists($TheFile)) {
    if ( time() - filemtime( $TheFile) > 1800){
    $cacheFile->cacheData('cache', $data);
    }; //5分钟300秒,时间可以自己调整
} else {
    $cacheFile->cacheData('cache', $data);
};
}

HTML结构:

<div class="ins-search" id="search">
    <div class="ins-search-mask">
    </div>
    <div class="ins-search-container">
        <div class="ins-input-wrapper">
            <form id="search-form" method="post" action="./" role="search">
                <input id="search-input" type="text" name="s" class="ins-search-input" placeholder="想要查找什么...">
            </form>
            <span id="close" class="ins-close ins-selectable">×</span>
        </div>
        <div class="ins-section-wrapper">
            <a id="Ty" href="#"></a>
            <div class="ins-section-container" id="PostlistBox">
                <section class="ins-section"><header class="ins-section-header">文章</header>
                <div class="ins-selectable ins-search-item" data-url="/">
                    <header>测试</header>
                    <p class="ins-search-preview">
及时搜索结果
                    </p>
                </div>
                </section><section class="ins-section"><header class="ins-section-header">页面</header>
                <div class="ins-selectable ins-search-item" data-url="/">
                    <header>测试</header>
                </div>
                </section><section class="ins-section"><header class="ins-section-header">分类</header>
                <div class="ins-selectable ins-search-item" data-url="/">
                    <header>测试<span class="ins-slug">测试</span></header>
                </div>
                </section><section class="ins-section"><header class="ins-section-header">标签</header>
                <div class="ins-selectable ins-search-item" data-url="/">
                    <header>测试<span class="ins-slug">测试</span></header>
                </div>
                </section>
            </div>
        </div>
    </div>
</div>

CSS:

.ins-search{display:none;z-index:999}
.ins-search a{-webkit-transition:none;transition:none}
.ins-search header{position:unset;width:auto}
.ins-selectable{cursor:pointer}
.ins-search-container,.ins-search-mask{position:fixed}
.ins-search-mask{top:0;left:0;width:100%;height:100%;z-index:100;background:rgba(0,0,0,.85)}
.ins-input-wrapper{position:relative}
.ins-search-input{width:100%;border:none;outline:0;font-size:16px;-webkit-box-shadow:none;box-shadow:none;font-weight:200;border-radius:0;background:#fff;line-height:20px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:12px 40px 12px 20px;border-bottom:1px solid #e2e2e2}
.ins-close{top:50%;right:10px;width:20px;height:20px;font-size:16px;margin-top:-15px;position:absolute;text-align:center;display:inline-block;font:22px/30px Arial,Helvetica Neue,Helvetica,sans-serif;color:#888;font-weight:300}
.ins-close:hover{color:#000}
.ins-search-container{left:50%;top:100px;z-index:101;bottom:100px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:540px;margin-left:-270px;border:1px solid #ccc;border-radius:.28571429rem;background:#fff;-webkit-box-shadow:0 1px 3px 0 rgba(0,0,0,.08);box-shadow:0 1px 3px 0 rgba(0,0,0,.08)}
@media screen and (max-width:559px),screen and (max-height:479px){.ins-search-container{top:0;left:0;margin:0;width:100%;height:100%;background:#f7f7f7}
}
.ins-section-wrapper{left:0;right:0;top:45px;bottom:0;overflow-y:auto;position:absolute}
.ins-section-container{position:relative;background:#f7f7f7}
.ins-section{font-size:14px;line-height:16px}
.ins-section .ins-search-item,.ins-section .ins-section-header{padding:8px 15px}
.ins-section .ins-section-header{color:#9a9a9a;border-bottom:1px solid #e2e2e2}
.ins-section .ins-slug{margin-left:5px;color:#9a9a9a}
.ins-section .ins-slug:before{content:'('}
.ins-section .ins-slug:after{content:')'}
.ins-section .ins-search-item .ins-search-preview,.ins-section .ins-search-item header{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;color:#616161}
.ins-section .ins-search-item header i{margin-right:8px}
.ins-section .ins-search-item .ins-search-preview{height:15px;font-size:12px;color:#9a9a9a;margin:5px 0 0 20px}
.ins-section .ins-search-item.active,.ins-section .ins-search-item:hover{color:#fff;background:#006bde}
.ins-section .ins-search-item.active .ins-search-preview,.ins-section .ins-search-item.active .ins-slug,.ins-section .ins-search-item:hover .ins-search-preview,.ins-section .ins-search-item:hover .ins-slug,.ins-section .ins-search-item:hover header{color:#fff}

JS:

var QueryStorage = [];
search_a("这里填写生成的json链接");
var otxt = document.getElementById("search-input"),
    list = document.getElementById("PostlistBox"),
    Record = list.innerHTML;
document.all ? otxt.onpropertychange = function() {
    query(QueryStorage, otxt.value, Record)
} : otxt.oninput = function() {
    query(QueryStorage, otxt.value, Record)
};

function search_a(val) {
    var _xhr = new XMLHttpRequest();
    _xhr.open("GET", val, true);
    _xhr.setRequestHeader("Content-Type", "application/json");
    _xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
    _xhr.send(val);
    _xhr.onreadystatechange = function() {
        if (_xhr.readyState == 4 && _xhr.status == 200) {
            json = _xhr.responseText;
            if (json != "") {
                QueryStorage = JSON.parse(json)
            }
        }
    }
}
if (!Object.values) Object.values = function(obj) {
    if (obj !== Object(obj)) throw new TypeError('Object.values called on a non-object');
    var val = [],
        key;
    for (key in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, key)) {
            val.push(obj[key])
        }
    }
    return val
}
function a(a) {
    document.getElementById("Ty").href = a.getAttribute("href"), document.getElementById("Ty").click()
}
function query(a, b, c) {
    var n, o, p, q, d = "",
        e = "",
        f = "",
        g = "",
        h = "",
        i = '<div class="ins-selectable ins-search-item" onclick="a(this)" href="',
        j = '<section class="ins-section"><header class="ins-section-header">',
        k = "</header>",
        l = "</section>",
        m = Cx(a, b);
    for (n = 0; n < Object.keys(m).length; n++) switch (o = m[n].this) {
    case "post":
        e = e + i + m[n].link + '"><header>' + m[n].title + '</header><p class="ins-search-preview">' + m[n].comments + m[n].text + "</p></div>";
        break;
    case "tag":
        f = f + i + m[n].link + '"><header>' + m[n].title + '<span class="ins-slug">' + m[n].text + "</span></header></div>";
        break;
    case "category":
        g = g + i + m[n].link + '"><header>' + m[n].title + '<span class="ins-slug">' + m[n].text + "</span></header></div>";
        break;
    case "page":
        h = h + i + m[n].link + '"><header>' + m[n].title + '</header><p class="ins-search-preview">' + m[n].comments + m[n].text + "</p></div>"
    }
    e && (d = d + j + "文章" + k + e + l), h && (d = d + j + "页面" + k + h + l), g && (d = d + j + "分类" + k + g + l), f && (d = d + j + "标签" + k + f + l), p = document.getElementById("PostlistBox"), q = document.getElementById("search-input"), p.innerHTML = "" == q.value ? c : d
}
function Cx(arr, q) {
    i = arr.filter(v = > Object.values(v).some(v = > new RegExp(q + '').test(v)));
    return I
}

0条评论

智能推荐