By researching, I've found some answers and tutorials that suggest me to hack to Core code. Eg: add some additional functions like addItemAfter($after, ...)
, addItemFirst(...)
But I think it's not ideal solution.
By looking into Mage_Page_Block_Html_Head
class, function getCssJsHtml
, I found this line:
$lines[$if][$item['type']][$params][$item['name']] = $item['name'];
It means, css/js files are grouped by its condition. Files with same condition are added into the same group.
So, I think, you can use file's condition like a hook.
According to MSDN document, you can use some conditional comments like this:
<!--[if (gte IE 9) | (IEMobile)]><!-->
Or if you want it to always return true, just use <!--[if true]><!-->
Let's go.
First, declare the hooks.
- Create a blank js file (or css file). Eg:
skin/frontend/your_package/your_theme/js/blank.js
. Leave it empty content.
- Open
app/design/frontend/your_package/your_theme/layout/page.xml
- In default handle (
<default translate="label" module="page">
), block head
, seek to last current js files (or css files if you want), add:
<action method="addItem">
<type>skin_js</type>
<name>js/blank.js</name>
<params/>
<if><![CDATA[<!--[if true]><!-->]]></if>
</action>
You must to specify a file name, because it's just a hook, use a blank file, so it doesn't affect to performance, especially when you turn on Merge mode.
Second, and last, use the hooks.
In your specific handle, eg. catalog_category_default
(Category page), add js/css file with the same condition you just declared.
<reference name="head">
<action method="addItem">
<type>skin_js</type>
<name>js/your.custom.js.file.js</name>
<params/>
<if><![CDATA[<!--[if true]><!-->]]></if>
</action>
</reference>
Now, load a category page and view it's source. You see:
<!--[if true]><!-->
<script type="text/javascript" src="http://example.com/skin/frontend/your_package/your_theme/js/blank.js"></script>
<script type="text/javascript" src="http://example.com/skin/frontend/your_package/your_theme/js/your.custom.js.file.js"></script>
<!--<![endif]-->
Your custom file is loaded in the same condition with the hook. Because the hook is at bottom of default files, so your custom file is at bottom as well.
It's done.
P/s: I don't know if it's valid, but actually, you can use any condition, like this <!--[if hook_one]><!-->
, <!--[if hook_two]><!-->
So, whenever you want to add js/css files into a desire place, just go to the root page (or parent page), declare a hook, then use it in custom handle. It's simple.