Skip to content

{ Tag Archives } Javascript

JavaScript 全半角转换

规律:半角空格的 charCode 为 32, 全角空格为 12288. 其他半角字符 ( 33 – 126 ) 与全角 ( 65281 – 65374 ) 的对应关系是:均相差 65248.

找好规律,代码就好写了:

var hash = {'32' : '\u3000'};
// 半角转全角
function sbc2dbc(str) {
    var ret = [], i = 0, len = str.length, code, chr;
    for (; i< len; ++i) {
        code = str.charCodeAt(i);
        chr = hash[code];
        if (!chr && code > 31 && code< 127) {
           chr = hash[code] = String.fromCharCode(code + 65248);
        }
        ret[i] = chr ? chr : str.charAt(i);
    }
    return ret.join('');
}

同理:

var hash = {'12288' : ' '};
// 全角转半角
function dbc2sbc(str) {
    var ret = [], i = 0, len = str.length, code, chr;
    for (; i< len; ++i) {
        code = str.charCodeAt(i);
        chr = hash[code];
        if (!chr && code > 65280 && code< 65375) {
            chr = hash[code] = String.fromCharCode(code - 65248);
        }
        ret[i] = chr ? chr : str.charAt(i);
    }
    return ret.join('');
}

上面的代码会将 33 - 126 中间的符号也转换。很多时候,这并不是我们需要的(比如将 @ 转换为 @)。下面的代码侵入性更小:

var hash = {};
// 半角转全角。仅转换 [0-9a-zA-Z]
function sbc2dbc_w(str) {
    var ret = [], i = 0, len = str.length, code, chr;
    for (; i< len; ++i) {
        code = str.charCodeAt(i);
        chr = hash[code];
        if (!chr &&
            (47< code && code< 58 ||
             64< code && code< 91 ||
             96< code && code< 123)) {
            chr = hash[code] = String.fromCharCode(code + 65248);
        }
        ret[i] = chr ? chr : str.charAt(i);
    }
    return ret.join('');
}
Also tagged

得到月份天数

32 - new Date(year, month, 32).getDate();
Also tagged

Closure Tools:Google的javascript库

FROM: Google的javascript库

Google 开发了那么多 web application, 由于 web 浏览器和 web 标准的差异性, 势必需要一套库来解放 Google 的这些程序天才, 让他们从无聊的底层代码解脱出来, 关注算法, 关注应用程序逻辑.

之前, Google 说也在用 YUI 和 ext js 等 Javascript 库, 但去看看它的程序代码就会疑惑, 几乎没有任何痕迹显示在用这些库. 当然, Google 也有一套工具:GWT. 用java代码来编写 web applicationi, 完全无视浏览器的存在, 但是显而易见的就是, 既然代码全是java代码转换而来, 肯定少不了也写包裹性质的代码, 性能必然有不小的折扣, 而且随着应用的扩大, 这个折扣也是直线上升的, 更重要的是, 数据被藏了起来, 我想任何希望自己数据被搜索引擎索引的开发者, 都是不能接受的. 所以, 除了做企业应用的开发商, 不会有多少人感兴趣. 至今, 我只看到 Google profile 在用GWT. 种种迹象表明, Google 内部一定有套大而全的 Javascript 库.

今天, Google 说出了这个秘密:Closure Tools. 由三个部分组成, 其中的 Closure Library 从概念上来说, 是一个和 YUI 和 ext js 可比较的, 大而全的 Javascript 库. 谷歌做了个比喻, 说这个库类似于 c++ 的 STL, 由于它还有 UI 的 widget, 我想至少还要加上类似微软 MFC/WTL 的作用. 可见这个库在 Google 内部是非常重要, 和被广泛采用的. 它的功能非常广泛, 整个的结构是按需消费的, 除了 base.js 以外, 其它组件都是可选, 具体的组件列表 在这里, 一些 demo 在这里. 使用上第一感觉就是, 非常的踏实, 该有的都有, 使用虽然不像 jQuery 那样精炼, 但也非常合理和简洁. 比 jQuery 好的就是不要去满地儿找插件, 我的预测是 YUI 将进一步边缘化, ext js 很难会有新用户了. 而 jQuery 由于其 lightweight 的特点, 应该能和 Closure Library 并存.

Colsure Tools 的其它两个部件分别是一个 Javascript 的优化器:Closure Compiler, 和一个 Javascript 的Template系统:Closure Templates. 这个 Javascript 的优化器不是简单的javascipt minimal的工具, 它会深入分析你的 Javascript 代码, 从而产生更精炼, 效率更高的代码. 比如如果有个变量没用到, 优化器会删掉它.

另一个是一个 Javascript 的 Template 系统, 我觉得更像是一个DSL(Domain-specific language). 它的目的是把数据表示成这个 DSL, 通过它再去生成HTML. 我们知道HTML本身就是表示数据的 DSL, XML 也是, 由于浏览器和 DocType 的差异性, 表示成 HTML 有点不够保险, 但是我们还有 JSON, 对 web 来说, 这可能是最高效的 DSL了, 再造一门 DSL, 有多大的必要性, 值得商榷, 何况这个 Google 的这个 DSL, 特点并不明显.

Also tagged

IE6下设置透明背景函数

function correctPNG() {
  for(var i = 0; i < document.images.length; i++) {
      var img = document.images[i]
      var imgName = img.src.toUpperCase()
      if (imgName.substring(imgName.length-3, imgName.length) == "PNG"){
          var imgID = (img.id) ? "id='" + img.id + "' " : ""
          var imgClass = (img.className) ? "class='" + img.className + "' " : ""
          var imgTitle = (img.title) ? "title='" + img.title + "' " : "title='" + img.alt + "' "
          var imgStyle = "display:inline-block;" + img.style.cssText
          if (img.align == "left") imgStyle = "float:left;" + imgStyle
          if (img.align == "right") imgStyle = "float:right;" + imgStyle
          if (img.parentElement.href) imgStyle = "cursor:hand;" + imgStyle
          var strNewHTML = "&lt;span " + imgID + imgClass + imgTitle
          + " style=\"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";"
          + "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"
          + "(src=\'" + img.src + "\', sizingMethod='scale');\"&gt;&lt;/span&gt;"
          img.outerHTML = strNewHTML
          i = i-1
      }
  }
}
Also tagged

RGB 转化为十六进制

function zero_fill_hex(num, digits) {
  var s = num.toString(16);
  while (s.length < digits)
    s = "0" + s;
  return s;
}

function rgb2hex(rgb) {

  if (rgb.charAt(0) == '#')
    return rgb;
  var n = Number(rgb);
  var ds = rgb.split(/\D+/);
  var decimal = Number(ds[1]) * 65536 + Number(ds[2]) * 256 + Number(ds[3]);
  return "#" + zero_fill_hex(decimal, 6);
}
rgb2hex('rgb(255, 255, 255)');
Also tagged

颜色拾取器

<!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=gb2312" />
<title>颜色选择器</title>
<style type="text/css">
body{
  text-align:center;
}
</style>
</head>
<body>
<p>
<script type="text/javascript" language="javascript">
<!--
var ColorHex = Array('00','33','66','99','CC','FF')
var SpColorHex = new Array('FF0000','00FF00','0000FF','FFFF00','00FFFF','FF00FF')
var current = null;
var select_opener = '';
function initcolor(evt) {
  var colorTable=''
  for (i=0;i<2;i++) {
    for (j=0;j<6;j++) {
      colorTable=colorTable+'<tr height=15>'
      colorTable=colorTable+'<td width=15 style="background-color:#000000">'
      if (i==0){
        colorTable=colorTable+'<td width=15 style="cursor:pointer;background-color:#'+ColorHex[j]+ColorHex[j]+ColorHex[j]+'" onclick="doclick(this.style.backgroundColor)">'}
      else{
        colorTable=colorTable+'<td width=15 style="cursor:pointer;background-color:#'+SpColorHex[j]+'" onclick="doclick(this.style.backgroundColor)">'}
      colorTable=colorTable+'<td width=15 style="background-color:#000000">'
      for (k=0;k<3;k++) {
        for (l=0;l<6;l++) {
          colorTable=colorTable+'<td width=15 style="cursor:pointer;background-color:#'+ColorHex[k+i*3]+ColorHex[l]+ColorHex[j]+'" onclick="doclick(this.style.backgroundColor)">'
        }
      }
    }
  }
  colorTable='<table border="0" cellspacing="0" cellpadding="0" style="border:1px #000000 solid;border-bottom:none;border-collapse: collapse;width:337px;" bordercolor="000000">'
  +'<tr height=20><td colspan=21 bgcolor=#ffffff style="font:12px tahoma;padding-left:2px;">'
  +'<span style="float:left;color:#999999;"></span>'
  +'<span style="float:right;padding-right:3px;cursor:pointer;" onclick="colorclose()">×关闭</span>'
  +'</td></table>'
  +'<table border="1" cellspacing="0" cellpadding="0" style="border-collapse: collapse" bordercolor="000000" style="cursor:pointer;">'
  +colorTable+'</table>';
  document.getElementById("colorpane").innerHTML=colorTable;
  var current_x = document.getElementById(select_opener).offsetLeft;
  var current_y = document.getElementById(select_opener).offsetTop;

  document.getElementById("colorpane").style.left = current_x + "px";
  document.getElementById("colorpane").style.top = current_y + "px";
}
function doclick(obj){
  document.getElementById(select_opener).value = rgb2hex(obj);
  colorclose();
}
function colorclose(){
  document.getElementById("colorpane").style.display = "none";
}
function coloropen(event, opener){
  document.getElementById("colorpane").style.display = "";
  select_opener = opener;
}

//转到固定长度的十六进制字符串,不够则补0
function zero_fill_hex(num, digits) {
  var s = num.toString(16);
  while (s.length < digits)
    s = "0" + s;
  return s;
}

function rgb2hex(rgb) {

  if (rgb.charAt(0) == '#')
    return rgb;
  var n = Number(rgb);
  var ds = rgb.split(/\D+/);
  var decimal = Number(ds[1]) * 65536 + Number(ds[2]) * 256 + Number(ds[3]);
  return "#" + zero_fill_hex(decimal, 6);
}
window.onload = initcolor;
</script>
</p>
<p> </p>
<p> </p>
<p> </p>
<p>
<input type="text" value="颜色选择" onclick="coloropen(event, 'inputcolor')" id="inputcolor" />
</p>
<p> </p>
<div id="colorpane" style="position:absolute;z-index:999;display:none;"></div>
</body>
</html>
Also tagged

hoverIntent 鼠标事件插件

hoverIntent jQuery Plugin

Also tagged ,

Mouse Event

鼠标事件,总是难以处理。mouseover, mouseout在 FF 下跑还比较正常,在 IE 下就像是患了抽搐症,根本就无法控制。

看了如下的文章,终其原因是 Javascript 的冒泡事件。
还是摘抄了过来~

TopExampleMousedown, mouseup, clickDblclickMousemoveMouseover and mouseoutrelatedTarget, fromElement, toElementCross–browser scriptsMousing out of a layerMouseenter and mouseleaveEnd

We’ll go through all mouse events: mousedown, mouseup and click, dblclick, mousemove and finally mouseover and mouseout. Then I explain the relatedTarget, fromElement and toElement event properties. Finally the Microsoft proprietary mouseenter and mouseleave events.

For browser compatibility, see the Event Compatibility Tables page.

Example

Here’s a small example. Try it to better understand the explanations below.
Mousedown, mouseup, click and dblclick are registered to the link. You’ll see the events that take place in the textarea, or in an alert, if you so choose.

The event handlers are registered on this link.
Clear textarea.

Show alert instead of writing to textarea

Mousedown, mouseup, click

If the user clicks on an element no less than three mouse events fire, in this order:

   1. mousedown, user depresses the mouse button on this element
   2. mouseup, user releases the mouse button on this element
   3. click, one mousedown and one mouseup detected on this element

In general mousedown and mouseup are more useful than click. Some browsers don’t allow you to read out mouse button information onclick. Furthermore, sometimes the user does something with his mouse but no click event follows.

Suppose the user depresses the mouse button on a link, then moves his mouse off the link and then releases the mouse button. Now the link only registers a mousedown event. Similarly, if the user depresses the mouse button, then moves the mouse over a link and then releases the mouse button, the link only registers a mouseup. In neither case does a click event fire.

Whether or not this is a problem depends on the user interaction you want. But you should generally register your script onmousedown/up, unless you’re completely sure you want the click event and nothing else.

If you use alerts in handling these events, the browser may lose track of which event took place on which element and how many times it took place, messing up your scripts. So it’s best not to use alerts.

Dblclick

The dblclick event is rarely used. Even when you use it, you should be sure never to register both an onclick and an ondblclick event handler on the same HTML element. Finding out what the user has actually done is nearly impossible if you register both.

After all, when the user double–clicks on an element one click event takes place before the dblclick. Besides, in Netscape the second click event is also separately handled before the dblclick. Finally, alerts are dangerous here, too.

So keep your clicks and dblclicks well separated to avoid complications.

Mousemove

The mousemove event works fine, but you should be aware that it may take quite some system time to process all mousemove events. If the user moves the mouse one pixel, the mousemove event fires. Even when nothing actually happens, long and complicated functions take time and this may affect the usability of the site: everything goes very slowly, especially on old computers.

Therefore it’s best to register an onmousemove event handler only when you need it and to remove it as soon as it’s not needed any more:

element.onmousemove = doSomething;
// later
element.onmousemove = null;
Mouseover and mouseout

Take another look at the example, switch the mouseovers on and try them. The example adds an onmouseover event handler to ev3 only. However, you’ll notice that a mouseover event takes place not only when the mouse enters ev3′s area, but also when it enters the area of ev4 or the span. In Mozilla before 1.3, the event even fires when the mouse enters the area of a text!

The reason for this is of course event bubbling. The user causes a mouseover event on ev4. There is no onmouseover event handler on this element, but there is one on ev3. As soon as the event has bubbled up to this element, the event handler is executed.

Now this setup, though completely correct, gives us some problems. Our first problem is targeting. Suppose the mouse enters ev4:

-----------------------------------------
| This is div id="ev3"                  |
|   -----------------------------       |
|   | This is div id="ev4"      |       |
|   | --------              <--------   |
|   | | span |                  |       |
|   | |      |                  |       |
|   | --------                  |       |
|   -----------------------------       |
-----------------------------------------

<--------: mouse movement

Now the target/srcElement of this event is ev4: it’s the element the event took place on, since the user mouses over it. But when this happens:

-----------------------------------------
| This is div id="ev3"                  |
|   -----------------------------       |
|   | This is div id="ev4"      |       |
|   | --------                  |       |
|   | | span |                  |       |
|   | |    -------->            |       |
|   | --------                  |       |
|   -----------------------------       |
-----------------------------------------

-------->: mouse movement

the event has exactly the same target/srcElement. Here, too, the mouse enters ev4. Nonetheless you might want do one thing when the mouse comes from ev3 and another thing when it comes from the SPAN. So we need to know where the mouse comes from.

relatedTarget, fromElement, toElement

W3C added the relatedTarget property to mouseover and mouseout events. This contains the element the mouse came from in case of mouseover, or the element it goes to in case of mouseout.

Microsoft created two properties to contain this information:

  • fromElement refers to the element the mouse comes from. This is interesting to know in case of mouseover.
  • toElement refers to the element the mouse goes to. This is interesting to know in case of mouseout.

In our first example, relatedTarget/fromElement contains a reference to ev3, in our second example to the SPAN. Now you know where the mouse came from.

Cross–browser scripts

So if you want to know where the mouse comes from in case of mouseover, do:

function doSomething(e) {
	if (!e) var e = window.event;
	var relTarg = e.relatedTarget || e.fromElement;
}

If you want to know where the mouse goes to in case of mouseout, do:

function doSomething(e) {
	if (!e) var e = window.event;
	var relTarg = e.relatedTarget || e.toElement;
}
Mousing out of a layer

In a layer-based navigation you may need to know when the mouse leaves a layer so that it can be closed. Therefore you register an onmouseout event handler to the layer. However, event bubbling causes this event handler to fire when the mouse leaves any element inside the layer, too.

--------------
| Layer      |.onmouseout = doSomething;
| --------   |
| | Link | ----> We want to know about this mouseout
| |      |   |
| --------   |
| --------   |
| | Link |   |
| |    ----> | but not about this one
| --------   |
--------------
---->: mouse movement

Another show stopper is that when you move the mouse into the layer, and then onto a link, browsers register a mouseout event on the layer! It doesn't make much sense to me (the mouse is still in the layer), but all browsers agree on this one.

So how do we reject any mouseout that does not take place when the mouse actually leaves the layer?

function doSomething(e) {
	if (!e) var e = window.event;
	var tg = (window.event) ? e.srcElement : e.target;
	if (tg.nodeName != 'DIV') return;
	var reltg = (e.relatedTarget) ? e.relatedTarget : e.toElement;
	while (reltg != tg && reltg.nodeName != 'BODY')
		reltg= reltg.parentNode
	if (reltg== tg) return;
	// Mouseout took place when mouse actually left layer
	// Handle event
}

First get the event target, ie. the element the mouse moved out of. If the target is not the DIV (layer), end the function immediately, since the mouse has certainly not left the layer.

If the target is the layer, we're still not sure if the mouse left the layer or entered a link within the layer. Therefore we're going to check the relatedTarget/toElement of the event, ie. the element the mouse moved to.

We read out this element, and then we're going to move upwards through the DOM tree until we either encounter the target of the event (ie. the DIV), or the body element.

If we encounter the target the mouse moves towards a child element of the layer, so the mouse has not actually left the layer. We stop the function.

When the function has survived all these checks we're certain that the mouse has actually left the layer and we can take appropriate action (usually making the layer invisible).
Mouseenter and mouseleave

Microsoft has another solution. It has created two new events mouseenter and mouseleave. They are almost the same as mouseover and mouseout except that they don’t react to event bubbling. Therefore they see the entire HTML element they’re registered to as one solid block and don’t react to mouseovers and –outs taking place inside the block.

So using these events solves our problem too: they react only to mouseovers/outs on the element they’re registered to.

At the moment these events are only supported by Explorer 5.5 on Windows and higher. Maybe the other browser vendors will copy these events.

看完,用上上面所说的。结果还是不令人满意。
后面,还是找了jQuery 的一个插件,才算是基本解决问题。

Also tagged

有趣的浏览器地址栏Javascript代码

FROM: http://www.kenengba.com/post/483.html/trackback

1 编辑网页

在地址栏输入下面的代码按 enter, 网页上所有元素都能变成可编辑状态, 你可以移动, 调整元素大小. 如果你只是讨厌某个网站想发泄一下, 我建议你使用 NetDisater.

    javascript:document.body.contentEditable='true'; document.designMode='on'; void 0

2 无敌风火轮

在地址栏运行下面的代码可使页面上所有图片元素一个接一个地转圈.

这种效果最好的实现地方就是图片搜索了, 改变代码里的 img 成任何网页上有的字符, 可以使这些字符做无敌风火轮运动.

    javascript:R=0; x1=.1; y1=.05; x2=.25; y2=.24; x3=1.6; y3=.24; x4=300; y4=200; x5=300; y5=200; DI=document.getElementsByTagName("img"); DIL=DI.length; function A(){for(i=0; i-DIL; i++){DIS=DI[ i ].style; DIS.position='absolute'; DIS.left=(Math.sin(R*x1+i*x2+x3)*x4+x5)+"px"; DIS.top=(Math.cos(R*y1+i*y2+y3)*y4+y5)+"px"}R++}setInterval('A()',5); void(0);

3 晃来晃去

不但是你, 浏览器也不是那么喜欢这个 Javascript. 在地址栏运行这个代码后, 浏览器会迅速地晃来晃去.


    javascript:function flood(n) {if (self.moveBy) {for (i = 200; i &gt; 0;i--){for (j = n; j &gt; 0; j--) {self.moveBy(1,i); self.moveBy(i,0);self.moveBy(0,-i); self.moveBy(-i,0); } } }}flood(6);{ var inp = "D-X !msagro na dah tsuj resworb rouY"; var outp = ""; for (i = 0; i &lt;= inp.length; i++) {outp =inp.charAt (i) + outp ; } alert(outp) ;}; reverse

4 计算器

在地址栏输入下面的代码, 可以实现简单的四则运算:

     javascript: alert(34343+3434-222);

5 防钓鱼验证

某些钓鱼网站提供的 URL 和网页本身的 URL 是不一致的, 可以用下面的代码进行验证, 当两个 URL 相差太大的时候, 就要稍加小心了:

    javascript:alert("The actual URL is:tt" + location.protocol + "//" + location.hostname + "/" + "nThe address URL is:tt" + location.href + "n" + "nIf the server names do not match, this may be a spoof.");
Also tagged

复制到剪切板

web 开发中常常要实现 “复制到剪切板” 功能。这个功能很实用,但是由于安全问题,浏览器的限制越来越严,实现的方法也越来越有限了。Firefox 默认下不能直接通过 Javascript 操作剪切板,必须开启相关的设置才行。想只通过 Javascript 技术实现跨浏览器 的剪切板是行不通的。现在常用的方法是利用 JavaScript+Flash实现,普遍流传的办法是 _clipboard.swf,这是国外最早实现的(著名的 Clipboard Copy 解决方案: http://www.jeffothy.com/weblog/clipboard-copy/)。但是很可惜,_clipboard.swf 在新出来的 flash10 中无效,因为 Flash10 中规定了只有在 swf 上进行了实际的操作(比如鼠标点击)才能启动剪切板。而 _clipboard.swf 方法的 swf 是隐藏的,通过 JavaScript 来操作 flash 的剪切板,显然没有对 swf 进行实际的用户操作。

function copy(v_str , tip_obj) {
	copy_clip(v_str);
}

function copy_clip(text2copy) {
	if (window.clipboardData) {
		window.clipboardData.setData("Text", text2copy);
	} else {
		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 = '<embed src="/img/_clipboard.swf" FlashVars="clipboard='+escape(text2copy)+'" width="0" height="0" type="application/x-shockwave-flash"></embed>';
		document.getElementById(flashcopier).innerHTML = divinfo;
	}
	return true;
}

function copyToClipboard(txt) {
	if (window.clipboardData) {
		window.clipboardData.clearData();
		window.clipboardData.setData("Text", txt);
	}	else if (navigator.userAgent.indexOf("Opera") != -1) {
		window.location = txt;
	}	else if (window.netscape)	{
		try {
			netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
		}	catch (e)	{
			alert("您的firefox安全限制限制您进行剪贴板操作,请打开'about:config'将signed.applets.codebase_principal_support'设置为true'之后重试");
			return false;
		}
		var clip = Components.classes['@mozilla.org/widget/clipboard;1'].createInstance(Components.interfaces.nsIClipboard);
		if (!clip)
			return false;
		var trans = Components.classes['@mozilla.org/widget/transferable;1'].createInstance(Components.interfaces.nsITransferable);
		if (!trans)
			return false;
		trans.addDataFlavor('text/unicode');
		var str = new Object();
		var len = new Object();
		var str = Components.classes['@mozilla.org/supports-string;1'].createInstance(Components.interfaces.nsISupportsString);
		var copytext = txt;
		str.data = copytext;
		trans.setTransferData("text/unicode",str,copytext.length*2);
		var clipid = Components.interfaces.nsIClipboard;
		if (!clip)
			return false;
		clip.setData(trans,null,clipid.kGlobalClipboard);
	}
	return true;
}

最近国外出现了一种新的方法,而且专门做了一个 JavaScript 库 Zero Clipboard ,它包含一个 flash 影片和一个 JavaScript 接口,这个 flash 是透明的(不是隐藏),用户不会察觉到它的存在。这个 flash 覆盖在一个 DOM元素上,比如 button,div之类,当点击这个 DOM 时,你实际点击的是这个 flash,这个作用在 flash 上的动作能够开启 flash 的剪切板。这实际上就是一种 clickjacking。

DEMO页面 : http://bowser.macminicolo.net/~jhuckaby/zeroclipboard/

Zero Clipboard项目主页: http://code.google.com/p/zeroclipboard/

Also tagged