js ip地址转真实地址

新浪,有道,ip138提供了将ip地址转换为真实地址的接口,这个控件的作用就是将这些接口封装起来,实现js将ip地址转换为真实地址。

使用方法很简单,如有html

<div class="query_ip">202.103.22.1</div>

调用如下js

$(".query_ip").getaddress({
    type:"youdao" // 支持youdao|sina|ip138 (有道速度快且准确,新浪快,ip138较慢)
});

则将HTML修改为

<div class="query_ip">202.103.22.1 湖北省十堰市 东风电信</div>

具体JS源码如下

(function(){
    /*
     * 默认配置
     */
    var domainAddressConf = {
        source : {
            "sina":"http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js&ip=",
            "youdao":"http://youliao.sinaapp.com/app/getip.php?callback=?&type=youdao&ip=",
            "ip138":"http://youliao.sinaapp.com/app/getip.php?callback=?&ip="
        },
        type : null,
        charset : "gb2312"
    }
 
    function getAddress( self,conf ){
        var type = conf.type || "youdao",
            ipadress = conf.source[type] + self.text(),
            api = new getAddressApi( type,ipadress );
 
        api.ready(function( data ){
            self.append( data );
        })
 
        return self;
    }
 
    function getAddressApi( type,conf ){
        var root = this;
 
        this.changeData = function( data ){
            this.data = data;
            return this;
        }
 
        return new getAddressApi[type]( root,conf );
    }
 
    /*
     * 获取新浪ip数据
     */
    getAddressApi.sina = function( root,dataUri ){
 
        this.root = root;
 
        $.getScript(dataUri,function(){
            root.changeData(remote_ip_info);
        });
    }
    getAddressApi.sina.prototype = {
        ready: function( fn ){
            var self = this,
                data = self.root.data;
 
            setTimeout(function(){
                if( data ){
                    fn.call(document,"&nbsp;"+data.province+"省"+data.city+"市&nbsp;"+data.desc);
                }else{
                    self.ready(fn);
                }
            },13);
        }
    }
 
    /*
     * 获取搜狐ip数据
     */
    getAddressApi.youdao = function( root,dataUri ){
 
        this.root = root;
 
        $.getJSON( dataUri, function( data ){
            root.changeData(data);
        });
    }
    getAddressApi.youdao.prototype = {
        ready: function( fn ){
            var self = this,
                data = self.root.data;
 
            setTimeout(function(){
                if( data ){
                    fn.call(document,"&nbsp;"+data[0]);
                }else{
                    self.ready(fn);
                }
            },13);
        }
    }
 
    /*
     * 获取ip138数据
     */
    getAddressApi.ip138 = function( root,dataUri ){
        this.root = root;
 
        $.getJSON( dataUri, function( data ){
            root.changeData(data[0].replace("查询结果:",""));
        });
    }
    getAddressApi.ip138.prototype = {
        ready: function( fn ){
            var self = this,
                data = self.root.data;
 
            setTimeout(function(){
                if( data ){
                    fn.call(document,"&nbsp;"+data);
                }else{
                    self.ready(fn);
                }
            },13);
        }
    }
 
    $.fn.getaddress = function(conf) {
 
        // 判断是否已实例化
        if (this.data("domainaddress")) { return this; }
 
        // 配置
        conf = $.extend(true, {}, domainAddressConf, conf);
 
        this.each(function() {
            var el = new getAddress( $(this), conf );
            $(this).data("domainaddress", el);
        });
 
        return conf.api ? el : this;
    }; 
 
})(jQuery);

因为有道和ip138使用的是xml,为解决跨域,增加了一个php做中转,源码如下

	@header("Content-Type: text/html; charset=utf-8");
	$type = $_GET['type'];
	if( $type == "youdao" ){
		$xml_file_content = fopen_url("http://www.youdao.com/smartresult-xml/search.s?type=ip&q=".$_GET['ip']);
 
		$xml = simplexml_load_string( $xml_file_content );
 
		echo $_GET['callback'].'('.json_encode($xml->product->location).')';
 
	}else{
		$xml_file_content = fopen_url("http://wap.ip138.com/ip.asp?ip=".$_GET['ip']);
 
		preg_match_all( "/\<p \>((.|\n)*)\< \/p\>/s",$xml_file_content,$content );
 
		foreach( $content[1] as $result )
		{
			preg_match_all( "/\<b \>((.|\n)*)\< \/b\>/",$result, $location ); 
 
			echo $_GET['callback'].'('.json_encode($location[1]).')';
		}
 
	}
 
	//Curl 获取网址内容
	function fopen_url($url) 
	{ 
		if (function_exists('file_get_contents')) { 
			$file_content = @file_get_contents($url); 
		} elseif (ini_get('allow_url_fopen') && ($file = @fopen($url, 'rb'))){ 
			$i = 0; 
			while (!feof($file) && $i++ < 1000) { 
				$file_content .= strtolower(fread($file, 4096)); 
			} 
			fclose($file); 
		} elseif (function_exists('curl_init')) { 
			$curl_handle = curl_init(); 
			curl_setopt($curl_handle, CURLOPT_URL, $url); 
			curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT,2); 
			curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER,1); 
			curl_setopt($curl_handle, CURLOPT_FAILONERROR,1); 
			curl_setopt($curl_handle, CURLOPT_USERAGENT, 'Trackback Spam Check'); 
			$file_content = curl_exec($curl_handle); 
			curl_close($curl_handle); 
		} else { 
			$file_content = ''; 
		} 
		return $file_content; 
	}

DEMO:http://www.zhangjingwei.com/getIp_0204_addip138_last.zip

原文链接(594 views)|评论 (2)

无限级菜单

随手写了一个,实现不复杂,只支持动态树。

如果要用的话,获取数据哪里做下简单的修改就可以了,这只是一个Demo。

  (function($){
 
	var jtree = {
		treeid : "jquery_tree_resource",
		treeclass : "tree",
		idname : "id",
		classname : "name",
		optionname : "options",
		openclass: "switch_roots_open",
		closeclass: "switch_roots_close",
		treeurl: ""
	}
 
	// constructor
	function tree(root, conf) {
		var self = root,
		cache = "",    // HTML缓存区
		current = null,    // 当前节点对象
		counter = 0;    // 层级计数器
 
		$.extend(self,{
			/*
			 * 初始化Html
			 * 设置固定的格式以及Id、Class
			 */
			init: function(){
				var el = root.append("< \ul>");
				el.attr({
					"id": conf.treeid,
					"class": conf.treeclass
				});
 
				if( !current ){
					current = root.find("ul");
				}
 
				return self;
			},
 
			getTreeHtml: function(){
				var html = "";
 
				/*
				 * 构建菜单
				 */
				$.each(window.now,function( n,o ){
					html += '<li class="tree-node" id="tree_resource_'+o.id+'"><a id="tree_resource_'+o.id+'_a"><span id="tree_resource_'+o.id+'_span">'+o.name+'</span></a><ul id="tree_resource_'+o.id+'_ul" style="display: none;"></ul></li>';
				});
				cache = html;
 
				return self;
 
			},
 
			/*
			 * 插入HTML代码
			 */
			innerTree: function(){
				current.html( cache ).show("fast");
 
				return self;
			},
 
			/*
			 * 显示菜单
			 */
			showTree: function(){
				current.show("fast");
 
				return self;
			},
 
			/*
			 * 关闭菜单
			 */
			hideTree: function(){
				current.hide("normal");
 
				return self;
			},
 
			/*
			 * 绑定点击事件
			 */
			bindTreeEvent: function(){
				var treeNodes = current.find("a");
 
				/*
				 * 实现菜单
				 */
				$.each(treeNodes,function(n,i){
					$(i).bind("click",function(){
						var s = $(this),
						type = s.data("menuType")
						current = s.nextAll("ul");
						if( !type ){
							if( type === undefined ){
								// ---模拟
								window.now = json_02;
								// 加入新节点
								counter++;
								self.getTreeHtml().innerTree().bindTreeEvent();
							}else{
								self.showTree();
							}
							s.data("menuType",true);
						}else{
							s.data("menuType",false);
							self.hideTree();
						}
					});
				})
				return self;
			}
		});
 
		return self;
	}
 
	$.fn.jtree = function(conf) { 
 
		var el = this.data("jtree");
		if (el) {
			return el;
		}
 
		conf = $.extend({}, jtree, conf); 
 
		this.each(function() {
			el = new tree($(this), conf);
			el.init().getTreeHtml().innerTree().bindTreeEvent();
			$(this).data("jtree", el);
		});
 
		return conf.api ? el: this; 
 
	};
 
  })(jQuery);

数据

  var json_01 = [{"id":"1","name":"111"},{"id":"2","name":"222"}];
 
  var json_02 = [{"id":"3","name":"aaaa"},{"id":"4","name":"bbb"}];

原文链接(60 views)|暂无评论(赶紧抢沙发)

运算符的特殊行为

加法运算符:

  • 运算数是NaN、undefined,则结果为NaN
  • Infinity加Infinity,结果为Infinity
  • -Infinity加-Infinity,结果为-Infinity
  • Infinity加-Infinity,结果为NaN

减法运算符:

  • 运算数是NaN、undefined时,结果为NaN
  • Infinity减Infinity,结果为NaN
  • -Infinity减-Infinity,结果为NaN
  • Infinity减-Infinity,结果为Infinity
  • -Infinity减Infinity,结果为-Infinity

乘法运算符:

  • 运算数是NaN,结果为NaN
  • Infinity乘以0,结果为NaN

除法运算符:

  • 运算数是NaN,结果为NaN
  • Infinity除Infinity,结果为NaN
  • 任何数除Infinity,结果为Infinity
  • 0除非无穷大的数(Infinity),结果为是NaN

取模运算符:

  • 运算数是NaN,结果为NaN
  • 除数是0或者被除数是Infinity,结果为NaN
  • Infinity除Infinity,结果为NaN
  • 除数是Infinity,结果为被除数
  • 被除数是0,结果为0

原文链接(34 views)|沙发已被占领(1)

js下的多态

多态性就是多种表现形式,具体来说,可以用”一个对外接口,多个内在实现方法“表示。举一个例子,计算机中的堆栈可以存储各种格式的数据,包括整型,浮点或字符。不管存储的是何种数据,堆栈的算法实现是一样的。针对不同的数据类型,编程人员不必手工选择,只需使用统一接口名,系统可自动选择。 百科链接

我理解了下,js下应该是这样来实现

var Car = function(type){
   return new Car[type]();
}
 
Car.jeep = function(){}
Car.jeep.prototype = {
    showType: function(){
        return "this is jeep";
    }
}
 
Car.bus = function(){}
Car.bus.prototype = {
    showType: function(){
        return "this is bus";
    }
}
 
var jeep = new Car("jeep");
var bus = new Car("bus");
 
jeep.showType(); // this is jeep
 
bus.showType(); // this is bus

不过要是都这么写,可能就累死了,maybe…

原文链接(419 views)|暂无评论(赶紧抢沙发)

jQuery Autocomplete plugin 1.2

修正因网络延迟而导致的显示错误
增加关键词高亮功能
修正了部分代码
使用固定的回调函数

插件代码:

(function($){
	$.tools = $.tools || {version: '1.2'};
	$.tools.suggest = {};
	$.tools.suggest.defaults = {
		url : null,
		params : null,
		delay : 100,
		cache : true,
		formId : '#search_form',
		focus:null
	}
	$.tools.suggest.borderKey = {
		UP: 38,
		DOWN: 40,
		TAB: 9,
		ESC: 27,
		ENTER:13
	}
 
	$.fn.suggest=function(options,fn){
		var options,key = $.tools.suggest.borderKey;
		if($.isFunction(options)){
			fn=options;
			options = $.extend({}, $.tools.suggest.defaults, key);
		}else{
			options = $.extend({}, $.tools.suggest.defaults, key, options);
		}
		return this.each(function(){
			var
				self = $(this),
				url = options.url,
				params = options.params,
				searchUrl = null,
				searchtimer = 0,
				delay = options.delay,
				cache = options.cache,
				formobj = $(options.formId),
				focus = options.focus,
				rebox = $('<ul />').attr("id","suggest"),
				htmlLi = null,
				litop = null,
				lileft = null,
				liwth = null,
				tip = false,
				val = null,
				rlen = null,
				UP = options.UP,
				DOWN = options.DOWN,
				TAB = options.TAB,
				ESC = options.ESC,
				ENTER = options.ENTER,
				index = -1,
				choseKey = null,
				backval = null,
				hidden = false,
				locksuggest = false,
				timer = null
			;
 
			/* 初始化 */
			if(focus){
				self.trigger('focus');
			}
 
			/* 初始化绑定事件 */
			self.bind("focus",function(){
				backval = (backval=$.trim(self.val()))==''?null:backval;	/* 触发焦点时初始化backval的值 */
				getQueue();
			})
			.bind("blur",function(){
				clearQueue();
				hideResult();
			})
			.bind("keydown",function(e){
				switch (e.keyCode){
				case UP:
					clearQueue();
					if($('#suggest').css('display') == 'none'){
						reSet();
						return false;
					}
					index--;
					if(index&lt;0){
						index=Math.abs(rlen)-1;
					}
					changeSelect(index);
					e.preventDefault();
					break;
				case DOWN:
					clearQueue();
					if($('#suggest').css('display') == 'none'){
						reSet();
						return false;
					}
					index++;
					if(index>=rlen){
						index=0;
					}
					changeSelect(index);
					e.preventDefault();
					break;
				case TAB:
					clearQueue();
					hideResult();
					break;
				case ESC:
					clearQueue();
					hideResult();
					e.preventDefault();
					break;
				case ENTER:
					clearQueue();
					break;
				default:
					getQueue();
					break;
				}
			});
 
			// 获取关键词
			function getKey(){
				val = $.trim(self.val());
				if(!!val && val!=backval){	/* 关键词不为空且关键词不重复 */
					backval = val;
					if(cache && !!$.tools.suggest[val]){	/* 如不需要缓存结果,设cache为false */
						index = -1;
						rlen = $.tools.suggest[val][1];
						appendSuggest($.tools.suggest[val][0]);
					}else{
					    $.tools.suggest[val] = ["",0];
						searchurl = url+'?'+$.param(params);
						getResult(searchurl);
					}
				}
				if(!!!val && !hidden){
					hideResult();	/* 如果关键词为空并且层没有隐藏则隐藏提示层 */
				}
			}
 
			/* 获取提示数据 */
			function getResult(searchurl){
				$.ajax({
                                    type: "GET",
                                    url: searchurl,
                                    cache: true,
                                    dataType: "jsonp",
                                    jsonpCallback: "$.fn.suggest.suggetCallback"
                                });
			}
 
			/* 插入提示数据 */
			function appendSuggest(result){
				locksuggest = hidden = false;
				/* 如果检索结果为空,隐藏提示层反之则输出 */
				if(!!result){
					if(!tip){
						litop = self.offset().top+self.outerHeight()-1;
						lileft = self.offset().left;
						liwth = self.outerWidth()-2;
						rebox.css({'position':'absolute','top':litop,'left':lileft,'width':liwth}).html(result).appendTo('body').show();
						tip = true;
					}else{
						rebox.html(result).show();
					}
					rebox.find('li').bind('mouseover',function(){
						locksuggest = true;		/* 锁定提示层 */
						index = $(this).index();
						changeSelect(index,false);
					})
					.bind('click',function(){
						changeSelect(index);
						searchSubmit();
					});
					rebox.bind('mouseout',function(){
						locksuggest = false;	/* 解锁提示层 */
					});
				}else{
					rebox.hide();
				}
			}
 
			/* JSONP 回调函数 */
                        $.fn.suggest.suggetCallback = function(tmp){
				var data = tmp,
			        htmltemp = '',
				htmllen = data.total,
				inputWord = data.kw;
 
				if(htmllen > 0){
				    $.each(data.list,function(i,n){
					    if(n.word != inputWord){
						    htmltemp += '<li data-value="'+n.word+'">'+n.word+'</li>';
					    }
				    });
				    htmltemp = htmltemp.toLocaleLowerCase();
				    var regex = eval("/\>"+inputWord+"/g"); 
				    htmltemp = htmltemp.replace(regex,"><b>"+inputWord+"</b>");
				    $.tools.suggest[inputWord]=[htmltemp,htmllen];
				}
 
				if(self.val() == inputWord){
				    rlen = htmllen;
				    index = -1;
				    appendSuggest(htmltemp);
				}
 
			}
 
			/* 创建队列 */
			function getQueue(){
				var n = $(document).queue("suggest");
				if(n.length < 1){
					$(document).queue("suggest",getQueue);
					getKey();
					timer = setTimeout((function(){
						$(document).dequeue("suggest");
					}),delay);
				}
			}
 
			/* 清除队列 */
			function clearQueue(){
				$(document).clearQueue("suggest");
				clearTimeout(timer);
			}
 
			/* 变更选项 */
			function changeSelect(index,v){
				v=v==false?false:true;
				var obj = rebox.find('li').eq(index);
				rebox.find('li.mo').removeClass('mo');
				obj.addClass("mo");
				if(v){
					choseKey = backval = obj.attr("data-value");
					self.val(choseKey);
				}
			}
 
			/* 重置层 */
			function reSet(){
				if(!!self.val()){
					index = -1;
					$('#suggest').css('display','block');
					rebox.find('li.mo').removeClass('mo');
					rlen = rebox.find('li').size();		/* 根据html结构重新计算提示结果长度 */
				}
			}
 
			/* 隐藏结果层 */
			function hideResult(){
				if(!locksuggest){
					choseKey = backval = null;
					hidden = true;
					rebox.hide();
				}
			}
 
			/*  提交表单 */
			function searchSubmit(){
				self.val(choseKey);
				clearQueue();
				hideResult();
				formobj.submit();
			}
 
		});
	}
})(jQuery);

返回数据格式

$.fn.suggest.suggetCallback({"total":2,"list":[{"id":"8926","word":"ZAMA\u00b7\u54b1\u4eec"},{"id":"44723","word":"ZOBON"}],"kw":"z"})

原文链接(236 views)|评论 (3)