Using Nivo Slider with Prototype

我想要一个 jQuery slider plugin 用在 Magento 上。jQuery slider 类不乏优秀的程序。我不及精挑细选,用了 Nivo Slider。

虽然 slider 能运行,但 FireBug 停止响应。查错发现 too much recursion occured in prototype.js 1132 行。自然想到了 jQuery 和 Prototype 的 conflict,但我有做 noConflict.js,而且 jquery.nivo.slider.js 也没有在全局使用 $,看上去挺规范的呀。

我让 Magento 暂不加载 prototype.js,too much recursion 错误就没有了,但 Magento 不能没有 prototype.js (盼望 Magento 哪天自动放弃 prototype,用 jQuery 重写)。

我有意放弃 Nivo Slider,无意中又发现别人竟做过同样的事情——把 Nivo Slider 用在Magento 下,而且没有 javascript 错误。

我以为是我那段 slider 的 html 写得不好,全盘拷了别人的来用,还是出错。然后我认为是版本问题,可是用别人的 jQuery 库,放在我这里,还是出错。

最后,直到最后,我意识到一点不同之处,我用不带任何参数启动 Nivo Slider,即

$('#slider').nivoSlider();

而别人用

	$('#slider').nivoSlider({
        effect: 'sliceDown', 
        slices: 15, 
       
        animSpeed: 500, 
        pauseTime: 3000, 
        startSlide: 0, 
		 
        directionNav: true, 
		        directionNavHide: true, 
		        controlNav: true, 
                keyboardNav: true, 
		        pauseOnHover: true, 
                captionOpacity: 1, 
        prevText: 'Prev', 
        nextText: 'Next' 
       
    });

就这点造成了 too much recursion。

Reinstate thumbnails in jQuery UI theme switcher

You might have noticed, some tools from jQuery are not fully functional recently. That could be caused by jQuery disabling hotlinks. jQuery UI theme switcher is affected. I call it a bug because jQuery team did not make necessary arrangement before enforcement of hotlink policy.

Nevertheless, how to reinstate thumbnails in jQuery UI theme switcher while waiting for jQuery team to release a hotlink compatible theme switcher? Easy, with my code – Themeswitcher Launcher.


jQuery(function($){
 $('body').prepend('<div id="msdk-themeswitcher"></div>');
 $('#msdk-themeswitcher').themeswitcher();
 var srcStart = "http://jqueryui.com/themeroller/images/";
 $('img[src^="http://jqueryui.com/themeroller/images/"]').each(
 function() {
 this.src = this.src.replace(srcStart,
 "http://static.jquery.com/ui/themeroller/images/");
 });
});

Themeswitcher Launcher just does a simple job: replacing images source in theme switcher to another source static.jquery.com, which still allow hotlinking. You can replace with your domain if you host these images.

To save your time, I packaged jQuery UI theme switcher with my Themeswitcher Launcher. Please note I changed jQuery UI theme switcher slightly because I need it for Magento sites. I put function themeswitcher() into jQuery namespace to be standard jQuery plugin, so it can be working with javascript prototype framework.

Download msdk-themeswitcher-launcher.js.tar.gz

For those who are interested in my Magento modules: jQuery UI theme switcher and my Themeswitcher Launcher are integrated into my Msdk (Magento SDK) module – it is just an advertisement.

Activate Magento ajax loading graphic using jQuery

I extend Magento js using jQuery.
I need ajax loading mask and grahpic for jQuery ajax request.
I want to achieve consistent look and feel.
I want to activate Magento ajax loading graphic initially used in prototype using jQuery.

Although prototype register global event handlers for ajax create and complete events, the handlers will not fire by jQuery ajax request. For jQuery to activate ajax loading graphic, I manually fire the onCreate event in jQuery function.

var r = {options:{loadArea:''}};
varienLoaderHandler.handler.onCreate(r);

to deactivate

varienLoaderHandler.handler.onComplete();

Let me know if you know a better way to tie jQuery and prototype together.

Magento datetime picker is not picking up time value

Magento 用了 dynarch.com 的 calendar 1.0 javascript,有个 bug:无法得到 time 的值。

dynarch.com calendar 已经是 2.0 了,单独使用的话,能显示和修改 time 的值。

我暂时没想好该怎么办:我倾向于用 jQuery 去增强 Magento(prototype 我也用不好,其他的就更不要说了),但 jQuery 现下的版本只有 datepicker,官方还没有 datetimepicker。试过很多第三方 jQuery datetimepicker plugin,没觉得某一款有 jQuery 的神韵。

jQuery dialog widget moves dialog DOM to the very end of body

我在 checkout page 上使用 jQuery dialog widget 来显示 terms and conditions。Terms and conditions 的内容不随 checkout 页面加载(因为大部分顾客不会去读它),而在首次点击 Read terms and conditions 链接后以 ajax 获取内容后用 jQuery dialog 展示。再次点击则不必再用 ajax 获取,而直接用 jQuery dialog 展示。

因为不同种类的产品会对应不同的 terms and conditions,所以 checkout page 会根据 shopping cart 里的所有产品列示出对应的 terms and conditions,可能会有多条。我原想把每条 Read terms and conditions 链接获取的 terms and conditions 内容插入在该链接的后面,在点击事件发生后就可以判断其后的内容 DOM 存在与否决定是否要执行 ajax post 操作。这样可以避免重复获取每个 terms and conditions,以加快用户响应和减少服务器负担。

可如意算盘打了一通,写出最初稿一运行,发现每点一次 Read terms and conditions,ajax post 都要执行一次。一开始我还以为内容 DOM 插入位置不正确,被判断为没加载过而去执行 ajax post。查了好久才发现,内容 DOM 插入位置是正确的,只是每次执行 jQuery dialog(),它就把 dialog DOM(也就是内容 DOM)移到了 body DOM 的最后。

这意味着我不能在 Read terms and conditions 链接后寻取对应的内容 DOM,而必须用另外的办法链接和内容的关系。当然办法有很多,这里就不多说了。

Learned something basic

今天又长知识了。

首先,最简单的,更正了长久以来的想当然,php 下 explode(‘,’, ”) != array(),而是得到长度为 1 的数组,key 是数值 0,value 是空字符串。天哪,我有多少个程序是基于 explode(‘,’, ”) == array() 写下去的,这下影响大了,得好好查一查。

其次,发现一个不晓得是 sshfs 的 bug 还是 gedit 的 bug。复制错误的过程是:用 Nautilus 或 Dolphin 打开 sshfs 挂载的目录,右击创建一个新文件。文件创建是成功的,属性是 774,用 gedit 打开它却无法保存,提示是没有写权限;但用 kwrite 编辑保存一切正常;用 gedit 再编辑 kwrite 编辑过的文件又能保存。或者,在右击创建一个新文件后,执行一次 chmod 774 filename,也能用 gedit 编辑保存了。

再次,发现在 IE6 下,用 javascript 增大元素的尺寸(比如 jQuery widget 化,增加 border,增加 padding,等),会增大父元素的尺寸。哪怕父元素已用 css 静态赋以宽度值,宽度也会被改变,这是某些精心布局在标准浏览器下很好看,到了 IE6 就面目全非的一大原因。万恶的 IE6 啊,当然从另一方面,说明精心布局仍不够“精心”。为 IE6 布局好比极限运动,挑战好心情的极限;如果看到下属多花一倍时间 fix for IE6,挑战的也是老板的心理极限。

然后,发现 jQuery gallery 里有两个 themes (Humanity, Vader) 的参数不太正常,多了 tr 参数,不知道怎么多出来的,删了似乎没影响。

最后,如果父元素包含所有的子元素都是 float:left 或 float right 的话,不做特殊操作,父元素是没有高度的。父元素的后续元素用一个 clear:both 就能站到该站的位置,但如要为父元素本身画一个边框就稍有难度。最早我用的办法是在这个元素所有的子元素之后增加一个隐形的<div style=”height:0; clear:both;”></div>,但这个硬生生加进去的元素改变了 DOM 结构,破坏了语义,不够 SEO。在 Magento 里学到了另一个方法 :after { clear:both; },如 .clearer 的示例,但要为低版本的 IE 专门写 clear after fix。我维护一份自己的 style.css,override Magento 原版的 style.css。我觉得这个任务就很“繁重”,如果再来一份自己的 style-ie.css,override Magento 原版的 style-ie.css,就为 clear after fix?总觉得小题大作。今天发现一个 clear after all floating children 的 neat solution,就是在父元素上设定 style=”overflow:auto; zoom:1″。overflow 让父元素调整到应有的高度,zoom 也是必须的,否则 IE6…,唉!

最后的最后,发现 z-index 值在 IE6 下被重置的简单通用的 fix。这个问题的来源是若干个 position 后的元素,给它们设定 z-index,IE6 下根本不按设定值 layout,而且还摸不到规律。比如下拉菜单,有时被其他东西给压住。fix 是赋予下拉菜单 z-index 时,赋予父元素(整个菜单)更高的 z-index。

Feed ThemeRoller with current theme parameters

If you are working on jQuery UI site to roll your own theme, you can always load your theme parameters by copying and pasting a long string into address bar, such as:

http://jqueryui.com/themeroller/#ffDefault=Lucida+Grande,+Lucida+Sans,+Arial,+sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=06_inset_hard.png&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=02_glass.png&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=06_inset_hard.png&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px

But, when you are working on your own site, using ThemeRoller Dev Tool for FireFox, you can not load the current page’s theme parameters into ThemeRoller easily. I find two workarounds. I must admit the workarounds are not easy either. There must be some easy “click-to-load” method, but I did not figure it out.

My solutions require FireBug.

Solution One.
1. Copy your theme parameters string to clipboard. The string is as you see before:

ffDefault=Lucida+Grande,+Lucida+Sans,+Arial,+sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=06_inset_hard.png&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=02_glass.png&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=06_inset_hard.png&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px

Please do not include “#” or “?” at the beginning, because when you paste, sometimes it requires a hash separator, sometimes a question mark separator. You’d better enter the separator separately at the time it requires.

2. Launch FireFox, Go to the web page to custom a theme for, Launch ThemeRoller, Launch FireBug

3. Find ThemeRoller <iframe> element, which is inside <div id=”inline_themeroller”> element, change <iframe> src by appending a hash and pasting theme parameters string. In another words, change src from

http://jqueryui.com/themeroller/developertool/appinterface.php

to

http://jqueryui.com/themeroller/developertool/appinterface.php#ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=6px&bgColorHeader=138b14&bgTextureHeader=01_flat.png&bgImgOpacityHeader=75&borderColorHeader=138b14&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=138b14&fcContent=138b14&iconColorContent=222222&bgColorDefault=138b14&bgTextureDefault=03_highlight_soft.png&bgImgOpacityDefault=7…=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=ffffff&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=05_inset_soft.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px

4. By now, you will see ThemeRoller “Roll your own” tab has loaded your custom values. However, the page appearance does not change until you enter any value box and hit Enter out.

Solution Two. It enables you to add your customised theme to ThemeRoller Gallery (temporarily), so you can switch and compare.

1. Same as Solution One

2. Same as Solution One

3. Find an <a> element of a Gallery theme and change its href. For example, the first theme in Gallery, its href is

http://jqueryui.com/themeroller/css/parseTheme.css.php?ffDefault=Trebuchet+MS,+Tahoma,+Verdana,+Arial,+sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=02_glass.png&bgI…gOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px

Change to

http://jqueryui.com/themeroller/css/parseTheme.css.php?ffDefault=Lucida+Grande,+Lucida+Sans,+Arial,+sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=06_inset_hard.png&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=02_glass.png&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=06_inset_hard.png&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px

The thumbnail of the theme won’t change unless you change the src of <img> inside <a>. I assume you won’t bother about changing the thumbnail as long as you know which thumbnail represents your theme.

You can change more than one theme in Gallery to various versions of your theme, so you can click and switch between them quickly.

Lack of jQuery menu UI

I started coding for jqol – thoughts from last week. But I ran into some dilemma.

A very important UI of an eshop is the menu. However, I do not have a mature jQuery UI menu (jQuery menu) widget to use. jQuery menu widget is only available from jQuery UI 1.9, which is still in a stage of milestone 3. The most recent jQuery menu can only theme a flat menu. It can not theme nested (or so called hierarchy) menu. In short, it is useless.

Luckily, Filament Group contributed a very sophisticated jQuery menu UI plugin (fg menu). It can theme flat or hierarchy menu into different styles – flat, flyout, ipod. However, when I try to use it, I find fg menu is based on a different concept to jQuery menu. Fg menu is simulating an OS start menu, and the object being menued is the start button, i.e. use the following code to initialise a menu.

jQuery("button").menu({options}); //menu content inside options

While jQuery menu is exactly a Magento menu, i.e. use the following code to initialise a menu.

jQuery("#nav").menu({options}); //jQuery("#nav").html() itself is the menu content

I am more comfortable taking jQuery core team’s logic, specially in the case of converting Magento menu to jQuery menu widget. Someone from jQuery team has clarified they are of different structures. The status quo is Magento core team’s menu is not completed, but fg menu is something I can use now. So my decision is –

Stay with fg menu for now, and change my code when jQuery menu is mature with all the options I want.

My new thoughts about jQuery in Magento

Today, I have two new thoughts about jQuery in Magento.

Firstly, I will stop using a jQuery plugin called jQuery corner. It is a great plugin though. The reason of withdraw is jQuery corner plugin rounds elements with any radius I can specify on the fly. Once upon a time I thought dynamic cornering a great feature. However, jQuery UI comes with ui-corner classes. It has fixed value of radius for all round corners. It does not let me round different elements to different radius, but guarantees the consistency. In this case, consistency is much more important than flexibility. When I do want make exceptional larger or smaller radius for some kinds of elements (one or two kinds at most), I can code css just for that class.

Secondly, I will start a new Magento module project called Jqol. It reads “JQuery themerOLler”, or “JQuery OnLine” (whatever you feel easier to remember). I am inspired by how easy it is to use jQuery Themeroller to build and change the look and feel of a website. It is a pity Magento does not come with jQuery. I keep mention it because I can not live without jQuery (for now). I implemented jQuery the very first thing when I started diving into Magento. While jQuery is getting stronger and more popular, I would like it play more important role in Magento. Therefore, I will let jQuery Themeroller control the look and feel for the top menu, buttons, accordion, tabs, etc. I can imagine a lot of benefits from this module: cleaner code, more semantic, and I (or even visitors to my sites) can switch the jQuery themes easily.