Simple上网导航--静态版
现在的网址导航显然是一个针对小白用户的网页大全,新闻、笑话、视频、黄段子要什么有什么,一个网址导航竟然也要滑动好多页。其实80%的功能我都用不到,但是它们却时刻展现在我的眼前。所以我决定做一个简洁清晰的网址导航,我的目标是牺牲20%的功能,提升80%的体验。本来是想给自己用的,用了一段时间感觉还不错,再让我回头用hao123会觉得特不清晰,干脆直接挂出来吧,反正也花不了几个钱,说不准还会有人喜欢。先看东西吧:Simple 最简洁的上网导航。可以随意拖动网址排序,删除或添加网址。Simple面向的用户是追求简洁实用的小众群体,并不针对小白用户,我觉得可能白领居多,不知是否合您的口味。跟大家简单分享一下纯静态版的实现,以及我的一些想法,本菜并不擅长做前端,如果出现低级错误,可不要贱笑啊。代码与最新的代码可能有所差别,可以直接查看源代码,注释比较详细。
一. 页面布局
<!doctype html>//省略了若干js,css引用,省略了不重要的页面元素 <html lang="zh"> <head> <meta charset="utf-8"> <title>Simple 最简洁的上网导航</title> <link rel="shortcut icon" type="image/ico" href="img/favicon.ico" /> </head> <body> <div> <div id="head"> <a href="#" onclick="showAbout()">帮助</a> <a href="#" onclick="reset()">重置</a> </div> <div id="logo">Simple</div> <div id="trashContainer"> <img id="trash" src="img/trash.png"/><img id="trash_tip" src="img/trash_tip.png" style="display:none"/> </div> <div id="searchContainer"> <form id="searchForm" action="http://www.baidu.com/s" target="_blank"> <input id="search" type="text" name="wd" baiduSug="2" /> </form> </div> <div style="margin-top: 50px"> <ul id="sortable"> <li no="1"><a href="http://www.baidu.com" target="_blank" style="background: url(img/defaultIcon.png) no-repeat 0px 0px">百 度</a></li>
<!--省略无数网址--> </ul> </div> </div> <div id="about"> <ol> <li>按空格键,可将焦点置于搜索框内; 按 Ctrl+<- 键,可清空搜索框</li>
<li>默认搜索为百度,关键词前空一格则使用google搜索</li> <li>网址可拖动调换位置并随意删除</li> <li>点击重置可恢复到最最原始的页面</li> <li>看在我们连logo都省了的份上,推荐给身边的朋友吧</li> </ol> <a style="float: right; text-decoration: none;" href="#" onclick="$('#about').hide('fast');">关闭</a> </div> </body> <script charset="gbk" src="http://www.baidu.com/js/opensug.js"></script> </html>
先说说功能系数,功能系数是指模块功能所占整个页面功能的百分比。我要使页面布局符合每个模块的功能系数。也就是说某模块的功能系数越高,那么它的位置就越显眼,在用户视野范围内的时间就越长。
页面主要是三个部分:Logo文字、搜索框、网址列表。其中Logo文字以显示一秒随后隐藏的方式来展现,我觉得以这种方式来展现Logo显得页面不那么呆板,最终隐藏掉Logo显得整个页面又不乏稳重,同时还保持了页面的简洁。最有用的当然是搜索框和下边的网址导航了,搜索框没有搜索按钮,因为我觉得搜索按钮的功能系数也是非常的低,Simple针对的用户不是小白用户,所以直接省略掉搜索按钮。网址列表仍然没有达到我理想的效果,后续还会慢慢改善。如何保持网站列表清晰又不花哨是一个值得探讨的问题,相信会有一个比较好的方案。
还有一个删除网址的垃圾桶,Simple没有在周围添加一个设置图标按钮,点击后在网址边上显示删除符号。而是直接在拖动的过程中,显示垃圾桶提示用户可以删除,保持了页面的简洁。
帮助、重置、添加是这里最不常用的功能,所以让它靠在了右上方不起眼的地方,以与它们的功能系数匹配。
二. 搜索框功能
点开帮助看一下,会看到有几个关于搜索框的功能点。js库使用的是jquery和jquery.cookie。
平时用搜索的时候有两点稍有不便,一个是焦点问题。我们的页面加载完成就将焦点放在了搜索框中,直接输入即可。另外按下空格键就可以将焦点放到搜索框中,如果按了空格键并且搜索框没有焦点,则使它获得焦点。这里采用的是keyup事件,如果用keydown事件的话,等文本框获得焦点之后,空格字符仍然会输入到文本框中。
$(document).keyup(function(e) { if (e.keyCode == 32 && document.activeElement.id != "search") { $("#search").focus(); } });
另一个是删除关键字问题,如果想删除关键字直接按ctrl+backspace即可,比ctrl+a再删除还方便,整个过程不需要鼠标的参与。是不是很爽啊,什么?你还是习惯咔咔咔咔摁删除?哎,习惯问题,我刚开始也是咔咔咔咔摁删除,但这是无意识的操作,如果有意识地用几次ctrl+backspace就会觉得由衷的爽。代码如下:
$("#search").keydown( function(e) { if (e.ctrlKey == 1 && e.keyCode == 8) { $("#search").val(""); } });
默认情况下按回车键调用百度搜索,搜索内容前置一个空格将调用google搜索,最近封网越加严重,google基本上不了了,裆中央看来是不想让同志们愉快地玩耍了。看代码吧,当看到有空格时就改变相应的属性,然后提交表单。这里为什么用表单而不用window.open呢?window.open兼容性有问题,至少在我的手机上点回车是不响应的。
$("#search").keydown( function(e) {if (e.keyCode == 13) { var keyword = $("#search").val(); if (keyword.length > 0 && keyword.charAt(0) == ' ') { $("#searchForm").attr("action","https://www.google.com.hk/search"); $("#search").attr("name","q"); } else { $("#searchForm").attr("action","http://www.baidu.com/s"); $("#search").attr("name","wd"); } $("#searchForm").submit(); return false; } });
当你输入关键字时,会得到提示,这里的提示来自百度,在搜索框上加baiduSug属性,再引入下边的opensug.js即可,baiduSug等于1时,用鼠标点击提示项会自动提交表单,等于2时不会自动提交表单。提示框最下边的“百度搜索框提示”稍微有点别扭,可以把js下载下来将提示删除。我刚开始是这么干的,后来想了想又直接用了原版,万一百度找上门来让我赔钱就麻烦了。
<script charset="gbk" src="http://www.baidu.com/js/opensug.js"></script>
三. Logo显示
logo显示有啥好说的?logo的颜色是会变的奥,不信明天再刷一下看看,我们让logo一周七个颜色,每天都不一样,每天带给大家不一样的心情。代码使logo透明度用一秒的时间从0变到1,停留一秒,再用一秒的时间从1变到0。
function loadLogo() { var colorArray = [ "#45b97c", "green", "violet", "#faa755", "#6950a1", "#4c4c4c", "#ef5b9c" ]; $("#logo").css("color", colorArray[new Date().getDay()]); $("#logo").fadeTo(1000, 1, function() { setTimeout(function() { $("#logo").fadeTo(1000, 0); }, 1000); }); }
四. 网址添加
点击右上角的添加即可弹出网址添加框,输入网址或网站名会有提示,选择并回车即可。网址提示框的实现可以看我的另一篇博客《贡献个网址搜索提示框》,就不再重复介绍了。这里只看一下添加网址的逻辑。先是大概的判断一下输入,校验一下网址,校验逻辑不是很严格。然后将网址名字、网址、编号保存到cookie中,过期时间设为1000天,如果不设的话,默认关闭浏览器cookie就没了。中间省略部分函数的代码,太多了就不贴了,看名字应该知道是什么意思。
function add() { var name = $("#mysite-name-add").val().trim(); var url = $("#mysite-url-add").val().trim(); if (name == '' || url == '') { addtip("添加内容不能为空", "red"); return; } url = url.replace(/^(http|https):\/\//, ''); if (!isURL(url)) { addtip("网址不规范", "red"); return; } if (name.length == 2)//网站名两个字时中间加一个空格 name = name[0] + ' ' + name[1]; var customArray; var custom = $.cookie('custom'); if (custom == undefined) customArray = []; else customArray = $.parseJSON(custom); var currentNo = getCustomMaxNo() + 1; customArray.push({ "name" : name, "url" : url, no : currentNo }); //save to cookie $.cookie('custom', JSON.stringify(customArray), { expires : 1000 }); appendSite(currentNo, name, url);//添加网址 changeOrder();//保存网址顺序 $("#mysite-name-add").val(''); $("#mysite-url-add").val(''); $("#btn-site-back").focus(); addtip(name + " 添加成功", "green"); }
五. 网址拖动
每个人常用的网址都不一样,每个网址的使用频率也不一样,所以我们的网址可以直接拖动变换位置。拖动用到了jquery.ui库的sortable,可以任意拖动对象排序,并设置排序的一系列回调函数,changeOrder就是排序完毕并发生改变时的回调函数。每个网址都有一个编号,当位置变动时,将编号依次纪录到cookie中。
function changeOrder(){ var order=[]; $("#sortable li").each(function(){ order.push($(this).attr("no")); }); $.cookie('order',JSON.stringify(order),{expires:1000}); }
六. 网址删除
网址拖动的过程中,搜索框上方会出现一个垃圾桶的图标,当网址覆盖垃圾桶时,垃圾桶的颜色会变成红色,这时候松开鼠标,网址就被删掉了。这里使用了jquery.ui库的droppable,它允许其他对象拖放到它上面,并提供了一系列的监听事件,例如覆盖、移除、放下等。垃圾桶是使用了两个不同的img,默认显示绿色的隐藏红色的。监听到开始拖放网址时(这个是sortable的事件)显示垃圾桶,网址覆盖到垃圾桶时隐藏绿色img显示红色img。如果松开鼠标直接将网址删除,并隐藏垃圾桶。这里为什么要选取两个img,而不是用一个img,监听到事件改变它的src属性呢?如果这样的话,每次改变src属性,浏览器都会重新请求资源,所以图片切换会跟不上。就算可以解决重新请求资源的问题,第一次改变src还是要请求的,这样会使第一次图片切换跟不上。所以直接用两个img,页面加载完成就开始请求图片,再切换时就不会因为请求资源带来延时了。看代码吧。
$("#trashContainer").droppable({
drop : function(event, ui) {
$(ui.draggable).remove();
deleteCustom($(ui.draggable).attr("no"));//如果网址是用户添加的,将在cookie中将添加的网址删除
$("#trash_tip").css("display", "none");
$("#trash").css("display", "block");
},
out : function(event, ui) {
$("#trash_tip").css("display", "none");
$("#trash").css("display", "block");
},
over : function(event, ui) {
$("#trash").css("display", "none");
$("#trash_tip").css("display", "block");
}
});
七. 网址加载
说一下我们的网址加载策略吧,像这些导航类的网站,默认网址列表可能会发生变化,比如我在后台删除或者添加了网址。为了最大化的提高用户体验,针对自定义过的用户,我们不让他受任何影响,没有自定义过的就按照后台定义的最新网址来。如果时间长了,后台变换的网址多了,想重新整理网址让所有用户都变为最新的网址列表,就变换网址版本,如果网址版本出现变化,不管有没有自定义都重新来过。如何实现呢,对于后台删除的网址,在网址对应的li上加个type="delete"属性,添加的网址直接添加即可。打开网站时,读取cookie,判断是否有版本变更,判断用户是否自定义过。如果没有自定义过将带有type="delete"属性的网址删除。如果自定义过,先把用户添加的网址追加到网址列表,再按保存的顺序把相应编号的网址移动到最后,可能还剩几个网址没有在order里出现,这些网址就是被用户删除掉的,算一下有几个,再把前边的几个删掉就ok了。
function loadWebSites() { //判断版本变更 if ($.cookie('ver') != '0.9') { $.removeCookie("order"); $.removeCookie("custom"); $.cookie('ver', '0.9', { expires : 1000 }); } //判断是否已经自定义过 var order = $.cookie('order'); if (order != undefined) { var custom = $.cookie('custom'); if (custom != undefined) { //add custom $($.parseJSON(custom)).each(function() { appendSite(this.no, this.name, this.url); }); } //change order var orderObject = $.parseJSON(order) $(orderObject).each(function() { $("#sortable li[no='" + this + "']").appendTo($("#sortable")); }); //remove deleted item var deletedCount = $("#sortable li").length - orderObject.length; $("#sortable li:lt(" + deletedCount + ")").remove(); } else { $("#sortable li[type=delete]").remove(); } }
今天是网站正式上线的第一天,后续还会不断地完善更新,欢迎大家提出任何建议。感兴趣的朋友请关注Simple上网导航的官方微博(左上角公告里有新浪微博关注按钮),我们会进行更多的互动。如果能分享给身边的朋友那更是感激不尽,先谢过了。其实文章和代码已经写好很久了,今天才上线是因为走了些弯路,以后再跟大家聊一下这些非技术方面的问题吧。