一些小玩意

呃。。。我就不吐槽我写这篇文章的时候是多么的傻了,反正大家都是这么过来的。

写了点JavaScript的小玩意呃,因为越来越多人开始用jQuery(曾经我也是这大军中的一员),但是感觉太大了,而且附带了太多我不需要的功能,比如动画,要使用得当的话还要引入一堆插件,无端地增加页面加载时间。涉及到一些问题,从自己服务器引用文件的话太慢,甚至有时候文件不完整;从google lib引用的话时不时就被Q;从sina lib引用的话,我翻Q的时候速度又下来了。

要是自己写的话,灵活度就大了,需要什么功能再加上,文件肯定比jQuery小很多,而且功能都是我需要的,不会有冗余。写了一堆小东西了,不过比较成熟、拿得出手的也不多,先放两个。

$选择器:http://www.qblog.kilu.net/source/Query.js

Show&Hide:http://www.qblog.kilu.net/source/shownhide.js

天气预报服务2

前天晚上查看天气预报的Cron执行结果时,看到了这个:

SuccessSuccessSuccessSuccessSuccessSuccessSuccessSuccessSuccessFailSuccess

我感到莫名的压力。。。因为实际上这个服务只有11个用户。只有11个用户的服务都无法保证服务质量,这多荒唐。

这时我才发现,原作者的设计实际上是最优的选择。他的设计是,数据库里每一个用户的记录多一个字段today,作为今天是否已经发送的标记。应用是在18:00~18:30每隔几分钟执行一次,而不是在18:00执行一次。运行时,从数据库取出today字段值为0的用户发送短信,发送成功后将这个字段值改为1,直到不存在此字段为0的用户为止。应用的Cron任务有两个,出了18:00~18:30的发送短信以外,每晚00:30有还一次数据库写入,将所有用户的today字段值改为0,以供第二天发送短信时读取。

于是我想到了使用 xml 文件的方式,我可以在 SAE 建立一个 Storage ,将数据放入 xml 文件,保存在那里,使用跟数据库类似的原理进行读写。而且跟方便的是, php 可以用 DOMDocument 读取 xml (虽然我从来没有用过,我的 php 实践只到文件夹扫描为止),这跟 JavaScript 类似,而数据库?从上学期期末数据库设计作业之后我就再也没写过 SQL 语句了。然后我动手写了这么一堆玩意。

<?php
function getCityId($cName){
  $cxml = new DOMDocument('1.0');
  $cxml -> load('citydata.xml');
  $cities = $cxml -> getElementsByTagName('city');
  foreach($cities as $cs){
    $cns = $cs -> getElementsByTagName('name');
    $cis = $cs -> getElementsByTagName('id');
    $cn = $cns -> item(0) -> nodeValue;
    $ci = $cis -> item(0) -> nodeValue;
    if($cn == $cName){
      return $ci;
    }
  }
}

$xml = new DOMDocument();
$xml -> load('userfeed.xml');
$users = $xml -> getElementsByTagName('user');
foreach($users as $user){
  $nicks = $user -> getElementsByTagName('nick');
  $citys = $user -> getElementsByTagName('city');
  $mobiles = $user -> getElementsByTagName('mobile');
  $todays = $user -> getElementsByTagName('today');
  $nick = $nicks -> item(0) -> nodeValue;
  $city = $citys -> item(0) -> nodeValue;
  $mobile = $mobiles -> item(0) -> nodeValue;
  $today = $todays -> item(0) -> nodeValue;
  if($today == 0){
    $cityId = getCityId($city);
    $tomorrow = getWeatherData($cityId);
    $msg = $nick . ',您好!' . $city . '明天' . $tomorrow['Weah'] . ',温度' . $tomorrow['Temp'] . ',关注天气变化,注意身体哦~' . $serviceIntro;
    $SMSUrl = $sendBaseUrl . '?phone=' . $mobileNo . '&pwd=' . $mobilePwd . '&to=' . $mobile .'&u=1&msg=' . $msg;
    $SMSResult = httpRequest($SMSUrl);
    if($SMSResult == '200'){
      //Change sent state.
      $xml -> formatOutput = true;
      // $user -> getElementsByTagName('today') -> item(0) -> nodeValue = 1;// 看到这一句和下一句了吗?
      $today = 1;
      $xml -> save('userfeed.xml');
    }
  }
}

喵了个咪的,看到中文注释那里了吗?为了排除问题,我把两个方式都用上了。最后确实可以发送出去短信,但是 xml 里的 today 值压根就没有变化。。我还尝试了 saveXML('userfeed.xml'); ,我还尝试了把保存的语句写在 foreach 循环的外面。。实际上这好像是个不可能的任务了。。

所以我想,应该只能用数据库了。

顺便说一句,在本地进行测试的时候,获取天气数据有很多时候都是返回空字符,没有仔细研究原因。而在服务器上则不会出现这种情况。

天气预报服务

这是仿造一位知友写的天气预报订阅写的,没什么技术含量,为了节约数据库开销(SAE的数据库读写好贵T.T),把用户数据和城市数据存在单独的php文件里作为两个数组。。。orz。。其实本来想写到xml文件里,这样以后导出也比较方便,数据格式也比较规范,但是对于xml不熟悉,而且貌似权限没有办法进行恰当的设置(这样会造成直接访问xml文件就看到数据了),所以没有使用。

现在有个问题,就是整个流程是由一个文件驱动的,这个文件一旦运行,就循环地取得天气数据和用户数据,然后把短信发送出去了。就是说,直接访问这个文件跟crontab触发这个文件,本质上是没有区别的,短信都会发出去。这样就造成一个比较麻烦的问题,如果有爬虫访问了这个文件,所有用户都会收到短信,如果有人无意间访问了这个文件,短信也会发送出去,这样对用户来说是很不礼貌的。目前还没有想到解决办法。

上一部分代码吧,php学得好差,见笑了。

先是用户数据的范例。

<?php
$FeedUsers = array(
  '哈尔滨' => array(
    'user1' => array(
      'nick' => '用户1',
      'mobileNo' => '15123456789'
    ),
    'user3' => array(
      'nick' => 'user3',
      'mobileNo' => '13812345670'
    )
  ),
  '大连' => array(
    'user2' => array(
      'nick' => '用户2',
      'mobileNo' => '13800138000'
    )
  )
);
?>

城市数据的范例。

<?php
$cityDatabase = array(
  '哈尔滨' => '101050101',
  '大连' => '101070201'
);
?>

发送短信的部分。

<?php
error_reporting(0);
set_time_limit(0);
include_once('feed.php');// 这是用户数据
include_once('database.php');// 这是城市数据
$mobile = '13800138000';// 用来发送飞信的手机号
$mobilePwd = '123456';// 飞信密码
$to = $FeedUsers;// Import user data.
$cityList = $cityDatabase;// Import city data.
$serviceIntro = '(此服务由Joker强力驱动,详情访问http://mynook.info/)';// 很无耻地加了点附加信息~~
$sendBaseUrl = 'http://' . $_SERVER['HTTP_HOST'] . '/pafetion1.4.php';// 定义pafetion的路径

function getWeatherData($cId){// 这个比较简单,从中国天气网获取天气信息的函数
  if(empty($cId)){
    return false;
  }
  $wurl = 'http://m.weather.com.cn/data/' . $cId . '.html';
  $json = file_get_contents($wurl);
  $json = get_object_vars(json_decode($json));
  $json = get_object_vars($json['weatherinfo']);
  $Weah = $json['weather2'];
  $Temp = $json['temp2'];
  $tomo = array(
    'Weah' => $Weah,
    'Temp' => $Temp
  );
  return $tomo;
}

function _get_http_result($_url){// 发送http请求的函数,因为不想每一次都curl整个来一遍,所以分离出来了
  if(empty($_url)){
    return false;
  }
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, "$_url");
  curl_setopt($ch, CURLOPT_TIMEOUT, 8);
  curl_setopt($ch, CURLOPT_HEADER, 0);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
  $result = curl_exec($ch);
  $info = curl_getinfo($ch);
  curl_close($ch);
  if($result){
    return 'Success';
  }
}

foreach($to as $cityName => $group){//外层循环,对于每个组查询一次天气信息
  $cityId = $cityList[$cityName];// Get every city's id according to city's name.
  $groupUsers = $to[$cityName];// Get th users of current group.
  $tomorrow = getWeatherData($cityId);// Get current city's weather.
  foreach($group as $user){// Get users in current group.// 内层循环,针对每个用户生成不同短信内容
    $msg = $user['nick'] . ',您好!' . $cityName . '明天' . $tomorrow['Weah'] . ',温度' . $tomorrow['Temp'] . ',关注天气变化,注意身体哦~' . $serviceIntro;
    $url = $sendBaseUrl . '?phone=' . $mobile . '&pwd=' . $mobilePwd . '&to=' . $user['mobileNo'] .'&u=1&msg=' . $msg;// 生成短信请求的URL
    $sendResult = _get_http_result($url);
    if($sendResult == 'Success'){
      echo 'Success';
    }else {
      echo 'Fail';
    }
    sleep(1);
  }
}
?>

这个服务使用到了 pafetion 的飞信 API ,详情参看作者的博客:<http://3haku.net/tag/pafetion "pafetion">。城市数据由知友的原版天气预报订阅服务的源码提取:http://zhi.hu/DFWO

源码下载:http://www.qblog.kilu.net/source/nookweather.tar.gz

受到惊吓了

昨天下午在MDN上看东西看得头发涨,就去豆瓣看了下,正好有个友邻更新了图集,里面有一张是日本武士切腹的示意图。然后有个人在下面回帖贴了个视频地址。我手贱(我擦勒我手怎么那么贱啊)点进去缓冲了大半天看完之后我第一次有想吐的感觉。

阅读剩余部分 -

HTML5播放器[续]

假期哪也没去,宅在寝室实现了两个播放器实例,基于HTML5的,一个是播放单一歌曲的,为博客文章内嵌音乐准备的;另一个是列表播放器,完全就是要拿来替代桌面播放器的(虽然还远没有达到目标)。单曲版播放器的Demo已经放出,地址在:http://mynook.info/try/yplayer/,另一个播放器的Demo我会尽快放出。现在先贴完整版播放器的代码。写得比较粗糙,高手见笑了。因为没有地方可以抓取ogg格式的音乐,所以这个实例只支持Chrome和Safari(只在Chrome测试过。)。(音乐从点点网抓取,可能需要先在浏览器上登录点点网才能获取读权限。)

阅读剩余部分 -

HTML5播放器

放假我也没什么好说的,不过是在写代码之余多了些看电影的时间罢了。本着钻研的精神也就写了个HTML5的音乐播放器。关于HTML5的audio标签已经有很多资料了,实在不了解的可以看这里:HTML5多媒体组件的使用——第二部分:音频,或者这里:HTML5: Audio & Video API,或者这里:Html5 audio标签(属性)的使用详解,在W3SCHOOL也有关于audio标签的讲解。当然浏览器默认的播放界面是很难看的,所以才需要自己写播放器,其实就是使用自己的样式、自己的脚本来掩盖并驱动默认的播放器。

<input id="volumeBar" type="range" />

首先使用js将audio的controls设置为false,这样就去掉了默认的控制界面。不要直接在audio里禁用controls,否则禁用了浏览器Javascript功能的用户就没有办法控制音乐的播放了。

var player = document.getElementById('player');
player.controls = false;

然后添加播放和暂停功能。

var playerPlay = document.getElementById('playBtn');
var playerMuteBtn = document.getElementById('muteBtn');
var playerVol = document.getElementById('volumeBar');
var playerPro = document.getElementById('audioProgress');
var playerProVal;
playerPlay.addEventListener('click',function(){
  if(player.paused || player.ended){
    player.play();
  }else{
    player.pause();
  }
});

解释一下,audio的事件和方法,具体可以参考这里:HTML5 Audio/Video 标签,属性,方法,事件汇总。实际上我们就是通过这些事件和方法来控制audio标签的。上面一段代码的作用,是给播放按钮绑定click事件,当音乐播放完毕或者处于暂停状态时,点击按钮播放;否则,点击按钮暂停。然后添加静音功能,用到muted属性。

playerMuteBtn.addEventListener('click',function(){
player.muted = !player.muted;
});

简单地说,是点击静音按钮后把muted属性值反转。添加音量控制。

playerVol.addEventListener('change',function(){
playerObj.volume = playerVol.value;
});

进度条的添加。(progress元素可能没有得到充分的浏览器支持,如果要做跨浏览器的兼容,建议使用span#progress。)

player.addEventListener('timeupdate',function(){
(player.currentTime > 0 && player.currentTime < player.duration) ? playerProVal = Math.floor((1000 / player.duration) * player.currentTime) : playerProVal = 0;
playerPro.setAttribute('value',playerProVal);
});

这里夹杂了Javascript里 if...else... 语句的一个简写: (a)?b:c; 若a为真则b,否则c。 如果你使用 span#progress 作为进度条的话,就应当将 playerProVal 的值赋给 span#progresswidth 。剩下的就是样式以及一些额外功能和优化了。以下是我做的播放器的截图。HTML5播放器-YPlayer

第一次写技术文,也不太会表达,见谅。

Learning HTML&CSS in 30 days

30天学会HTML和CSS!

这个教程存在我电脑里有些时间了,以致于我忘记了最初是从哪里看到的消息,作者名字和网站也完全没有映象,如果有哪位知道,请告知我一声,我好把作者信息加上。

Update:此教程来自http://learncss.tutsplus.com/,原标题是 **30 Days to Learn HTML & CSS: A Free Tuts+ Premium Course **,作者为Jeffrey Way 。
视频是无字幕及水印的。最近在听译视频内容,争取把外挂字幕做出来。

好了,直接放地址。

阅读剩余部分 -

开学什么的

开学很久了都没有想起来要写点东西,记忆力和执行力都退化到一个不像样的档次了么。这学期的课貌似很满,没有大块的时间来堆砌代码了,不过这样也好,可以从另一个方面锻炼自己对零碎时间的利用。

阅读剩余部分 -