Tag: javascript

  • Javascript bookmark this page in Chrome

    I have a stupid client asked me to add “Bookmark this page” to his web pages. I explained to him how bad usability it is but he did not listen to me. He insisted the majority of web users were as stupid as him, so him wanted to help them bookmark the page.

    Nevertheless, it is not my site and he is my customer. Customer is the God. So I spent some time digging around and found this script.

    <script type="text/javascript">
    //<![CDATA[
    function bookmark_us(){
    var url = window.location;
    var title = document.title;
    
    if (window.sidebar) // firefox
        window.sidebar.addPanel(title, url, "");
    else if(window.opera && window.print){ // opera
        var elem = document.createElement('a');
        elem.setAttribute('href',url);
        elem.setAttribute('title',title);
        elem.setAttribute('rel','sidebar');
        elem.click();
    } 
    else if(document.all)// ie
        window.external.AddFavorite(url, title);
    }
    //]]>
    </script>
    

    However, Chrome browser does not allow us to bookmark any page using javascript. There is no workaround, and I think Google is absolutely right on this.

    My concern is: the above script does not do anything in Chrome. Sooner or later my client will come back to me asking why my script does not work in Chrome. To avoid being questioned, I finally use another solution. It is a jQuery plugin called jBrowserBookmark. It will prompt the correct way to bookmark in unsupported browsers.

  • this vs $(this) in jQuery

    I don’t know why, but this is how it happens.

    When I make a jQuery plugin, the skeleton is

    (function($) {
    $.fn.myplugin = function() {
    return this;
    };
    })(jQuery);
    

    And if I need an each operation inside plugin, the skeleton can be

    (function($) {
    $.fn.myplugin = function() {
    //outside each, this.width() can work
    return this.each(function() {
    //inside each, only $(this).width() works
    });
    };
    })(jQuery);
    

    The interesting thing is inside each, I must use “$(this)” to run jQuery functions, but outside each, I can also use “this”.

    I don’t know why now, but I think I will know some day.

  • CSS styling without images

    I am quite surprised with the styling effect achieved by pure CSS without the help of images. I can round corner and rotate html elements without creating any background images.

    See the result I get.

    Comprehensive styling using pure CSS
    Comprehensive styling using pure CSS

    And this is the ONLY product image in this CSS styling demo:

    Halloin 3D gift bags
    Halloin 3D gift bags

    Although the effect is comprehensive, but with the help of jQuery plugins, the syntax is very simple. Just a few lines of text.

  • Stupid IE6

    我负责的一个网站的访问者中, IE6 用户仍占 6.2%,这个比例不尴不尬。改版初期对他们照顾不够,今天下狠心花了时间去测试 IE6 下的兼容性。几小时之后,IE6 下都能完全正常显示了,我也多了一些心得。

    1. 如果要加层,先设置该层 text-align:left,否则 IE6 下与层有点关系的元素,不管它是在层内还是层外,位置会摆置得莫名其妙。特别是当看到层外元素整体摆错位置,我更莫名其妙,实在搞不懂 IE6 对层的理解是什么。如果一开始就对层进行初始化({ text-align:left; position:relative; })就会节省很多时间。
    2. 避免使用高级的 css 语法,比如多 class 的连贯,.class-a.class-b { color:red; }。本希望该样式只应用于同时具有 class-a 和 class-b 元素,结果 IE6 不理解。如果 IE6 对不理解的 selector 作忽略处理倒还好,可是 IE6 把该样式应用到了所有 class-b 元素(只具有 class-a、不具有 class-b 的元素未受影响),IE6 是不是显得不懂装懂?祸害很大,害我多花了一小时在找被错误影响了的 class-b 元素的原因。如果实在想要多 class 的连贯的 selector,那比较可行的办法是用 jquery 来保证跨浏览器的兼容性,即 $jquery(‘.class-a.class-b’) 。

    题外话:很久前我写过一篇Cross-browser CSS。今天多了两点心得,本想直接写入以前的文章。转念一想不对,今天的心得是今天的,以前的心得是以前的,以后万一我来翻看自己的文章,我也想从中看出我的成长历程,混在一起就看不出历程了。但从心得角度讲,最好把所有 cross-browser css 的内容写在一起,否则,若干年后我再看Cross-browser CSS那一页时不一定想起今天补充的两点。似乎没什么好办法(即使用 related posts 也比较勉强)。

  • Lightbox not working in Magento 1.4 solved

    My case is special –

    很久以前为 Magento 1.3 加装 Lightbox 2 时,我听从某人的建议,去掉了 Magento 自带的 scriptaculous effects.js,安装了当时最新的 scriptaculous 1.8.3 effects.js。Lightbox 调试成功后一直没去动它。

    Magento 升级到 1.4 后,默认启用 Merge JavaScript Files,这时 Lightbox 就不工作了。如果禁用 Merge JavaScript Files,Lightbox 恢复正常。我调试不出 Lightbox 失效的原因,大概是 js library 版本不兼容。再看了一下 Magento 如今自带 scriptaculous 1.8.2,估计和 1.8.3 相差不大,为了兼容性,干脆就用 Magento 原装的 js。

    于是去掉我自装的 scriptaculous 1.8.3 effects.js,启用 Merge JavaScript Files,如我所愿 Lightbox 恢复正常。

  • Style Magento checkout form fields without touching the core code

    Although I can change css complete restyle the checkout forms, this is not what I want to discuss today. What I want to achieve are:

    1. fix City required asterisk not showing bug
    2. change Address lines from full width to half width as City

    The City required asterisk is hidden by a javascript wrongly. I found City and State/County/Province are put into one li, i.e. <li><div></div></li>. It might be something should happen on State/County/Province but happens on City. If I close li after City, and reopen it before State/County/Province, bug is fixed. By the way, I hide State/County/Province.

    To show a field in full length, Magento uses
    <li><label><span></span></label><input/></li>
    To show a field in half length, Magento uses
    <li><div><label><span></span></label><input/></div></li>

    So just find the right place to insert <div> and close it for Address lines, I easily style them to the same length of City.

  • Email encoder for not being spidered

    我用Email encoder很久了。以前总是去别人网站上运算一下,拿来就用。如今觉得加密算法很多,我应该筛选一下,并作一个适合我自己的常用的工具。

    因为跟javascript 字符串加解密有关,我首先找到一段程序,试运行了一下,相当不错,据说还支持中文字符串加密以及中文密码。

    function Encrypt(str, pwd) {
    if(str=="")return "";
    str = escape(str);
    if(!pwd || pwd==""){ var pwd="1234"; }
    pwd = escape(pwd);
    if(pwd == null || pwd.length <= 0) {
    alert("Please enter a password with which to encrypt the message.");
    return null;
    }
    var prand = "";
    for(var i=0; i<pwd.length; i++) {
    prand += pwd.charCodeAt(i).toString();
    }
    var sPos = Math.floor(prand.length / 5);
    var mult = parseInt(prand.charAt(sPos) + prand.charAt(sPos*2) + prand.charAt(sPos*3) + prand.charAt(sPos*4) + prand.charAt(sPos*5));
    var incr = Math.ceil(pwd.length / 2);
    var modu = Math.pow(2, 31) - 1;
    if(mult < 2) {
    alert("Algorithm cannot find a suitable hash. Please choose a different password. \nPossible considerations are to choose a more complex or longer password.");
    return null;
    }
    var salt = Math.round(Math.random() * 1000000000) % 100000000;
    prand += salt;
    while(prand.length > 10) {
    prand = (parseInt(prand.substring(0, 10)) + parseInt(prand.substring(10, prand.length))).toString();
    }
    prand = (mult * prand + incr) % modu;
    var enc_chr = "";
    var enc_str = "";
    for(var i=0; i<str.length; i++) {
    enc_chr = parseInt(str.charCodeAt(i) ^ Math.floor((prand / modu) * 255));
    if(enc_chr < 16) {
    enc_str += "0" + enc_chr.toString(16);
    }else
    enc_str += enc_chr.toString(16);
    prand = (mult * prand + incr) % modu;
    }
    salt = salt.toString(16);
    while(salt.length < 8)salt = "0" + salt;
    enc_str += salt;
    return enc_str;
    }
    
    function Decrypt(str, pwd) {
    if(str=="")return "";
    if(!pwd || pwd==""){ var pwd="1234"; }
    pwd = escape(pwd);
    if(str == null || str.length < 8) {
    alert("A salt value could not be extracted from the encrypted message because it's length is too short. The message cannot be decrypted.");
    return;
    }
    if(pwd == null || pwd.length <= 0) { 
    alert("Please enter a password with which to decrypt the message.");
    return;
    }
    var prand = "";
    for(var i=0; i<pwd.length; i++) {
    prand += pwd.charCodeAt(i).toString();
    }
    var sPos = Math.floor(prand.length / 5);
    var mult = parseInt(prand.charAt(sPos) + prand.charAt(sPos*2) + prand.charAt(sPos*3) + prand.charAt(sPos*4) + prand.charAt(sPos*5));
    var incr = Math.round(pwd.length / 2);
    var modu = Math.pow(2, 31) - 1;
    var salt = parseInt(str.substring(str.length - 8, str.length), 16);
    str = str.substring(0, str.length - 8);
    prand += salt;
    while(prand.length > 10) {
    prand = (parseInt(prand.substring(0, 10)) + parseInt(prand.substring(10, prand.length))).toString();
    }
    prand = (mult * prand + incr) % modu;
    var enc_chr = "";
    var enc_str = "";
    for(var i=0; i<str.length; i+=2) {
    enc_chr = parseInt(parseInt(str.substring(i, i+2), 16) ^ Math.floor((prand / modu) * 255));
    enc_str += String.fromCharCode(enc_chr);
    prand = (mult * prand + incr) % modu;
    }
    return unescape(enc_str);
    }

    转念一想,我把问题搞复杂了,对自己没什么好处。我的Email encoder用得着这么复杂吗?毕竟我想保护的又不是名人的Email address。所以我改用我自己的方式——采用双重url encode,在第二重url encoding时,encode全部字符(含字母和数字)。