Adding Bootstrap theme template files to your custom Magento theme

Last post, I created my own cusomised Magento theme. It looks crap, but it works! Instructions here https://delboy1978uk.wordpress.com/2015/06/04/creating-custom-magento-themes/ In this post, I am going to take my fancy bootstrap 3 store template, and integrate it in to our newly created theme. The first stage is learning how the templates all work, so we’ll bring in the js and css, and make our own header until we get the hang of it. Then we can take the HTML from our template and add it in. But first things first.

fashion

The theme I downloaded has Bootstrap 3, but not the latest version, so I’m grabbing the latest from http://getbootstrap.com/getting-started/#download.

Once downloaded, copy the following files into your theme in /skin/frontend/fashion/default :

/css
    /bootstrap.min.css
/js
    /bootstrap.min.js
/fonts
    /glyphicons-halflings-regular.eot
    /glyphicons-halflings-regular.svg
    /glyphicons-halflings-regular.ttf
    /glyphicons-halflings-regular.woff

Stick your jquery.min.js in /js/lib/jquery.  There’s already a jQuery in there, but yours might be newer. You’ll notice a noconflict.js too. That stops jQuery and Prototype from conflicting with one another.
Ok, now we’ve done that, we need to configure our /app/design/frontend/fashion/default/layout/local.xml file. Javascript & Css go in our head block. So lets add it:

<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
 * local.xml
 * Local layout modifications for our local theme
 * @category    design
 * @package     fashion
 * @copyright   Copyright (c) 2015 delboy1978uk.
 */
-->
<layout version="0.1.0">
    <default>
        <reference name="head">
            <action method="addJs"><script>js/lib/jquery.min.js</script></action>
            <action method="addJs"><script>js/lib/jquery/noconflict.js</script></action>
            <action method="addItem"><type>skin_js</type><name>js/bootstrap.min.js</name></action>
            <action method="addItem"><type>skin_css</type><name>css/bootstrap.min.css</name></action>
            <action method="addItem"><type>skin_css</type><name>css/styles.css</name></action>
            <action method="addItem"><type>skin_css</type><name>css/styles-ie.css</name></action>
        </reference>
    </default>
</layout

As you know, the C of CSS stands for cascading. The styles.css in the base theme will be called first, which obviously is unwanted behaviour which could cause class conflicts, so we really want to stop the base theme from loading it. So add this line before the bootstrap.min.css line :

<!-- Remove base theme styles.css --> 
<action method="removeItem"><type>skin_css</type><name>css/styles.css</name></action>

Now let’s deal with the world’s shittiest, least standards compliant browser out there (if you can call it a browser) : Internet Explorer.  The usual suspects apply here, namely https://oss.maxcdn.com/libs/respond.js/1.3.0/ respond.min.js & https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js . Download them into the theme js folder, and add them under that bootstrap js line (notice the params bit):

<action method="addItem"><type>skin_js</type><name>js/html5shiv.js</name><params/><if>lt IE 9</if></action>
<action method="addItem"><type>skin_js</type><name>js/respond.min.js</name><params/><if>lt IE 9</if></action>

You can also add a config section specifically for print, so here’s what to add after the reference=”head” section:

<print translate="label" module="page">
    <label>All Pages (Print Version)</label>
    <!-- Mage_Page -->
    <block type="page/html" name="root" output="toHtml" template="page/print.phtml">

        <!-- This block allows the print.phtml template to get the logo -->
        <block type="page/html_header" name="header" as="header"/>

        <block type="page/html_head" name="head" as="head">

            <action method="addCss"><stylesheet>css/styles.css</stylesheet></action>
            <action method="addItem"><type>skin_css</type><name>css/styles-ie.css</name><params/><if>lt IE 8</if></action>
            <action method="addCss"><stylesheet>css/widgets.css</stylesheet></action>
            <action method="addItem"><type>skin_css</type><name>css/print.css</name></action>
        </block>

        <block type="core/text_list" name="content" as="content" translate="label">
            <label>Main Content Area</label>
        </block>

    </block>
</print>

Now we add our ‘root’ template file. At the top, in the default node but above the <reference name=”head”> node, add the following (for the example I’m using the 2 col layout):

<reference name="root">
      <action method="setTemplate">
          <template>page/2columns-left.phtml</template>
      </action>
</reference>

Great! Now it’s time to rip apart the .phtml files we copied over from the base theme! Open /app/design/frontend/fashion/default/template/page/2columns-left.phtml

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $this->getLang() ?>" lang="<?= $this->getLang() ?>">

    <head>
        <?= $this->getChildHtml('head') ?>
    </head>

    <body<?= $this->getBodyClass() ? ' class="'.$this->getBodyClass().'"' : null; ?>>
        <?= $this->getChildHtml('after_body_start') ?>
        <?= $this->getChildHtml('global_notices'); ?>
        <header>
            <?= $this->getChildHtml('header'); ?>
        </header>
        <section id="after-header">
            <div class="container">
                <?= $this->getChildHtml('slider'); ?>
            </div>
        </section>
        <section id="maincontent">
            <div class="container">
                <div class="row">
                    <?= $this->getChildHtml('breadcrumbs'); ?>
                    <aside class="col-left sidebar col-md-3">
                        <?= $this->getChildHtml('left'); ?>
                    </aside>
                    <div class="col-main col-md-9">
                        <?= $this->getChildHtml('global_messages'); ?>
                        <?= $this->getChildHtml('content'); ?>
                    </div>
                </div>
            </div>
        </section>
        <footer id="footer">
            <div class="container">
                <?= $this->getChildHtml('footer'); ?>
            </div>
        </footer>
        <?= $this->getChildHtml('before_body_end'); ?>
        <?= $this->getChildHtml('global_cookie_notice'); ?>
        <?= $this->getAbsoluteFooter(); ?>
    </body>

</html>

Okay, do the same for the other template files too! You know the score! Ditch the Magento markup and replace with BS3 awesomeness!
Check out my next post where we’ll start editing the view files and creating blocks etc!

 

Advertisements

Hide Magento header mini-cart window by clicking outside

This was really annoying me as I found a nice lib which worked called jquery-outside-events , which I forked onto my own Github (could be tidier/easier imho) but it wouldn’t work! The reason I think was possibly it was conflicting with Prototype JS, which Magento uses.

The $ symbol is reserved for Prototype so I found I had to replace $(‘#etc’); with jQuery(‘#etc’); Since doing that however I’ve discovered you can call $j instead of $ or jQuery.

Anyway! Here’s the code you need:

$j('body').click(function (event)
{
    element = $j(event.target);
    if(element.parents('.skip-link.skip-cart').length == 1 || element.hasClass('skip-cart'))
    {
        return;
    }
    var parent = $j('.minicart-wrapper').parents('.skip-content');
    var link = parent.siblings('.skip-link');

    if (element.parents('.minicart-wrapper').length == 0) {
        parent.removeClass('skip-active');
        link.removeClass('skip-active');
    }
});

Now when you click show basket, the basket appears, but you can now click elsewhere on the page to make it close again!

TypeError: $(…).ready is not a function

Ever seen that message? I have, but thought I’d let you know what’s going on, as I just encountered it again in a Magento site I’m working on in my new workplace.

When this happens, it’s usually because of a clash between some other javascript library that uses the $ symbol. In Magento’s case, that’s Prototype JS (http://prototypejs.org/).

To sort it, you just need to replace all your $’s with jQuery, like so:

jQuery(document).ready(function(){
    // etc
});

You can also say var $j = jQuery, then use $j(‘#id’); instead 😀

jQuery UI Datepickers with Bootstrap Modals

If you’re here, that’s probably because you just put a datepicker into a bootstrap modal, but realised that the Year dropdown isn’t working properly, and when you click it, nothing appears to happen.

Luckily, it’s quite easy to fix. After initialising your element with

$('#mytextbox').datepicker({//options here});

All that is required is to paste this line of code, which does something regarding javascript’s dom focus :

$.fn.modal.Constructor.prototype.enforceFocus = function() {}

Job done! You can get back on with your work now! 🙂

jQuery Form Submit Handling with Return Key

If you have ever done any stuff with jquery/javascript that redirects you upon submitting a form, you’ll have noticed that the return key slips through the net and doesn’t obviously trigger the click event.
I’ve dealt with this nonsense plenty of times but i always end up hunting through my code to find it again. So to spare my sanity, I’m putting it here!

$('#submit').click(function(e){
 e.preventDefault();
 var name = $('#search').val();
 window.location.href = '/some/url/'+name;
 });
$("#search").keyup(function(event){
 if(event.keyCode == 13){
 $("#submit").click();
 }
 });

Using Tiny MCE javascript WYSIWYG

Just some quick notes.
Firstly, don’t give your customers all those buttons! They will end up breaking something!
Secondly, although they bang on about a jQuery version, I just could not get it to work!
Probably the most important factor here is adding images etc. Without buying some $50 plugin, its actually one line of code!
Anyway, here’s a typical setup from one of my sites:

<script type="text/javascript" src="/js/tiny_mce/tiny_mce.js"></script>
<script type="text/javascript">

$(document).ready(function() {
tinyMCE.init({
plugins : '-example', // - tells TinyMCE to skip the loading of the plugin
    mode : "textareas",
    theme : "advanced",
    theme_advanced_blockformats : "p,div,h1,h2,h3,h4,h5,h6,blockquote,dt,dd,code,samp",
    theme_advanced_buttons1 : "image, bold,italic,underline,separator,strikethrough,justifyleft,justifycenter,justifyright,justifyfull,bullist,numlist,undo,redo,link,unlink,formatselect,code",
    theme_advanced_buttons2 : "",
    theme_advanced_buttons3 : "",
    theme_advanced_toolbar_location : "top",
    theme_advanced_toolbar_align : "left",
    theme_advanced_statusbar_location : "bottom",
 editor_encoding: "raw",
    remove_linebreaks : false,
    convert_newlines_to_brs : true

// Example content CSS (should be your site CSS)
content_css : "css/style.css",

});

//adding your images ionto the tinmce window
$('#click').click(function(){
img = '<img src="http://your/url/to/image.jpg" />';
tinyMCE.execCommand('mceInsertContent',false,img);
});
});
</script>

Stop jQuery slideUp slideDown madness!

Ever made a jquery slider only to find that when you mouse over your menu items quickly you need to wait until it all catches up with itself? you need to .stop()!

<ul id="nav">
<li>
<a href="/about/opening-times">About Us</a>
<ul class="submenu" style="display: none;">
<li><a href="/about/opening-times">Opening Times</a></li>
<li><a href="/about/key-people">Key People</a></li>
<li><a href="/about/awards">Awards</a></li>
</ul>
</li>
<li>
<a href="/our-tea/list">Our Tea</a>
<ul class="submenu" style="display: none;">
<li><a href="/our-tea/list">List of our teas</a></li>
<li><a href="/our-tea/tea-guild">Information on the tea guild</a></li>
<li><a href="/our-tea/info">Information on purchase of tea</a></li>
</ul>
</li>
<li><a href="/menus">Menus</a></li>
<li>
<a href="/afternoon-tea/history">Afternoon Tea</a>
<ul class="submenu" style="display: none;">
<li><a href="/afternoon-tea/history">History of afternoon tea</a></li>
<li><a href="/afternoon-tea/our-offerings">Our offerings</a></li>
<li><a href="/afternoon-tea/menus">Menus</a></li>
</ul>
</li>
<li><a href="/events">Events</a></li>
<li><a href="/gallery">Gallery</a></li>
<li><a href="/private-hire">Private Hire</a></li>
<li><a href="/testimonials">Testimonials</a></li>
</ul>
<script type="text/javascript">
$(document).ready(function(){
$('ul#nav li').hover(function()
{
$(this).find('ul.submenu').stop(true, true).slideDown('slow'); }, 
function() {$(this).parent().find('ul.submenu').stop(true, true).slideUp('slow');
});
});
</script>

And that should take care of it!