发布于JavaScript分类中的文章

Aug 09

家中或者公司使用了 Tomato 或者 DD-WRT 固件路由器的同学可能想分享他们的“私密” Hosts 文件,但是又不方便拷贝到每台机器,那么把这个 Hosts 文件内容放到路由器上是最方便的,不过 DNSMasq 的 Hosts 文件与 Windows 的 Hosts 文件格式不同,需要做一个转换,于是有了下面这个 HTML 文件,其实就是一个简单的 Javascript 转换。复制所有内容,存为任意命名的 HTML 文件,用浏览器打开,然后点击转换按钮,把转换后的数据贴到路由器 DNS 设置界面就行了。


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Hosts2DNSMasq</title>
<script type="text/javascript">
//类似 PHP 中的 trim
    function trim(str) {
        var str = str.replace(/^\s\s*/, ''),
            ws = /\s/,
            i = str.length;
        while (ws.test(str.charAt(--i)));
        return str.slice(0, i + 1);
    }
//转换 Hosts 文件格式到 DNSMasq 的格式
    function htol(el) {
        var i;
        var localz = new Array();
        var hosts = document.getElementById(el).value;
        var localzs='';
        hostdomain = hosts.split("\n");
        for (i=0;i<hostdomain.length;i++) {
            if (trim(hostdomain[i]) != '') {
                localz[i] = hostdomain[i].split("\t");
                if (localz[i][1] != undefined && localz[i][0].indexOf("#") == -1) {
                    localzs += 'address=/'+localz[i][1]+'/'+localz[i][0]+'\n';
                } else {
                    localzs += hostdomain[i]+'\n';
                }
            }
        }
        document.getElementById(el).value = localzs;
    }
</script>
</head>
<body>
    <div style="width:1024px; margin:0 auto;">
            <h2>HOSTS</h2>
            <div style="margin: 5px auto; display: block;">
            <button type="button" id="hosttolocal" onclick="htol('hostsMap');">ConventerToDNSMASQ</button>
            </div>
            <textarea id="hostsMap" onclick="this.focus();this.select()" style="width:98%;height:550px;margin:0;padding:3px;display:block;"></textarea>
    </div>
</body>
</html>

例如以下的 Hosts 数据:


203.208.45.200	base0.googlehosted.com
203.208.45.200	base1.googlehosted.com
203.208.45.200	base2.googlehosted.com
203.208.45.200	base3.googlehosted.com
203.208.45.200	base4.googlehosted.com
203.208.45.200	base5.googlehosted.com
203.208.45.200	bks0.books.google.com
203.208.45.200	bks1.books.google.com

会被转换成:


address=/base0.googlehosted.com/203.208.45.200
address=/base1.googlehosted.com/203.208.45.200
address=/base2.googlehosted.com/203.208.45.200
address=/base3.googlehosted.com/203.208.45.200
address=/base4.googlehosted.com/203.208.45.200
address=/base5.googlehosted.com/203.208.45.200
address=/bks0.books.google.com/203.208.45.200
address=/bks1.books.google.com/203.208.45.200

注意,只是做了简单的格式转换,没有利用 DNSMasq 的(泛域名)特性优化。 :shock:


Nov 24

vTip 这个基于 jQuery 的气泡提示只有 706 字节(压缩后),比本站以前用的 SweetTitle 小得多了(5k),功能却一点也不差,稍微修改了一下就很好用了。

vtip.js

vtip.css


Oct 23

这个脚本功能很简单,如果你有境外 PHP 主机空间,利用这个脚本可以查询到被 DNS 污染的一些站点的真实 IP 。缓存的结果可以直接拷贝到系统 Hosts 文件中使用,也可以转换为 Unbound 的 localzone 格式供 Unbound 调用。hosts.txt 中包含需要查询的站点主机名,一行一个,ipcache.txt 则为查询结果缓存文件,标准的 Windows 系统 Hosts 文件格式。

可以到本站: gethosts 页面体验效果。


<?php
/**
 * gethosts
 *
 * @link       https://www.quakemachinex.com/gethosts/
 * @copyright  Copyright (c) 2011 AvP
 * @license    MIT Style License
 * @version    1.0
 */

$hostsLock = true; //用户提交的查询数据是否写入 hosts.txt,默认:不写入

$isPost = false;

if (isset($_POST['hosts'])){
    $hosts_txt = $_POST['hosts'];
    $isPost = true;
	if (!$hostsLock) file_put_contents('hosts.txt',$hosts_txt);
} else {
	$hosts_txt = file_get_contents('hosts.txt');
}
$hosts_array = preg_split('/[\s,]+/', $hosts_txt, -1, PREG_SPLIT_NO_EMPTY);
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>gethosts</title>
<script src="ZeroClipboard.js" type="text/javascript"></script>
<script type="text/javascript">
//类似 PHP 中的 trim
    function trim(str) {
        var str = str.replace(/^\s\s*/, ''),
            ws = /\s/,
            i = str.length;
        while (ws.test(str.charAt(--i)));
        return str.slice(0, i + 1);
    }
//基于 ZeroClipboard 的跨浏览器复制到剪贴板
    function ctoc() {
        var txt = document.getElementById('hostsMap').value;

        if (window.clipboardData) {
            window.clipboardData.setData("text", txt);
            alert("Copied text to clipboard:\n" + txt);
        } else {
            var clip = new ZeroClipboard.Client();
            clip.glue('clickme');
            clip.setText(txt);
            clip.addEventListener('complete', function(client, text) {
                alert("Copied text to clipboard:\n" + text);
            });
            }
    }
//转换 Hosts 文件格式到 Unbound 的 localzone 格式
    function htol() {
        var i;
        var localz = new Array();
        var hosts = document.getElementById('hostsMap').value;
        var localzs='';
        hostdomain = hosts.split("\n");
        for (i=0;i<hostdomain.length;i++) {
            if (trim(hostdomain[i]) != '') {
                localz[i] = hostdomain[i].split("\t");
                localzs += 'local-data: "'+localz[i][1]+' A '+localz[i][0]+'"\n';
            }
        }
        document.getElementById('hostsMap').value = localzs;
    }
</script>
</head>
<body>
<?php
//判定字符串是否是 IP 地址
function IsIPAdress($value){

    if (preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $value)){
        return true;
    }
    return false;
}
//获取真实 IP,并且缓存,用户提交数据不缓存
function getRealIP(){
    global $hosts_array, $isPost;
    if($isPost) {
        foreach($hosts_array as $hostname){
            $ip = gethostbyname($hostname);
            if (IsIPAdress($ip)) {
                $i = $i + 1;
                echo "$ip\t$hostname";
                echo "\n";
                if ($i > 25) return;
            }
        }
    } else {
        $cache_days = 1; //缓存多少天
        $fz = filesize('ipcache.txt');
        $ipcache_create_time = filectime('ipcache.txt');
        $time_now = date("Y-m-d H:i:s");
        $ipcache_stay_days = (strtotime($time_now)-strtotime(date("Y-m-d H:i:s",$ipcache_create_time)))/86400;
        $ipcache_stay_days = floor($ipcache_stay_days);

        if ($fz && $fz != 0 && $ipcache_stay_days < $cache_days) {
            $ipcache = file_get_contents('ipcache.txt');
            echo $ipcache;
         } else {
            foreach($hosts_array as $hostname){
                $ip = gethostbyname($hostname);
                if (IsIPAdress($ip)) {
                    $ipcacheall .= "$ip\t$hostname\n";
                }
            }
            $local_ipcache = 'ipcache.txt';
            $local_ipcache_actual = fopen($local_ipcache, 'w+');
            fwrite($local_ipcache_actual, $ipcacheall);
            fclose($local_ipcache_actual);
            $ipcache = file_get_contents('ipcache.txt');
            echo $ipcache;
         }
     }
}
?>
    <div style="width:1024px; margin:0 auto;">
        <div style="float:left;margin:0 10px;">
            <h2>Blocked Hostnames</h2>
            <form method="post">
                <button type="submit" style="margin: 5px auto; display: block;">Get Hosts</button>
                <textarea name="hosts" style="width:400px;height:550px;margin:0;padding:3px;display:block;"><?php echo $hosts_txt;?></textarea>
            </form>
        </div>
        <div style="float:left;margin:0 10px;">
            <h2>hosts</h2>
            <div style="margin: 5px auto; display: block;">
            <button type="button" id="clickme" onclick="ctoc();">CopyToClipboard(Click Twice!)</button>
            <button type="button" id="hosttolocal" onclick="htol();">ConventerToLocalzone</button>
            </div>
            <textarea id="hostsMap" onclick="this.focus();this.select()"style="width:500px;height:550px;margin:0;padding:3px;display:block;"><?php getRealIP(); ?></textarea>
        </div>
    </div>
</body>
</html>

ZeroClipboard 可到官方下载。 :!:


Oct 02

Coda Slider 这个效果我最初是从 Mashable 看到的,当然那时候我并不知道这种效果叫 Coda Slider。通过查看源码和一番搜索我知道了这个玩意是用 Jquery + Coda Slider 插件做出来的,它的网站是 Niall Doherty's Coda Slider

于是我当然想把它用在我的站点。去 WordPress 官方插件站点扫了一下居然没找到(嗯,太多插件,也不知从何搜起),只好自己弄了。看下 Coda Slider 的范例文件就很清楚地知道,只要把 Slider 的内容放入一个特定 Class 的 Div 里面即可,从 Mashable 看来,Slider 的内容就是文章的第一张图片(如果有的话)和文章标题。这样就简单了,我们只需要把这些内容从 WordPress 数据库中提取出来放入那些 Div 容器即可。

当我正准备动手写代码的时候,突然想起在哪见过这类提取图片的应用,还是在我的链接列表里面,于是找了几个站点,在 “我爱水煮鱼”的 Blog 找到了 Advance Post Image Plugin ,噢,这下又省了很多事情。。。 :mrgreen:

好了,随便搭下积木这插件就弄成了,用法基本和 Advance Post Image Plugin 一样:

上传 wordpress-post-coda-slider 整个目录到 /wp-content/plugins/ 目录下 ;

在插件菜单下激活插件 ;

在模板文件中适当的位置插入 :


if(function_exists('get_post_image_list')) { get_post_image_list(); }

这个位置一般是你文章主体那个 Div 上面;

在 wp-content 目录下创建 thumb-cache 文件夹并将其设置为 777 ,哪个文件夹不重要(你可以修改源代码定目录),重要的是一定要可写!

然后函数 get_post_image_list() 的以下五个参数是可以定制的:

$image_number = 20 // 设置显示图片个数,默认为20 张
$thumb_width =80 // 设置所略图的宽度,默认为 50 像素,如果为 0,则会根据高度自动修改,但是宽度和高度至少填一个
$thumb_height = 45 // 设置所略图的高度,默认为 50 像素,如果为 0,则会根据宽度自动修改,但是宽度和高度至少填一个
$type = "random" // 设置列表的类型,"recent" 显示最近日志的图片, "random" 则显示随机日志的图片
$randompic = "random" // 设置显示图片方式,”random“为随机显示文章中的图片,”first“为显示文章中第一张图片,”last“显示文章中最后一张图片

好了,最后再次感谢”我爱水煮鱼“和 Jquery Coda Slider 的原作者,这插件 99% 的代码是他们写的。 :shock:

2008 年 10 月 3 日 凌晨修订,版本 1.1:数据库中的地址已经编码,提出图片地址后要解码,这会影响有空格或者中文的图片文件名。



Sep 28

哥,帮我做个相册好不?靠,你很闲啊,自己去弄!

ImageVue 是一款做的非常漂亮的基于 Flash+PHP+Javascript 的网络相册,在 2008 年 9 月发布了它的最新版本 03.09.08 Beta 。

ImageVue V2 功能

  • 1.加入了 HTML 相册模式及 Rewrite 地址静态化支持,使原来 Flash 不利于搜索引擎收录的缺点得到很好的改善
  • 2.放弃了 V1 中的相框设计,采用了更加美观的开放界面,使宽屏和大显示器用户拥有更好的浏览效果
  • 3.后台管理模块更加强大,包括管理用户、修改配置文件、更改语言包、更换主题和管理所有图片文件夹等
  • 4.基于 V1 的功能,包括自动探测文件夹、自动生成缩略图、支持 MP3 背景音乐等
  • 目前已经非常完美的支持中文,包括中文目录,文件名,文件描述等等,而你只需要稍微修改一下模板的 CSS 文件中的字体定义而已

ImageVue V2 新功能和特色

  • 1.后台管理员增加目录管理,可设置特定用户管理某一特定图片文件夹,实现了相册的多人管理和分级管理
  • 2.增加了Cache缓存模块,极大的节省了图片打开时间
  • 3.管理员可以在前台页面直接修改图片,使管理直观化

ImageVue V2 官方演示

ImageVue V2 环境需求

ImageVue 运行在 PHP 环境下,并且最好带 GD2 库(为了自动生成缩略图,如果没有 GD2,你也可以手工生成缩略图然后上传)。V2 在后台提供了空间测试功能,用来测试你的空间是否(完全)支持 ImageVue。V2 程序采用了智能模块化设计,所以某些空间上的缺陷并不会影响到整个程序,好比我测试的时候用的 PHPStudy 包默认没有开 EXIF 支持,它只是提醒而已,这并不会影响整体功能。

(要打开 EXIF 功能,你需要编辑 php.ini 文件,取消 php_exif.dll 以及 php_mbstring.dll 前面的注释,而且注意,php_mbstring.dll 必须在 php_exif.dll 之前加载!而 php.ini 中默认 php_exif.dll 是在 php_mbstring.dll 之后的,一定记得调整。)

ImageVueV2

ImageVue V2 简单设置

解压上传后,假设你的相册地址是:

https://www.quakemachinex.com/imagevue/

那么你的后台管理地址是:

https://www.quakemachinex.com/imagevue/imagevue

嗯,不要搞错了,默认用户名和密码都是 admin,进入后它会提示你及时更改这个超级用户密码,安全第一,改了吧。

点 Config,再点右边的 Create New Language ,新建一个语言包,输入 Chines,你就可以自己定制语言包了,要翻译的东西非常简单我就不详细说了。然后你需要在 themes - 你选择的模板 - edit - settings - language 里面填入 Chinese 就让主界面变成中文了。

它默认模板的字体对中文支持都不好,所以你可以在:

“themes - 你选择的模板 - edit - 右边的 Create new theme, based on default theme - Edit theme stylesheet”

里面修改类似:

“font-family: Candara, Arial, "Times New Roman", Times, serif;

的字段为:

" font-family: Tahoma, Arial, "Times New Roman", Times, serif;”

当然你也可以用文本编辑器打开:

https://www.quakemachinex.com/imagevue/imagevue/themes/你选择的模板目录名字

下面的 imagevue.css 文件,查找替换一次性搞定。 :mrgreen:

好了,其他的自己研究吧。 :evil:


Dec 06

AJAXRequestAHAH 是两个轻量级的 AJAX 应用开发框架,没错 JQuery,Prototype 等足够强大,可是实际上那几十上百 K 的代码我们用得着多少?

AJAXRequest 和 AHAH 只有几 K 大小,却完全能满足一般站点的 AJAX 应用。

AjaxRequest

AHAH


Nov 17

SweetTitles 这个 JavaScript 的脚本原作者是 Dustin Diaz。把它做成 WordPress 插件只需要很小的工作量。

SweetTitles 能实现原 FancyTooltips 的全部功能但是脚本缩小了 50% ,仅 5K ,如果有兴趣可以压缩一下会更小,而且具有淡入淡出效果。使用这些 Tooltips 插件不光为了美观,也因为 FireFox 默认的 ToolTip 能显示的内容太少。

SweetTitles 和 FancyTooltips 共同存在的问题是:

  1. 当 img 和 a 标签同时有 title 内容时(有时候还会显示 img 的 alt 内容),会重叠显示,其中一个为原浏览器 Tooltip 样式,1.1 解决了这个问题。
  2. 当 a 的 title 内容为空时或者根本没有 title 属性时,会显示一个空的 div 框,这个解决了。

另外,由于我只是使用 SweetTitles 来让 Tooltips 显示更多的 title 内容,所以原有的显示标签快捷键以及对应超链接地址功能被我屏蔽了,在 js 脚本的 137 行,需要的可以改回它。

脚本以及插件在 FireFox 以及 IE7 下测试成功。如果你使用了类似 Def-Link 这样的插件,强烈建议同时使用 SweetTitles 。

你还可以参考 Sweet Titles by class 一文,在特定的 Class 上使用 SweetTitles 而不是全部链接。


Nov 05

现在基本 80% 时间在用 FireFox 了,插件比较好玩。无聊点了一下 TrackBack 按钮,居然没反应,G 了一下才发现 FireFox 不支持剪贴板操作(它还不支持本地查看图片~.~,规矩真多);可是我看 MediaFire.com 明明支持 FireFox 把文件地址复制到剪贴板啊,于是把 MediaFire.com 的 main.js 下下来看了一下,原来是通过一个 Flash 文件来变相处理的。继续 G ,发现了这个方法的始作者 jeffothy ,他的文章为 Clipboard Copy。结合他的方法和 IE 本身简单的操作剪贴板,跨浏览器版本的“复制到剪贴板”源程序如下:


function copyTrackBack(str)
{
  if (window.clipboardData) {
    var copyornot = confirm('复制TrackBack到剪贴板?');
    if (copyornot) {
    window.clipboardData.setData("text", str);
    }
  }else{
    var copyornotm = confirm('复制TrackBack到剪贴板?');
    if (copyornotm) {
        var flashcopier='flashcopier';
        if(!document.getElementById(flashcopier)) {
            var divholder=document.createElement('div');
            divholder.id=flashcopier;
            document.body.appendChild(divholder);
        }
        document.getElementById(flashcopier).innerHTML='';
        var divinfo='';
        document.getElementById(flashcopier).innerHTML=divinfo;
    }
  }
  return false;
}

_clipboard.swf 请到原作者页面下载。


Oct 26

CoolCode默认显示模式是自动换行,当你的正文版面宽度很窄时,这样频繁的换行会使阅读代码变得困难。于是做了一点小改动,当点击代码界面时,自动显示滚动条,此时代码不换行。

需要改动的文件有.css,.js,.php。

.css


.hl-surround {
    background-color: #F9FBFC;
    border: 1px solid #C3CED9;
    padding: 0;
    margin: 0;
    margin-bottom: 5px;
    width: 98%;
    height: auto;
    overflow: hidden;
    white-space: normal;
    text-align: left;
    font-family: "Courier New", "BitStream Vera Sans Mono", Fixedsys, Courier, monospace;
}

主要是添加(改动)overflow: hidden 和 white-space: normal 这两个属性;

.js


function switchscroll(id){
if(id.style.overflow!="auto"){
	id.style.overflow="auto";
	id.style.whiteSpace="nowrap";
}else{
	id.style.overflow="hidden";
	id.style.whiteSpace="normal";
}
}

把这个函数添加进去;

.php


<div class="hl-surround" onclick="switchscroll(this);">

在.php中找到<div class="hl-surround",在其中添加一个onclick的事件,一共有四处。

示例,点击代码窗口:


$options = array(
    'numbers' => HL_NUMBERS_LI,
);
$hl =& Text_Highlighter::factory($lang, $options);
$this->blocks[$blockID] .= '<div class="hl-surround" onclick="switchscroll(this);">' . str_replace($this->hl_class, $this->hl_style, $hl->highlight($txt)) . '</div>';
$this->blocks[$blockID] = preg_replace('/<span style="[^"]*?"></span>/', '', $this->blocks[$blockID]);
$this->blocks[$blockID] = str_replace('<ol class="hl-main">',
    '<ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)">',
    $this->blocks[$blockID]);
$this->blocks[$blockID] = str_replace(""> </span></li>", "">&nbsp;</span></li>", $this->blocks[$blockID]);
$this->blocks[$blockID] = preg_replace('/<li><span style=(.*?)> </si', '<li><span style=\1>&nbsp;<', $this->blocks[$blockID]);

if ($hackphp) {
    $this->blocks[$blockID] = str_replace("<span style="color: Blue;">&lt;?php</span></li>n<li>", '', $this->blocks[$blockID]);
    $this->blocks[$blockID] = str_replace('<li><span style="color: Blue;">?&gt;</span></li>', '', $this->blocks[$blockID]);
}

附件是改好的文件。

BTW: IE真是...不好说了,注意到没,点击后,在FireFox下不会出现垂直滚动条,因为那个滚动条宽度并没计算到原容器里面,而在IE下点击,会出现垂直滚动条,它把滚动条的宽度也计算进去了>_<


Oct 23

该插件可以让你通过 <!--page--> 注释标签来将一个长篇文章分页显示,效果见NirSoft Software Collection

之所以叫“虚拟分页”,是因为本插件只是通过Javascript+CSS来隐藏部分页内容,所以实际上文章内容在页面载入时是全部加载的。Virtual Pagination不能提高你的长篇文章载入速度,但是可以很好的控制文章的版面长度,至于切换页面,当然是实时的了。

插件的使用很简单,下载解压后把vpage目录上传到WordPress的Plugins目录下,在后台激活Virtual Pagination;在文章中通过<!--page--> 来进行分页。

注意:使用本插件用<!--page-->分页时,有分页文章的页面可能不能通过XHTML验证,原因是WordPress的wpautop生成了一些多余的未封闭的p标签。通常这并不影响显示效果。

如果您特别在意,目前解决的办法是,文章手工分段(或者使用内置的所见即所得编辑器),然后使用在分页文章的自定义字段添加:“killautop”(不包括引号),值为 1

Install Notes (English):

This plugin allows long post to be split across multiple Virtual Page,and switch pages realtime.

DEMO: NirSoft Software Collection

1. Download and extract it,then upload to your wordpress plugins directory.

2. Activate it in administrator’s interface.

3. Use:
< linenum="off">

or [!--page--]

tag to pagination the post.

4. If you care about XHTML ,you can add a custom field of 'killautop' set to '1' to this paged post to disable the auto formatting.


[1/2]  1 2 >