<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title type="html"><![CDATA[RIA爱好者]]></title>
    <subtitle type="html"><![CDATA[Flash,Flex,AIR,Ajax,Silverlight,Html5]]></subtitle>
    <id>http://www.riafan.com/</id>
    <link rel="alternate" type="text/html" href="http://www.riafan.com/" /> 
    <link rel="self" type="application/atom+xml" href="http://www.riafan.com/atom.asp" /> 
    <generator>PJBlog</generator> 
    <updated>2012-02-03T18:12:35+08:00</updated>
    <entry>
        <title type="html"><![CDATA[用CSS3移除点击交互元素的高亮背景]]></title>
        <author>
             <name>Flying</name>
             <uri>http://www.riafan.com/</uri>
             <email>riafan@163.com</email>
        </author>
        <category term="" scheme="http://www.riafan.com/default.asp?cateID=12" label="HTML5" /> 
        <updated>2012-02-03T18:12:35+08:00</updated>
        <published>2012-02-03T18:12:35+08:00</published>
        <summary type="html"><![CDATA[<p>我在移动设备上测试前面教程的图表实例时发现，当手指点击图表出现ToolTip时，图表容器的会出现一个半透明的高亮背景。设备浏览器不一样，颜色也不一样，很是影响交互效果。试了一下用Javascript来移除，花了一天时间也没弄出来，最后不得不Google了，又花了几个小时，终于用CSS3搞定了。</p>
<p>代码如下：</p>
<pre class="brush:css">
-webkit-tap-highlight-color: rgba(255, 255, 255, 0); 
-webkit-user-select: none;
-moz-user-focus: none;
-moz-user-select: none;
</pre>
<p>新加了禁止选择文本的功能。其中，前二句对WebKit内核浏览器(Safari、Chrome、iPhone、iPad、Android等)有效，后二句对Gecko内核的浏览器(Firefox等)有效。</p>
<p>看来真该花些时间学学CSS3了。</p>]]></summary>
        <link rel="alternate" type="text/html" href="http://www.riafan.com/article/html5/remove-tap-highlight-color-in-devices-with-css3.html" /> 
        <id>http://www.riafan.com/default.asp?id=263</id>
    </entry>
    <entry>
        <title type="html"><![CDATA[使用Flotr自定义线性轴来显示时间]]></title>
        <author>
             <name>Flying</name>
             <uri>http://www.riafan.com/</uri>
             <email>riafan@163.com</email>
        </author>
        <category term="" scheme="http://www.riafan.com/default.asp?cateID=12" label="HTML5" /> 
        <updated>2012-01-26T12:15:21+08:00</updated>
        <published>2012-01-26T12:15:21+08:00</published>
        <summary type="html"><![CDATA[<p>Flotr的轴默认为线性轴(mode="normal")。为什么要使用Flotr自定义线性轴来显示时间呢？正如上一篇文章所言：如果使用时间轴，当时间范围为五天时，会在当天与下一天之间绘制一大段多余的

连接线，而且轴标签有时会找不到对应的数据点而缺少实际意义。因此，有必要自定义线性轴而不是使用时间轴。</p>
<p><a target="_blank" href="http://www.riafan.com/html5/linearaxis">点击此处</a>查看本实例的效果。是不是和<a target="_blank" href="http://www.riafan.com/?id=224">http://www.riafan.com/default.asp?id=224</a>很相似呀？</p>
<p>是的，连算法都很相似。这里的所有日期标签是用axis.ticks数组来管理的，同样在一种日期格式下，当前标签与下一日期标签和上一标签的文本不相同时才显示出来。请参考下面代码：</p>
<pre class="brush:js">
else if (o.mode == 'timeEx') {
  var data = hitData;
  var tu = Flotr.Date.timeUnits,
  span = data[axis.max][0] - data[axis.min][0];
  $H(tu).each(function(pair) { 
    var v = Math.floor(span/pair.value);
    // less than 3 times
    if(0 < v && v < 72){
      t = Flotr.Date.timeUnits[pair.key];
      axis.tickUnit = pair.key;
    }
  });  
  tick_dateFormat = Flotr.Date.getFormat(t, span); 
  // store all possible ticks.
  var preLabel;
  var nextLabel;
  var r = axis.max - axis.min; 
  for(i = 0; i < r; ++i){
    preLabel = o.tickFormatter(i);
    nextLabel = o.tickFormatter(i + 1);
    if(nextLabel != preLabel)
      axis.ticks.push({ v: i + 1, label: nextLabel });
  }
}</pre>
<p>当两个日期标签间隔太近容易重叠时，我们也用了类似方法来移除，只不过在Flex中参照间距是相对的，而此处是绝对的。如下面代码：</p>
<pre class="brush:js">
//filter the labels
var len = axis.ticks.length;
if(len > 4){
  var preTick;
  var nextTick;
  for (i = len - 1; i > 0; i--) {
    preTick = axis.ticks[i - 1];
    nextTick = axis.ticks[i];
    //remove the middle label
    if(nextTick){
      if(axis.d2p(nextTick.v) - axis.d2p(preTick.v) < 8 * preTick.label.length){
	axis.ticks.splice(i - 1, 1);
      }
    }
  }
}
</pre>
<p>使用方法很简单，将xaxis的mode指定为自定义的线性轴就行了。另外，本实例中不得不命名两个全局的变量hitData和tick_dateFormat，为了简单我们在flotr.js中引用了它们。当然，你可以将它

们封闭到flotr.js中。</p>]]></summary>
        <link rel="alternate" type="text/html" href="http://www.riafan.com/article/html5/dispay-time-using-customized-linearaxis-in-flotr.html" /> 
        <id>http://www.riafan.com/default.asp?id=262</id>
    </entry>
    <entry>
        <title type="html"><![CDATA[使用Flotr绘制股票图]]></title>
        <author>
             <name>Flying</name>
             <uri>http://www.riafan.com/</uri>
             <email>riafan@163.com</email>
        </author>
        <category term="" scheme="http://www.riafan.com/default.asp?cateID=12" label="HTML5" /> 
        <updated>2011-12-20T12:28:23+08:00</updated>
        <published>2011-12-20T12:28:23+08:00</published>
        <summary type="html"><![CDATA[<p>HTML5虽然还在起草阶段，但这不妨碍Html5 Canvas的流行。不管是简单游戏还是绘制图表，Html5 Canvas完全都可以胜任，各种主流浏览器都对Html5 Canvas支持得很好，低版本的IE也可以使用Excanvas来兼容。我们可以预见：Html5 Canvas将代替Flash绘制交互性很强的股票图。本文推荐使用Flotr，它是目前我见过的功能最全、性能最好、最适合绘制股票的HTML5 JavaScript图表库。不仅支持各种类型的图表（包括蜡烛图），还支持各种交互操作，如鼠标跟踪、选择缩放等。适当扩展，完全可以做出Google Finance那样的效果：http://www.humblesoftware.com/finance/index。本文的实例这么复杂，主要介绍一下绘制股票图基本流程和注意事项。</p>
<p><a target="_blank" href="http://www.riafan.com/html5/flotr">点击此处</a>查看本实例的效果。以Yahoo股票为例，页面加载完成后会绘制当天的收盘价格图。切换到不同的时间范围会重新绘制相应的图表。下面说一下基本流程。</p>
<h3>一、知识准备</h3>
<ul>
    <li>对Flotr有所了解，可以参看我上一篇文章：<a target="_blank" href="http://www.riafan.com/?id=260">Flotr快速入门指南</a>；</li>
    <li>对prototype框架有所了解，尤其是Ajax和事件部分。Flotr整个库就是基于prototype框架的，本实例也会用到它。</li>
</ul>
<h3>二、数据准备</h3>
<p>本实例是使用Ajax从http://chartapi.finance.yahoo.com/instrument/1.0/抓取的Json数据，数据格式如下：</p>
<p>{"data":[":[[1324287010000,14.9300],[1324287119000,14.9500]...]}</p>
<p>本实例只绘制一个数据系列，组成数据系列每个数据点对应一个x和y坐标的数组。其中，x坐标表示自1970年1月1日午夜（通用时间）以来的毫秒数，y坐标表示该时间的收盘价。</p>
<h3>三、绘制图表</h3>
<p>使用document的observe()方法侦听“dom:loaded”事件，以便加载完dom后调用updateChart方法绘制当天的收盘价格图。代码好下：</p>
<pre class="brush:js">
var f = null; 
document.observe('dom:loaded', function(){
    updateChart("1d", 10);
});
</pre>
<p>updateChart有两个参数。第一个参数表示当前的时间范围，如“id”、“5d”、“1y”等。另一个参数表示刻度线数量。</p>
<pre class="brush:js">
function updateChart(range, noTicks){
    new Ajax.Request('stock.aspx?symbol=YHOO&amp;range=' + range, {
        method:'get',
        onSuccess: function(transport){
            var json = transport.responseText.evalJSON();
            if(json.data){
                ...
	        f = Flotr.draw($('container'), [json.data], options);
            }else{
	        $('container').update('The data could not be retrieved.')
            }
        }
    });
}
</pre>
<p>代码中选项设置比较多，如设置折线图填充为渐变色['#618192', '#749AAF']，其实这就和Flex Chart组件的区域图差不多。</p>
<h3>四、更新图表</h3>
<p>最后我们在时间范围按钮的onclick事件中调用updateChart()方法，通过Ajax重新获取数据，重绘相应的图表。其实，也可以使用按钮的observe()方法，在侦听click事件中回调updateChart()方法来实现图表更新。</p>
<h3>注意事项：</h3>
<ul>
    <li>本实例中x轴使用了时间轴，从而简化了应用。但是当时间范围为五天时，会在当天与下一天之间绘制一大段多余的连接线。这不是什么Bug，与时间轴的算法有关。Flex Chart组件的时间轴也有这个问题。可以用线性轴或通过后台计算显示设置刻度线来修正这个问题，下次再聊这个话题吧。</li>
    <li>在显示数据点提示时，时间应该是本地时间。</li>
</ul>
<h3>更多了解Html5 JavaScript图表库：</h3>
<ul>
    <li><a target="_blank" href="http://www.amcharts.com">amCharts</a></li>
    <li><a target="_blank" href="http://www.jqchart.com">Jqchart</a></li>
    <li><a target="_blank" href="http://code.google.com/p/flot">Flot</a></li>
    <li><a target="_blank" href="http://www.rgraph.net">Rgraph</a></li>
    <li><a target="_blank" href="http://www.zingchart.com">Zingchart</a></li>
</ul>]]></summary>
        <link rel="alternate" type="text/html" href="http://www.riafan.com/article/html5/stock-chart-using-flotr.html" /> 
        <id>http://www.riafan.com/default.asp?id=261</id>
    </entry>
    <entry>
        <title type="html"><![CDATA[Flotr快速入门指南]]></title>
        <author>
             <name>Flying</name>
             <uri>http://www.riafan.com/</uri>
             <email>riafan@163.com</email>
        </author>
        <category term="" scheme="http://www.riafan.com/default.asp?cateID=12" label="HTML5" /> 
        <updated>2011-12-18T20:55:09+08:00</updated>
        <published>2011-12-18T20:55:09+08:00</published>
        <summary type="html"><![CDATA[<p>Flotr是一个基于Prototype开发的javascript绘图工具。支持图例、鼠标跟踪、图片区域选择、图片缩放、添加事件钩子（event hook）、通过CSS设置样式等。本文是快速创建并运行Flotr的入门指南。首先确保你从<a title="Flotr Google Project Page" target="_blank" href="http://code.google.com/p/flotr/">Google Project</a>得到Flotr的副本。</p>
<h2>准备HTML</h2>
<p>要使用Flotr，你得在header标签中包含如下脚本：</p>
<pre class="brush:xml">
&lt;!--[if IE]&gt;&lt;script language="javascript" type="text/javascript" src="path/to/excanvas.js"&gt;&lt;/script&gt;&lt;![endif]--&gt;
&lt;script language="javascript" type="text/javascript" src="path/to/prototype-x.x.x.x.js"&gt;&lt;/script&gt;
&lt;script language="javascript" type="text/javascript" src="path/to/flotr.js"&gt;&lt;/script&gt;
</pre>
<p>第一个script标签包含了一个html条件语句， 这样可以确保只有在用户使用IE时才包含<a title="Excanvas Project Page" target="_blank" href="http://excanvas.sourceforge.net/">excanvas</a>&nbsp;javascript文件。Firefox、Safari和Opera 9 支持canvas标签来绘制2d图形。IE有一些类似于canvas标签的东西，叫<a title="Wikipedia Vector Markup Language" target="_blank" href="http://en.wikipedia.org/wiki/Vector_Markup_Language">VML</a>。Excanvas为IE增加了canvas功能，但其它浏览器不需要它。</p>
<p>现在我们已经包含了javascript文件，还需要一个div元素来显示图表。Flotr在绘制时插入两个canvas标签到此div中。第一个canvas标签用来绘制背景网格、轴和图表，第二个canvas标签用作重叠显示用户交互。</p>
<p>设置容器div的宽高是非常重要的，可以使用内联的样式属性，或者css规则来实现。一个容器div的实例：</p>
<p>&lt;div id="container" style="width:600px;height:300px;"&gt;&lt;/div&gt;</p>
<p>所有需要的html就这些。当然，你可以为各种各样用Flotr创建的图表设置样式。详见CSS章节。</p>
<h2>准备Javascript</h2>
<p>与<a title="Plotr Javascript Charting Engine" target="_blank" href="http://www.solutoire.com/plotr">Plotr</a>不同，Flotr的语法极其简单。绘制图表仅需调用Flotr.draw(element, series, options)就行了， 其参数为：</p>
<ul>
    <li>element: 容器元素</li>
    <li>series: 系列数组</li>
    <li>options: 可选的选择对象</li>
</ul>
<h2 id="series">Flotr (数据)系列</h2>
<p>Flotr可接受的数据由系列数组组成，如：</p>
<p>[ serie1, serie2, ... ]</p>
<p>系列可以是原生数据或属性对象。原生数据的格式为x和y坐标的数组：</p>
<p>[ [x1, y1], [x2, y2], ... ]</p>
<p>通过传递一个对象，你也可以传递系列为指定选项：</p>
<pre class="brush:js">
{
    color: 颜色或数字,
    data: 原生数据,
    label: 字符,
    lines: 特定的lines选项,
    bars: 特定的bars选项,
    points: 特定的points选项,
    mouse:  鼠标追踪选项,
    shadowSize: 数字
}
</pre>
<p>这样的系列对象可能是：</p>
<pre class="brush:js">
{
    data: [ [1, 2], [2, 4], [3, 6] ],
    label: "y = 2x",
    lines: {fill: true},
    points: {show: true}
}
</pre>
<p>下面实例实现了javascript怎样绘制两个系列，代码可能如下：</p>
<pre class="brush:js">
// Execute this when the page's finished loading
var f = Flotr.draw(
	$('container'), [
	{ // first series
	    data: [ [0, 0], [1, 2], [2, 4], [3, 6], [4, 8] ],
	    label: "y = 2x",
	    lines: {show: true, fill: true},
	    points: {show: true}
	},
	{ // second series
	    data: [ [0, 2.5], [1, 5.5], [2, 8.5], [3, 11.5], [4, 14.5] ],
	    label: "y = 2.5 + 3x"
	}]
);
</pre>
<p>图表将会插入到id为'container'的元素中。第一个系列由一条带有特定坐标（数据属性）点的线组成。当指定系列标签时，会为图表自动添加图例。第二个系列中是一条功能为'y = 2.5 + 3'的直线。了解更多数据系列，参看<a title="Passing data to Flotr" target="_blank" href="http://solutoire.com/flotr/docs/passing-data-to-flotr/">'传递数据给Flotr'</a>。</p>
<p><img alt="QuickStart Graph 1" src="http://solutoire.com/blog/wp-content/uploads/2008/02/quickstart-graph1.png" /><br />
<i>效果图表</i></p>
<h2>选项对象</h2>
<p>Flotr.draw()的第三个参数为一个可选的属性对象，该属性可以覆盖图例、网格、线、轴等的默认属性：</p>
<pre class="brush:js">
{
    colors: 颜色或数字数组,
    legend: 特定的图例,
    xaxis: 特定的xaxis选项,
    yaxis: 特定的yaxis选项,
    grid: 特定的grid选项,
    lines: 特定的lines选项,
    bars: 特定的bars选项,
    points: 特定的points选项,
    selection: 鼠标选择选项,
    mouse: 鼠标追踪选项,
    shadowSize: 数字
}
</pre>
<p>所以说选项对象会覆盖默认属性，但轮到那些选项时，却被<a target="_blank" href="http://solutoire.com/flotr/docs/quickstart/#series">系列对象</a>定义的选项所覆盖。</p>
<p>更多资源：</p>
<ul>
    <li>官网：<a target="_blank" href="http://solutoire.com/flotr/">http://solutoire.com/flotr/</a></li>
    <li>帮助文档：<a target="_blank" href="http://solutoire.com/flotr/docs/">http://solutoire.com/flotr/docs/</a></li>
    <li>示例：<a target="_blank" href="http://phenxdesign.net/flotr/examples/prototype/">http://phenxdesign.net/flotr/examples/prototype/</a></li>
    <li>案例：<a target="_blank" href="http://www.humblesoftware.com/finance/index">http://www.humblesoftware.com/finance/index</a></li>
</ul>]]></summary>
        <link rel="alternate" type="text/html" href="http://www.riafan.com/article/html5/flotr-quick-start-guide.html" /> 
        <id>http://www.riafan.com/default.asp?id=260</id>
    </entry>
    <entry>
        <title type="html"><![CDATA[使用HTML5 Canvas绘制简单图表]]></title>
        <author>
             <name>Flying</name>
             <uri>http://www.riafan.com/</uri>
             <email>riafan@163.com</email>
        </author>
        <category term="" scheme="http://www.riafan.com/default.asp?cateID=12" label="HTML5" /> 
        <updated>2011-11-28T15:00:35+08:00</updated>
        <published>2011-11-28T15:00:35+08:00</published>
        <summary type="html"><![CDATA[<p>HTML5 canvas最流行的应用之一是绘制图表。我们将用一个很简单的例子，讲述如何在画布上绘制图表。明白这些基本概念后再进一步深化，就可以使我们的图形功能更灵活。</p>
<p>下面是我们简单绘制图表的步骤：</p>
<ul>
    <li>创建2D画布context对象</li>
    <li>绘制X轴</li>
    <li>绘制Y轴</li>
    <li>基于数据绘制路径</li>
</ul>
<p>我们需要理解如何在画布上元素绘制多个点。在X轴从左边0开始，向右移值增加，y轴从0开始的顶部，向向下移值增加。如下图：</p>
<p><img alt="坐标" border="0" src="http://www.riafan.com/attachments/month_1111/chart.gif" /></p>
<p>让我们将画布放置在页面上。</p>
<pre class="brush:xml">
&lt;canvas id="canvas" width="180" height="105"&gt;
  Your browser does not support the canvas element.
&lt;/canvas&gt;
</pre>
<p>要在画布上绘图，我们需要使用JavaScript引用canvas元素。我们用init（）函数实现这一功能并在初始化时调用它。</p>
<pre class="brush:js">
function init() {
    canvas = document.getElementById("canvas");
    if(canvas.getContext)
    {
      ctx = canvas.getContext("2d");
      draw();
    }
}
</pre>
<p>首先，我们通过canvas的id搜索DOM元素得到画布元素，然后新建了一个画布context对象，该对象可以在JavaScript内部完成绘制工作。 context对象包含在画布上绘图的基本方法，比如arc(), lineto() 和stroke()。</p>
<p>然后调用draw()函数来绘制图表。</p>
<pre class="brush:js">
function draw() {
    clear();
    drawaxes();
    plotdata();  
}
</pre>
<p>我们调用clear()函数，该函数使用clearRect()方法来清除一个与画布同样大小矩形。清除的矩形的两个对角设置为（0,0）和（宽，高）。宽度和高度与画布上的宽度高度相同。你可以很容易部分清除画布，但我们想要的是清空画布。</p>
<pre class="brush:js">
function clear() {
    ctx.clearRect(0, 0, WIDTH, HEIGHT);
}
</pre>
<p>接下来，使用drawaxes()函数在画布左侧和底部绘制X轴和Y轴。</p>
<pre class="brush:js">
function drawaxes(){
    ctx.strokeStyle = "black";
    ctx.beginPath();
    /* y axis along the left edge of the canvas*/  
    ctx.moveTo(0,0);  
    ctx.lineTo(0,105);
    ctx.stroke();  
    /* x axis along the bottom edge of the canvas*/  
    ctx.moveTo(0,105);  
    ctx.lineTo(180,105);
    ctx.stroke();  
}
</pre>
<p>context对象的strokestyle属性设置成想要的笔触颜色，在使用stroke()方法绘制路径时会用到它。</p>
<p>ctx.strokeStyle = "black";</p>
<p>然后我们从新建的路径开始绘制。</p>
<p>ctx.beginPath();</p>
<p>现在，我们利用创建的新路径，使用stroke方法绘制Y轴。</p>
<pre class="brush:js">
/* y axis along the left edge of the canvas*/  
ctx.moveTo(0,0);  
ctx.lineTo(0,105);
ctx.stroke();
</pre>
<p>同样的方法绘制X轴。</p>
<pre class="brush:js">
/* x axis along the bottom edge of the canvas*/  
ctx.moveTo(0,105);  
ctx.lineTo(180,105);
ctx.stroke();
</pre>
<p>下一步，在draw()方法中调用plotdata()方法。</p>
<pre class="brush:js">
function plotdata() {
    ctx.strokeStyle = "rgb(0,0,165)";
    ctx.lineWidth = 1;
    ctx.beginPath();
    ctx.lineJoin = "miter";
    ctx.moveTo(0, HEIGHT - (temps[0]));
    j = 1;
    for (var i in temps) {
        ctx.lineTo(j * 30, HEIGHT - (temps[j]));
        ctx.stroke();
        j++;
    }
}
</pre>
<p>同样，设置context对象的strokestyle属性，从新建路径开始绘制。</p>
<pre class="brush:js">
ctx.strokeStyle = "black";
ctx.beginPath();  
</pre>
<p>移至坐标原点。从顶部至底部Y轴值下降，但打算我们顶端表示数据的最小值，底端表示数据的最大值，因此我们使用如下公式：</p>
<p>ctx.moveTo(0,HEIGHT-(temps[0]));</p>
<p>这个公式有效地反转温度值，因此距离底部80像素，而不是距离顶部80像素。现在，我们遍历其它的温度值并在每个相邻值之间画一条线。</p>
<pre class="brush:js">
j = 1;
for (var i in temps) {
    ctx.lineTo(j * 30, HEIGHT - (temps[j]));
    ctx.stroke();
    j++;
}
</pre>
<p>我们使用j * 30，每个数据点间距为30像素，而不是7像素，这样才有足够的空间。</p>
<p><a target="_blank" href="http://www.riafan.com/html5/simplegraph">点击此处</a>查看本实例的效果。</p>]]></summary>
        <link rel="alternate" type="text/html" href="http://www.riafan.com/article/html5/simple-chart-in-the-html5-canvas.html" /> 
        <id>http://www.riafan.com/default.asp?id=259</id>
    </entry>
    <entry>
        <title type="html"><![CDATA[在Flex手机应用中使用PopUpManager创建Alert窗口]]></title>
        <author>
             <name>Flying</name>
             <uri>http://www.riafan.com/</uri>
             <email>riafan@163.com</email>
        </author>
        <category term="" scheme="http://www.riafan.com/default.asp?cateID=5" label="Flex" /> 
        <updated>2011-11-11T10:13:03+08:00</updated>
        <published>2011-11-11T10:13:03+08:00</published>
        <summary type="html"><![CDATA[<p>Flex手机应用中没有Alert组件。今天在Flex Developer Center看到一篇文章：<a href="http://www.adobe.com/devnet/flex/articles/flex-mobile-development-tips-tricks-pt4.html">http://www.adobe.com/devnet/flex/articles/flex-mobile-development-tips-tricks-pt4.html</a>，觉得用SkinnablePopUpContainer来弹出Alert窗口确实简单，但这种做法太过简单了，不能重用代码，旋转手机时Alert窗口不能重新居中，于是我花了点时间自己做了一个Mobile Alert组件。</p>
<p>进入每个视图都会弹出一个Alert窗口，点击Open按钮也会弹出Alert窗口。该组件是用PopUpManager来实现Alert窗口打开和关闭的，因为本人更喜欢Flex Web中的Alert组件的静态方法，比用new关键字来创建简捷一点。</p>
<p>这是在HTC上运行效果图：</p>
<p><img alt="横向效果图" src="http://www.riafan.com/attachments/month_1111/alert_landscape.gif" /></p>
<p>可以看到，横向旋转手机时，Alert窗口依然是居中的。</p>
<p>感兴趣的话，<a href="http://www.riafan.com/download.asp?id=87">点击此处</a>下载源码。</p>
<p>代码不难，有几点要指出一下：</p>
<ol>
    <li>用resize事件实现了Alert窗口重新居中显示，不知道为何用orientationChange事件来实现不会成功。</li>
    <li>show()方法有四个参数，分别表示Alert窗口的标题、消息、容器对象和是否为模态窗口。</li>
    <li>考虑到切换主视图时要清除前一个视图中所有的Alert窗口，因此加了一个removeAll()方法，对每个视图viewDeactivate事件不得不调用该方法，这点比较麻烦。</li>
    <li>该组件由AlertForm.mxml实现界面，很轻量，在窗口关闭时没有回调方法也不能返回函数。需要更高级的功能可以自行扩展。</li>
</ol>]]></summary>
        <link rel="alternate" type="text/html" href="http://www.riafan.com/article/flex/flex-mobile-alert-with-popupmanager.html" /> 
        <id>http://www.riafan.com/default.asp?id=258</id>
    </entry>
    <entry>
        <title type="html"><![CDATA[在Flex手机应用中使用media规则]]></title>
        <author>
             <name>Flying</name>
             <uri>http://www.riafan.com/</uri>
             <email>riafan@163.com</email>
        </author>
        <category term="" scheme="http://www.riafan.com/default.asp?cateID=5" label="Flex" /> 
        <updated>2011-10-31T23:09:40+08:00</updated>
        <published>2011-10-31T23:09:40+08:00</published>
        <summary type="html"><![CDATA[<p>有时，开发人员希望对不同的平台设备和设备配置（如不同的DPI）使用不同的样式，我们可以在样式表中使用@media规则做到这一点。</p>
<p>@media规则是 CSS 规范的一部分；Flex 扩展了此规则，将额外的属性application-dpi和os-platform包括进来。通过这些属性，可以根据应用程序DPI和运行应用程序的平台来选择性地应用样式。</p>
<p>Flex支持两种CSS选择器。第一种针对操作平台。下面的代码演示了在不同平台下为标签选择不同的字体颜色。</p>
<pre class="brush:css">
@namespace s "library://ns.adobe.com/flex/spark"; 
@media (os-platform: "IOS") { 
  s|Label 
  { 
    color: red; 
  } 
} 
@media (os-platform: "Android") { 
  s|Label { 
    color: blue; 
  } 
}</pre>
<p>第二种针对DPI。下面的代码演示了在不同DPI下为按钮选择不同的字体大小。</p>
<pre class="brush:css">
@namespace s "library://ns.adobe.com/flex/spark"; 
@media (application-dpi: 160) { 
  s|Button { 
    fontSize: 10; 
  } 
} 
@media (application-dpi: 240){ 
  s|Button { 
    fontSize: 11; 
  } 
} 
@media (application-dpi: 320){ 
  s|Button { 
    fontSize: 12; 
  } 
}</pre>
<p>另外，@media规则还支持运算符and和not。同时还支持以逗号分隔的列表。如果以逗号分隔表达式，意味着各项之间是or的关系。</p>]]></summary>
        <link rel="alternate" type="text/html" href="http://www.riafan.com/article/flex/media-query.html" /> 
        <id>http://www.riafan.com/default.asp?id=257</id>
    </entry>
    <entry>
        <title type="html"><![CDATA[设计和开发手机应用程序的注意事项]]></title>
        <author>
             <name>Flying</name>
             <uri>http://www.riafan.com/</uri>
             <email>riafan@163.com</email>
        </author>
        <category term="" scheme="http://www.riafan.com/default.asp?cateID=5" label="Flex" /> 
        <updated>2011-10-25T11:28:21+08:00</updated>
        <published>2011-10-25T11:28:21+08:00</published>
        <summary type="html"><![CDATA[<p>构建适用于移动设备的应用程序不仅仅是将桌面应用程序缩小为不同的屏幕大小。通过Flex，您可以针对每个外观因素分别创建适当的用户界面，同时在手机、浏览器和桌面项目之间共享基础模型和数据访问代码。</p>
<p>移动触摸屏设备的应用程序与桌面和浏览器应用程序有以下不同之处：</p>
<p>为了通过触控输入实现简便的操作，手机组件通常具有比桌面或浏览器应用程序中更大的点击区域。</p>
<ul>
    <li>在触摸屏设备上，滚动等操作的交互模式不同。</li>
    <li>由于屏幕区域有限，因此手机应用程序通常设计为在屏幕上同时只显示少量的用户界面。</li>
    <li>用户界面的设计必须考虑不同设备之间屏幕分辨率的差异。</li>
    <li>相较于桌面设备，手机和平板电脑的CPU和GPU性能更为有限。</li>
    <li>由于移动设备上可用内存有限，因此应用程序必须注意节约内存。</li>
    <li>手机应用程序可以随时（例如在接听电话或短信时）退出和重新启动。</li>
</ul>]]></summary>
        <link rel="alternate" type="text/html" href="http://www.riafan.com/article/flex/considerations-in-mobile-applications.html" /> 
        <id>http://www.riafan.com/default.asp?id=256</id>
    </entry>
    <entry>
        <title type="html"><![CDATA[自定义Javascript类型]]></title>
        <author>
             <name>Flying</name>
             <uri>http://www.riafan.com/</uri>
             <email>riafan@163.com</email>
        </author>
        <category term="" scheme="http://www.riafan.com/default.asp?cateID=7" label="Ajax" /> 
        <updated>2011-09-23T11:56:56+08:00</updated>
        <published>2011-09-23T11:56:56+08:00</published>
        <summary type="html"><![CDATA[<p>Javascript没有类的概念，ECMA-262把Javascript对象定义为“无序属性的集合，其属性可以包含基本值、对象和函数”。我们可以把Javascript对象看作是Hash对象，其中属性就是键，值可以是数据或函数。</p>
<p>自定义Javascript对象最简单的办法就是创建一个Object的实例，然后为它添加属性方法。看下面代码：</p>
<pre class="brush:js">
var person = new Object();
person.name = 'Jim';
person.age = 30;
person.job = 'IT';
person.sayName = function(){
	alert(this.name);
};</pre>
<p>显然，这种方式会产生大量重复代码。为解决这一问题，通常可以用工厂模式。</p>
<p>一、工厂模式</p>
<p>这种模式采用了软件工程中的工厂设计模式的思想。看下面代码：</p>
<pre class="brush:js">
function createPerson(name, age, job){
	var o = new Object();
	o.name = name;
	o.age = age;
	o.job = job;
	o.sayName = function(){
		alert(this.name);
	};
	return o;
}
var person1 = createPerson('Jim', 30, 'IT');
var person2 = createPerson('Tom', 27, 'Doctor');</pre>
<p>工厂模式虽然解决了重复代码的问题，但与创建Object实例方式一样，没解决对象类型的问题。于是，构造函数模式出现了。</p>
<p>二、构造函数模式</p>
<p>Javascript中有一个很重要的概念：函数是对象，函数名实际上是一个函数对象指针。创建算自定义函数，从而添加自定义的属性方法。改写前面的代码：</p>
<pre class="brush:js">
function Person(name, age, job){
	this.name = name;
	this.age = age;
	this.job = job;
	this.sayName = function(){
		alert(this.name);
	};
}

var person1 = new Person('Jim', 30, 'IT');
var person2 = new Person('Tom', 27, 'Doctor');
alert(person1 instanceof Person); //true</pre>
<p>创建自定义函数意味着可以将函数名作为自定义对象类型，这也是构造函数模式优越于工厂模式之处。然而这种模式也缺点。因为函数是对象，因此自定义函数是的方法也应该是对象，对象属于引用类型，因此：</p>
<pre class="brush:js">
alert(person1.sayName == person2.sayName); //false</pre>
<p>我们在一个构造函数中用两个方法去完成相同的任务，显然会带来内存的额外开销。</p>
<p>三、原型模式</p>
<p>为了共享自定义对象的属性方法，引入了原型模式。看下面的代码：</p>
<pre class="brush:js">
function Person(){
}
Person.prototype = {
	constructor: Person,
	name : 'Jim',
	age : 30,
	job : 'IT',
	friends : ['Kite'],
	sayName : function () {
		alert(this.name);
	}
};
var person1 = new Person();
person1.sayName(); // Jim
var person2 = new Person();
person2.name = 'Tom';
person2.sayName(); // Tom
person1.friends.push('Mike');
alert(person1.friends); // Kite,Mike
alert(person2.friends); // Kite,Mike
alert(person1.friends === person2.friends); //true</pre>
<p>原型模式是所有的属性方法都是共享的，与其它语言中的静态类相似。虽然解决了原型模式中对象方法的重复使用问题，但如果属性是引用类型就有问题了。Person.prototype对象中有一个名为friends属性，该属性包含一个字符串数组。然后新建了两个Person实例，接着向person1.friends属性引用的数组新增了一个字符串。由于friends数组存在于Person.prototype而非person1中，所以对person1的修改也会在person2中反映出来。因此实际应用中很少单独用这种方法。</p>
<p>四、构造函数/原型混合模式</p>
<p>创建自定义Javascript类型的最常见方式就是构造函数/原型混合模式，构造函数用于定义非共享的属性，原型模式用来定义方法和共享的属性。取两者之长，发挥各自优势。下面重写了前面的代码：</p>
<pre class="brush:js">
function Person(name, age, job){
	this.name = name;
	this.age = age;
	this.job = job;
	this.friends = ['Kite'];
}
Person.prototype = {
	constructor: Person,
	sayName : function () {
		alert(this.name);
	}
};
var person1 = new Person('Jim', 30, 'IT');
var person2 = new Person('Tom', 27, 'Doctor');
person1.friends.push('Mike');
alert(person1.friends); // Kite,Mike
alert(person2.friends); // Kite
alert(person1.friends === person2.friends); //false
alert(person1.sayName === person2.sayName); //true</pre>
<p>这种混合模式目前也是ECMAScript中使用最广、认同度最高的自定义Javascript类型的方法。</p>]]></summary>
        <link rel="alternate" type="text/html" href="http://www.riafan.com/article/ajax/customize-type-with-javascript.html" /> 
        <id>http://www.riafan.com/default.asp?id=255</id>
    </entry>
    <entry>
        <title type="html"><![CDATA[阻止SQL Server错误日志不断增多]]></title>
        <author>
             <name>Flying</name>
             <uri>http://www.riafan.com/</uri>
             <email>riafan@163.com</email>
        </author>
        <category term="" scheme="http://www.riafan.com/default.asp?cateID=9" label="Backend" /> 
        <updated>2011-09-19T14:31:21+08:00</updated>
        <published>2011-09-19T14:31:21+08:00</published>
        <summary type="html"><![CDATA[<p>最近遇到一个头痛有问题，SQL Server数据库被人恶意攻击，错误日志不断增多，把C盘空间填满了。打开日志文件，有无数条类似的错误信息：错误: 18456， 严重性: 14，状态: 5。Login failed for user 'sa'。[客户端: IP地址]。</p>
<p>试了很多方法，打SP3补丁，新建用户访问，采用Windows身份验证，错误日志还是不断增多。上网Google有人说用防火墙封IP，可是IP不是固定的，根本封不了。</p>
<p>不过这启发了我，我想是不是可以通过SQL Server来限制IP呢？打开配置工具〉SQL Server配置管理器〉MSSQLSERVER的协议〉TCP/IP地址〉IP地址，在IPAll中将TCP动态端口设置为空。Ok，整个世界清静了！</p>]]></summary>
        <link rel="alternate" type="text/html" href="http://www.riafan.com/article/backend/stop-error-logs-constantly-growing-on-sqlserver.html" /> 
        <id>http://www.riafan.com/default.asp?id=254</id>
    </entry>
</feed>
