比较不同机器上的两个目录是否完全相同,将两个目录的每个文件的内容和文件名都做md5:
find /home/junjie -type f -exec md5sum {} \; | sort | md5sum
DevOps
比较不同机器上的两个目录是否完全相同,将两个目录的每个文件的内容和文件名都做md5:
find /home/junjie -type f -exec md5sum {} \; | sort | md5sum
最近遇到一些用户不能访问https,下面记录一下不能访问https的几种情况:
1. 用户的电脑的时间不在证书有效期内
a. 用户将电脑时间调到了证书生效时间以前,或证书确实还没有生效
b. 用户将电脑时间调到了证书失效时间以后,或证书确实已经失效
2. 用户的浏览器不支持https,或没有开启https的相关选项;由于ssl2存在安全问题,所以浏览器一般默认启用ssl3 tls,而不启用ssl2
3. 浏览器存在bug,发现IE 8.0.6001.18702 如果不启用ssl2,访问https就有问题
偶尔发现系统里有一些cookie的值为deleted,然后就研究了一下,颇有所获;下面就分享一下如何使用PHP删除cookie
1. setcookie("name",""); 方式删除cookie时,PHP将cookie的值设置为deleted,过期时间设置为一年前的该时刻;如果用户的时间为两年前,则该cookie没有被删除,而是将值设置为了deleted;比较靠谱的删除cookie的方法为:
setcookie("name","deleted",1,path,domain);
注意:cookie的值可以不是deleted,但是不能为空,否则,时间参数将不被参考。
2. 浏览器识别删除cookie的逻辑: 浏览器不关心cookie的值是什么,如果过期时间小于当前时间,就删除该cookie,否则认为是设置cookie
关于cookie的secure属性和Httponly属性
只要cookie的name、path、domain相同,就是同一个cookie; 设置cookie时如果使用了secure或Httponly关键字,则删除的时候不需要这些关键字也能删除cookie
关于cookie与https
1. http的请求可以设置secure属性的cookie(只是自己设置的自己却得不到,没人这么用的);
2. http的请求也可以删除secure属性的cookie; 如果你需要先得到要删除的cookie做点儿什么然后再删除的话,走http删除https的cookie就不行了
kmeleon.js及pref.js配置解释
K-MeleonCCF ME目录下的defaults\pref\kmeleon.js保存了K-Meleon的默认设置.(kmeleon1.1*以前的官方版 defaults\pref下的所有.js文件也都是保存的默认设置,相当于根据用途,把kmeleon.js分散成几个文件)
K-MeleonCCF ME\Profiles\????????.default\prefs.js(老版本是K-Meleon ME\Profiles\Profiles\prefs.js)是个人设置, 保存你对浏览器设置上的修改, 它优先于kmeleon.js. 个人建议当设置好后,把大部分prefs.js里的设置转移到kmeleon.js,这样不会因为删除个人目录而丢失设置.
prefs.js里面的值要写成 user_pref 开头的形式
如果prefs.js有和kmeleon.js相同的设置项目且其值相同时, prefs.js里的项目会在运行后自动删除.
根据我的经验, 解释一下部分设置的意思.
Quote:
pref("general.useragent.vendor", "K-Meleon"); 默认UserAgent为:K-Meleon
pref("general.useragent.vendorSub", "1.5"); K-Meleon的版本为:1.5
pref("kmeleon.MRU.maxURLs", 16); 最近访问地址记录:16个
pref("kmeleon.MRU.behavior", 2); 最近访问地址记录保存类型: 0 所有 / 1 域名 / 2 仅输入的 / 3 不保存
pref("kmeleon.general.homePage", ""); 设置主页网址
pref("kmeleon.general.startHome", false); 启动时打开主页: true 是 / false 否
pref("kmeleon.general.offline", false); 离线浏览: true 是 / false 否
pref("kmeleon.general.openurl", "ID_OPEN_LINK"); 点击链接默认在当前标签打开,如果改成"ID_OPEN_LINK_IN_BACKGROUND",则是默认在背景标签打开
pref("prefs.converted-to-utf8", true); 把配置文件的编码方式为 utf-8: true 是 / false 否
pref("kmeleon.general.sourceCommand", ""); 察看网页源码的外部编辑器地址(例如C:\WINDOWS\notepad.exe,要写成C:\\WINDOWS\\notepad.exe)
pref("kmeleon.general.sourceEnabled", false); true 用外部编辑器察看网页源码 / false 用kmeleon本身的源码察看器
pref("view_source.wrap_long_lines", true); kmeleon本身的源码察看器是否自动换行
pref("kmeleon.general.mode", "LAYERS ONLY"); 所有的窗口以标签形式打开
/**************插件部分*********************/
pref("kmeleon.plugins.bmpmenu.load", true); 菜单图标支持插件是否载入: true 是 / false 否
pref("kmeleon.plugins.rebarmenu.load", true); 菜单拖动支持插件,没有这个插件,菜单栏就无法拖动,只能以windows固定形式出现
pref("kmeleon.plugins.crash.load", false); 浏览器崩溃报告
pref("kmeleon.plugins.fullscreen.load", true); 全屏插件
pref("kmeleon.plugins.history.load", true); 历史记录插件
pref("kmeleon.plugins.toolbars.load", true); 工具栏插件
pref("kmeleon.plugins.luamacro.load", true); luamacros插件
pref("kmeleon.plugins.macros.load", true); macros插件
pref("kmeleon.plugins.searchbar.load", true); 搜索栏插件
pref("kmeleon.plugins.sessions.load", true); 线程插件
pref("kmeleon.plugins.searchbar.title", ""); 搜索栏标题
pref("kmeleon.plugins.bookmarks.load", true); 书签(收藏夹)插件 是否载入: true 是 / false 否
pref("kmeleon.plugins.bookmarks.chevron", true); 书签(收藏夹)是否显示网站图标
pref("kmeleon.plugins.bookmarks.menuAutoDetect", true); 书签(收藏夹)bookmark.html文件默认位置
pref("kmeleon.plugins.bookmarks.openurl", "ID_OPEN_LINK"); 默认在当前标签打开书签(收藏夹)网址,如果改成"ID_OPEN_LINK_IN_NEW_TAB",为在新标签打开;"ID_OPEN_LINK_IN_BACKGROUNDTAB",则是在背景标签打开
pref("kmeleon.plugins.favorites.load", true); 直接使用IE的收藏夹插件 是否载入: true 是 / false 否
pref("kmeleon.plugins.favorites.menuAutoDetect", true);
pref("kmeleon.plugins.favorites.openurl", "ID_OPEN_LINK");
pref("kmeleon.plugins.hotlist.load", false); 直接使用opera的书签插件 是否载入: true 是 / false 否
pref("kmeleon.plugins.hotlist.menuAutoDetect", true);
pref("kmeleon.plugins.hotlist.openurl", "ID_OPEN_LINK");
pref("kmeleon.plugins.gestures.load", true); 鼠标手势插件 是否载入: true 是 / false 否
pref("kmeleon.plugins.gestures.down", "ID_CLOSE_TAB"); 鼠标手势 向下=关闭标签
pref("kmeleon.plugins.gestures.downleft", "ID_OPEN_LINK_IN_BACKGROUNDTAB"); 鼠标手势 左下=背景标签打开链接
pref("kmeleon.plugins.gestures.downright", "ID_OPEN_LINK_IN_BACKGROUNDTAB"); 鼠标手势 右下=背景标签打开链接
pref("kmeleon.plugins.gestures.left", "ID_NAV_BACK"); 鼠标手势 左=后退
pref("kmeleon.plugins.gestures.right", "ID_NAV_FORWARD"); 鼠标手势 右=前进
pref("kmeleon.plugins.gestures.up", "ID_NEW_TAB"); 鼠标手势 上=开新标签
pref("kmeleon.plugins.gestures.upleft", "macros(top_level)"); 鼠标手势 左上
pref("kmeleon.plugins.gestures.upright", "sessions(undo)"); 鼠标手势 右上=恢复关闭窗口
//****************************标签栏****************************/
//*—————————K-Meleon1.5, K-MeleonCCF ME, K-MeleonCCF ME极简版—————————*/
pref("browser.tabs.autoHide", false); 只有一个标签时,是否自动隐藏标签: true 是 / false 否
pref("browser.tabs.warnOnClose", false); 关闭浏览器是否确认
pref("kmeleon.tabs.OnDoubleClick", 0); 双击标签时: 0 关闭标签/1 新建标签 /2 显示标签菜单
pref("kmeleon.tabs.OnMiddleClick", 0); 中键点击标签时: 0 关闭标签/1 新建标签/2 显示标签菜单
pref("kmeleon.tabs.OnRightClick", 2); 右键击标签时: 0 关闭标签/1 新建标签/2 显示标签菜单
pref("kmeleon.tabs.catchOpen", 1);
pref("kmeleon.tabs.onCloseLast", 1); 关闭最后一个标签时 0 关闭K-Meleon /1 打开空白标签 /2 什么都不做
pref("kmeleon.tabs.onCloseOption", 2); 关闭标签时: 0 显示紧邻的右边一个标签/ 1 显示紧邻的左边一个标签 / 2, 显示上一次选中的标签
pref("kmeleon.tabs.onOpenOption", 1); 新建的标签 0 在标签栏最后位置 / 1 在当前标签后
//*—————————K-Meleon1.1*以layer插件模拟标签—————————*/
pref("kmeleon.plugins.layers.confirmClose", false); 是否确认关闭标签: true 是 / false 否
pref("kmeleon.plugins.layers.load", false); layer插件载入: true 是 / false 否
pref("kmeleon.plugins.layers.rebar", true);
pref("kmeleon.plugins.layers.style", 2);
pref("kmeleon.plugins.layers.catchOpen",true);
pref("kmeleon.plugins.layers.catch",true);
pref("kmeleon.plugins.layers.load",true);
pref("kmeleon.plugins.privacy.load", true); 隐私工具是否载入: true 是 / false 否 (作用:清除缓存,cookie,历史记录等等…)
pref("kmeleon.plugins.privacy.clearCache", 0);
pref("kmeleon.plugins.privacy.clearCookies", 0);
pref("kmeleon.plugins.privacy.clearHistory", 0);
pref("kmeleon.plugins.privacy.clearMRU", 0);
pref("kmeleon.plugins.privacy.clearSignOn", 0);
pref("kmeleon.plugins.sessions.load", true); 线程插件是否载入: true 是 / false 否
pref("kmeleon.plugins.sessions.list", "last,");
// ********************************界面 ****************************************/
pref("kmeleon.general.toolbars_locked", true); 锁定界面: true 是 / false 否
pref("kmeleon.display.URLbarTitle", ""); 地址栏左边的标题显示什么(这里为空,就是没有标题)
pref("browser.display.use_system_colors", true); 是否使用系统主题的色彩配置(主要作用于空白标签的颜色): true 是 / false 白色
pref("kmeleon.display.backgroundImage", ""); 背景图片位置(例如C:\bg.jgp,要写成C:\\bg.jgp)
pref("kmeleon.display.backgroundImageEnabled", true); 是否使用北京图片
pref("kmeleon.favicons.show", true); 是否显示网站图标: true 是 / false 否
pref("kmeleon.favicons.cached", false); 是否保存网站图标: true 是 / false 否
pref("browser.chrome.site_icons", false);
pref("browser.chrome.favicons", false);
pref("kmeleon.display.maximized", false); 启动时是否最大化: true 是 / false 否 (目前有bug,设置成true也不能最大化)
pref("kmeleon.display.height", 740); K-Meleon的高度(单位:像素)
pref("kmeleon.display.width", 970); K-Meleon的宽度(单位:像素)
pref("kmeleon.display.XPos", 64); K-Meleon的X轴位置(单位:像素)
pref("kmeleon.display.YPos", 48); K-Meleon的Y轴位置(单位:像素)
pref("kmeleon.toolband.Tabs.break", 0); 标签栏后换行: 1 是 / 0 否
pref("kmeleon.toolband.URL Bar.index", 0); 地址栏位置为第一
pref("kmeleon.toolband.Tabs.index", 1); 标签栏位置为第二
pref("kmeleon.toolband.Tabs.visibility", true); 是否显示标签栏
pref("kmeleon.toolband.URL Bar.break", 1); 地址栏后换行: 1 是 / 0 否
pref("kmeleon.toolband.URL Bar.size", 200); 地址栏宽度为: 200像素
// pref("kmeleon.toolband.Tabs.size", 760); 标签栏宽度为: 760像素
// 同一行个栏目的宽度之和 = K-Meleon宽度 – 10;
// 说明:b23版本必须要指明各个栏目宽度,不然界面会乱.其它版本如果在同一行只有两个项目, 只需要指定一个,另一个就会自动;
pref("kmeleon.toolband.URL Bar.visibility", true); 是否显示地址栏
// ****************隐私设置********************************************/
pref("network.cookie.cookieBehavior", 1); cookie的处理 0: 接受所有cookie /1: 只接受源服务器的cookie /2: 不接受cookie /3:用p3p
// *———–UserAgent设置———————*/
pref("kmeleon.privacy.useragent1.name", "MSIE 6.0");
pref("kmeleon.privacy.useragent1.string", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
pref("kmeleon.privacy.useragent2.name", "Firefox 2.0");
pref("kmeleon.privacy.useragent2.string", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6");
pref("kmeleon.privacy.useragent3.name", "Opera 8.54");
pref("kmeleon.privacy.useragent3.string", "Opera/8.54 (Windows NT 5.1; U) [en]");
pref("capability.policy.restrictedpopups.Window.open", "allAccess");
pref("capability.policy.restrictedpopups.sites", "");
pref("dom.disable_open_during_load", true); 弹出窗口屏蔽
pref("security.enable_java", false); 允许执行java : true 是 / false 否
pref("security.warn_entering_secure", false);
pref("security.warn_leaving_secure", false);
pref("security.warn_entering_weak", true);
pref("security.warn_submit_insecure", false);
pref("security.warn_viewing_mixed", false);
pref("signon.rememberSignons", false); 记住填表内容: true 是 / false 否
//************搜索**********************************/
pref("kmeleon.general.searchEngine", "http://www.google.com/search?q="); 默认搜索引擎地址(必须是kmeleon.plugins.macros.search.engine[0..?].url里列出的)
pref("kmeleon.general.searchEngineName", "Google"); 默认搜索引擎名称(必须是kmeleon.plugins.macros.search.engine[0..?].name里列出的)
pref("kmeleon.plugins.macros.search.locked", true); 锁定搜索引擎
pref("kmeleon.plugins.macros.search.engine0.name", "Google"); 搜索引擎名称
pref("kmeleon.plugins.macros.search.engine0.url", "http://www.google.com/search?q="); 搜索引擎地址
pref("kmeleon.plugins.macros.search.engine1.name", "Baidu");
pref("kmeleon.plugins.macros.search.engine1.url", "http://www.baidu.com/s?ie=utf-8&wd=");
pref("kmeleon.plugins.macros.search.engine2.name", "Wikipedia");
pref("kmeleon.plugins.macros.search.engine2.url", "http://en.wikipedia.org/wiki/Special:Search/");
pref("kmeleon.plugins.macros.search.engine3.name", "DictCN");
pref("kmeleon.plugins.macros.search.engine3.url", "http://www.dict.cn/search/?q=");
// ***********************下载*************************/
pref("kmeleon.general.CloseDownloadDialog", true); 下载完成时关闭下载对话框
pref("kmeleon.general.saveDir", "F:\\Download Files\\"); 保存目录设置
pref("kmeleon.download.dir", "F:\\Download Files\\"); 下载目录设置
pref("kmeleon.download.saveDir", "F:\\Download Files\\");
pref("kmeleon.download.lastDir", "F:\\Download Files\\"); 上次使用的下载目录
pref("kmeleon.download.askOpenSave", false); 下载是否要经过确认 : true 是 / false 否
pref("kmeleon.download.SaveUnkownContent", true); 保存未知内容
pref("kmeleon.download.showMinimizedDialog", false); 下载对话框最小化
pref("kmeleon.download.closeDownloadDialog", true); 下载完成自动关闭对话框
pref("kmeleon.download.flashWhenCompleted", false); 下载完成时任务栏闪动
pref("kmeleon.download.saveUseTitle", true); true: 以网页标题为文件名保存网页/ false: 以网页本身的文件名保存网页
pref("kmeleon.download.useDownloadDir", true); 使用"kmeleon.download.dir"定义的目录保存下载内容
pref("browser.downloadmanager.behavior", 1); 1 打开下载进度对话框/ 2 不用下载进度对话框
// ****************加速设置****************************/
pref("browser.display.show_image_placeholders", false); 图片未载入时,是否显示图片图标: true 是 / false 否
pref("Network.dns.disableIPv6", true); 是否禁用IPv6
pref("network.cookie.prefsMigrated", true);
pref("network.dnsCacheExpiration", 3600); DNS缓存条目过期的时间(单位:秒)
pref("network.dnsCacheEntries", 512); DNS缓存中保存条目的数目
// Cache Prefs
pref("browser.cache.memory.capacity", -1); 浏览器内存缓存大小(单位KB) -1: 自动
pref("browser.cache.disk.capacity", 32768); 浏览器磁盘缓存大小(单位KB) -1: 自动 (32768=32M)
// ***************Gecko引擎调整*****************************/
// HTTP Connection Prefs
pref("network.http.max-connections", 64);
pref("network.http.max-connections-per-server", 20);
pref("network.http.max-persistent-connections-per-server", 8);
pref("network.http.max-persistent-connections-per-proxy", 16);
//pref("network.http.keep-alive", false);
//pref("network.http.proxy.keep-alive", false);
// HTTP Pipelining Prefs
pref("network.http.pipelining", true);
pref("network.http.proxy.pipelining", true);
pref("network.http.pipelining.firstrequest", true);
pref("network.http.pipelining.maxrequests", 16);
// Rendering Prefs
pref("browser.sessionhistory.max_viewers", 4);
pref("nglayout.initialpaint.delay", 10);
pref("content.notify.ontimer", true);
pref("content.notify.interval", 10000);
pref("content.notify.backoffcount", 200);
pref("content.interrupt.parsing", true);
pref("content.max.tokenizing.time", 50000);
pref("content.switch.threshold", 1000000);
// ***************字体设置*****************************/
pref("intl.charset.detector", "universal_charset_detector"); 自动监测网页编码设置
pref("font.minimum-size.x-unicode", 10); unicode最小字体大小
pref("font.minimum-size.x-western", 10); 西方字体最小字体大小
pref("font.minimum-size.zh-CN", 10); 简体中文最小字体大小
pref("font.minimum-size.zh-TW", 10); 繁体中文最小字体大小
pref("font.askWhenNeeded", false); 缺少字体支持时是否弹出警告框
/*****************杂项*******************************/
pref("kmeleon.find.matchCase", false); 查找时 匹配大小写
pref("kmeleon.find.searchBackwards", false); false: 向后查找 / true: 向前查找
pref("kmeleon.find.wrapAround", true);
pref("kmeleon.find.highlight", true); 高亮显示查找到的内容
pref("mousewheel.withnokey.numlines",6); 一个滚轮动作滚动行数
pref("mousewheel.withnokey.sysnumlines",false); 是否使用系统定义的滚动行数
pref("mousewheel.withcontrolkey.action",3);
//pref("general.smoothScroll", true); 平滑滚动
pref("browser.enable_automatic_image_resizing", true); 大图片自动缩小到窗口大小
pref("browser.xul.error_pages.enabled", true); 网页连接不上时,显示自带的错误页
//pref("kmeleon.urlbar.dropdown_lines", 10); 地址栏下拉菜单显示行数
pref("browser.urlbar.autoFill", true); 地址栏自动完成
pref("browser.urlbar.autocomplete.enabled", true); 地址栏自动完成
pref("browser.link.open_external", 3); 外部程序调用浏览器时 0,默认窗口/ 1,当前窗口或标签/ 2, 新窗口/3, 新标签
// handle links targeting new windows
//2 (default): In a new window 3: In a new tab 1 (or anything else): In the current window
pref("browser.link.open_newwindow", 3); 链接要求开新窗口时, 打开: 1,当前窗口 2, 默认窗口/ / 3, 新标签
// 0: no restrictions – divert everything
// 1: don’t divert window.open at all
// 2: don’t divert window.open with features
pref("browser.link.open_newwindow.restriction", 0);
pref("kmeleon.display.newWindowOpenAs", 0); 新建窗口或标签时显示: 0,空白页/ 1, 主页 / 2, 复制当前窗口
pref("kmeleon.display.newWindowURL", ""); 新建窗口或标签时显示的网址
这是最简单的一种方式,比如Google Adsense:
1 |
<script type="text/javascript"><br />google_ad_client = 'pub-3741595817388494';<br /></script><br /><script type="text/javascript" src="http://pagead2.<br />googlesyndication.com/pagead/show_ads.js"></script><br /> |
缺点是引入了全局变量。其中引入文件的方式还有两个变体:
1 |
// 变体1:用document.write输出<br /><script type="text/javascript"><br />google_ga_id = 'g6u7un8646xx';<br />document.write(unescape('%3Cscript type="text/javascript" src=<br />"http://www.google-analytics.com/ga.js"%3E%3C/script%3E'));<br /></script><br /><br />// 变体2:用DOM操作append到head里<br /><script type="text/javascript"><br />G_BEACON_ATP = 'category=&userid=&channel=112ad_id=';<br />document.getElementsByTagName('head')[0].appendChild(document.<br />createElement('script')).src='http://taobao.com/atp.js';<br /></script><br /><br />// 注意:上面的代码是根据实际应用虚拟的示范代码<br /> |
注:变体1应用很多,常见写法如下:
1 |
<script type="text/javascript"><br />// 直接转义即可:<br />document.write('<script type="text/javascript" src="test.js"></script>');<br />// 或者像Yahoo!首页一样:<br />document.write('<scr' + 'ipt type="text/javascript" src="test.js"></scr' + 'ipt>');<br /></script><br /> |
和全部变量相比,我们更希望能像下面这样传入参数:
1 |
<script type="text/javascript" src="test.js?a=b&c=d"></script><br /> |
核心问题是如何获取到src属性。
方法一是给script添加id属性,通过id得到当前script,再用正则从src中取出参数。缺点是HTML 4.01 Specification里,SCRIPT元素没有id属性。这个缺点也算不得是缺点,毕竟尽信标准不如无标准。
方法二是用js的文件名当作钩子,js代码里通过document.getElementsByTagName('script')
后,正则匹配出当前js文件。这个方法很正统,但要求文件名唯一。缺点是代码多,不精炼,对性能也稍有影响。
方法三是在方法一的基础上,干脆再添加一个自定义属性data:
1 |
<script id="testScript" type="text/javascript" src="test.js" data="a=b&c=d"></script><br /> |
test.js文件里,通过下面这行得到传入的参数:
1 |
var scriptArgs = document.getElementById('testScript').getAttribute('data');<br /> |
方法四是利用js的顺序执行机制(js文件的加载可以是同步或异步方式,但执行时,一定是按照在文档流中的顺序来执行的)。当某个js文件执行时,一定是“已加载”的js文件中的最后一个:
1 |
var scripts = document.getElementsByTagName('script');<br />var currentScript = scripts[scripts.length - 1];<br /> |
方法四比方法二更灵巧天才。
从代码的精简和性能上讲,方法三 > 方法 一 > 方法四 > 方法二
小结:如果你很在意标准,推荐方法四;如果和我一样觉得没必要完全遵守标准,推荐方法三。
如果你和我一样是John Resig的忠实fans,或许还记得去年8月份讨论得很火爆的《Degrading Script Tags》。John Resig给我们开启了一扇想象的门,对于本文的问题来说,还可以用以下“邪门歪道”来实现:
1 |
<script type="text/javascript" src="test.js"><br /> TB.SomeApp.scriptArgs = 'a=b&c=d';<br /></script><br /> |
在test.js文件里:
1 |
TB = {}; TB.SomeApp = {};<br />var scripts = document.getElementsByTagName("script");<br />eval(scripts[ scripts.length - 1 ].innerHTML);<br /> |
这样就将参数存储到了TB.SomeApp.scriptArgs
变量里。
当参数不多时,甚至可以这样:
1 |
<script type="text/javascript" src="test.js">a=b&c=d</script><br /> |
js文件里:
1 |
var scripts = document.getElementsByTagName("script");<br />var scriptArgs = scripts[ scripts.length - 1 ].innerHTML.replace(/[s]/g, '');<br /> |
想象是无止境的,还可以利用onload:
1 |
<script type="text/javascript" src="test.js" onload="TB.SomeFun('a=b&c=d')"></script><br /> |
js文件里定义好函数即可:
1 |
TB = {};<br />TB.SomeFun = function(arg) { //code };<br /> |
上面的代码在非ie浏览器下,都能正确运行。针对笨笨的ie,还得加几行代码:
1 |
if(window.ActiveXObject) {<br /> var scripts = document.getElementsByTagName('script');<br /> eval(scripts[scripts.length - 1].getAttribute('onload'));<br />}<br /> |
只要继续发扬挖掘精神,我相信还有更多灵感方案-.-
看了上面这么多解决方案,究竟哪个方案最好呢?我的答案是:没有最好,只有最合适!因为对于不同的应用,以及不同的理念来说,对“好”的定义是各异的。
比如我当前的理念,觉得没必要完全遵守标准,而全局变量,要避免的是滥用,不是不用。因此我会选择全局变量方案,最简单,性能也最好。
如果是我的同事小马,很遵从标准,或许就会选择第二类方案中的方法二或方法四。
再或者等小雕长大了,也许直接就用onload方案同时不用再给ie特殊照顾了,甚至直接通过某种高级传送门就把参数传过去了……
摘自: http://lifesinger.org/blog/2009/03/how-to-pass-params-to-javascript-file/
我打算写一个系列文章,介绍webim的方方面面,今天开始第一篇。
我之前发布了一个webim,那个im设计了前端UI、交互,后端程序和通讯只是随便写了一下。作为一个交互很多的web应用,良好的后端设计可以减少数据库访问、减轻服务器负载;良好的通讯模式更是可以较少服务器连接数、节省流量。这篇文章主要讲web即时通讯中常用的技术。
HTTP是无连接的,HTTP通讯过程基本就是:客户端发送请求给服务器,服务器接收请求给出响应信息,客户端接收响应信息显示在用户的显示器上, 客户端断开连接。由此可知,要实现即时聊天中的”即时”,我们有两个办法:服务器抓住连接不断开和客户端不断的向服务器发起请求实现伪即时。当然用 Flash XMLSocket可以实现真正的即时通讯,但这样已经不是使用HTTP协议了,HTTP天生的优势(无需另外开端口、自动穿越防火墙)也就无法体现。
1.短轮询(polling):核心思想是客户端定时去服务器取消息。为了实现即时效果,轮询的间隔必须设计得足够短,另外为了操作的流畅,需要使 用Ajax来发送请求。本人的QGYWebIM就是采用的此方案。这种方案的优点是:后端程序编写比较容易,发送完响应信息马上断开连接,不会占用太多服 务器资源。缺点是一般情况下,频繁的请求中有大半是无用,这些冗余请求无形中浪费了带宽和服务器资源。我们可以通过判断用户的活跃程度来决策请求服务器的 间隔,我在51的一个帖子提到过这种方法,但是间隔一旦长了,消息的传送就有延时,违背了即时聊天的初衷了。
2.长轮询(long-polling):基本原理是客户端向服务器发送请求,服务器接到请求后hold住连接,直到有新消息才返回响应信息并关闭 连接,连接被断开期间用户的新信息会被服务器缓存起来。客户端处理完响应信息后再向服务器发送新的请求。这种做法的优势是如果用户一直没新消息,客户端不 会频繁的轮询去服务器取消息,节省了流量,但是服务器维持长连接是很消耗资源的。具体实现起来,前端这边基本不需要什么改动,依然是用Ajax轮询取信 息,后端需要在没有新消息时处理一下。
3.长连接(streaming):其实很早以前就有人使用这种技术来实现聊天室的通讯。以前在页面中嵌入一个iframe,iframe里放一个 使用长连接页面,服务器有新消息就会及时的在iframe里反映出来,再依靠客户端的脚本解析出来就OK了。这样做一个比较严重的问题是:使用 iframe请求长连接时,无论是IE还是firefox都会认为页面没有加载完而显示进度条,很难看。不过这个问题是可以解决的。firefox支持了Streaming Ajax,在readyState为3的时候就能接受数据,所以问题不大;IE则只能在readyState为4,即连接断开时才能得到返回值。但是伟大的Google工程师使用了一个hack成功的解决了这个问题:使用一个被称为“htmlfile”的ActiveX,把iframe放在这个ActiveX里就OK了。
无疑,使用长连接对于用户来说是最好的方案,用户体验最好(消息能及时的到达)、占用用户带宽最少(不会发送无用的请求),但是会增加服务器的开销;长轮询是折中方案,Facebook IM 就是采用这种方案,不过做了一点改动:客户端发起的每个连接服务器都hold10S,这10S中新消息会源源不断的返回给客户端,10s后连接关闭,客户 端发起下一个连接。这样做是因为Facebook的用户会不断的打开、关闭新页面,如果每个页面都建立一个永久的长连接,会阻塞浏览器其他请求,服务器也 会吃不消的;短轮询因为实现起来简单,适用于小型应用。
转自: http://www.qgy18.com/2008/08/webim-design-transport/
给字符串对象添加宽字符截取方法
String.prototype.substr2=function(a,b){
var s = this.replace(/([^x00-xff])/g,"x00$1");
return(s.length<b)?this:s.substring(a,b).replace(/x00/g,');
}
var queryString = function(val){
var uri = window.location.search;
var re = new RegExp("" +val+ "=([^&?]*)", "ig");
return ((uri.match(re))?(uri.match(re)[0].substr(val.length+1)):null);
};
曾经写过一个javascript自动常见form,并提交到自动创建的iframe的一个应用。由于提交之后跳转到另外一个页面,然后回退,会返现form的提交请求又自动重发了一次,因为是提交到一个隐形的iframe中的,我就在提交之后把iframe给删除了,但是回退后还会重新发送提交请求,我没有办法,知道有一天我在走路的时候,突然想到问题可能出现在为删除的form上,于是,我测试了一个,提交form之后就删除form,然后回退就没有该问题了,困扰了我几个月的问题终于真相大白、水落石出了。
1. 跨域访问是浏览器非常明显的访问限制
2. 另外除了根据域名的访问限制外,还有协议间的限制,如:http 和 https即使是同域也不能相互访问;
我原来以为跨域限制应该不限制http和https之间的访问,知道做的时候才发现是有这方面的限制的。做浏览器这方面开发是需要更多地了解浏览器的特性的。