DRY Modals

Sharing common markup and behavior for modals in Ember.js

by fangyang

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0-rc.3/handlebars.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/ember.js/1.0.0-rc.2/ember.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-modal/2.1.0/bootstrap-modal.pack.js"></script>
<script type="text/x-handlebars" data-template-name="application">
    <h1>Modals</h1>
    {{#linkTo precious.m1 class="btn btn-success"}}Modal 1{{/linkTo}}
    {{#linkTo precious.m2 class="btn btn-success"}}Modal 2{{/linkTo}}
    
    {{ outlet }}
</script>

<script type="text/x-handlebars" data-template-name="modal_layout">
<div class="modal fade in form-custom-field-modal">
    <div class="modal-header">
        <div class="button close btn-dismiss" {{action cancel }}>x</div>
        <h2 class="app-icon-large">{{view.name}}</h2>
    </div>
         
    <div class="modal-body">
      {{yield}}        
    </div>
 
    <div class="modal-footer">
        <button class="btn btn-dark" {{action cancel }}>Cancel</button>
        <button class="btn btn-success" type="submit"  {{action submit }}>Ok</button>
    </div>  
</div>
</script>

<script type="text/x-handlebars" data-template-name="precious/m1">
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ac sem tempor augue pulvinar posuere id eu ligula. Cras ultrices tincidunt enim quis condimentum. Donec vehicula, dui a fermentum elementum, lacus nisl vulputate turpis, in venenatis massa elit ac diam. Nullam viverra convallis turpis at posuere. Nunc at nunc odio, vitae auctor quam. Aliquam egestas rhoncus tristique. Donec accumsan lobortis dui, eget convallis mauris posuere placerat. Vestibulum auctor ultrices metus, sed laoreet sem euismod in. Fusce dui mauris, pharetra a scelerisque nec, aliquet et sem. Pellentesque sed magna at nulla viverra mattis volutpat eget ipsum. Suspendisse in neque vel felis egestas eleifend. Nulla tincidunt, tortor in dapibus viverra, erat urna viverra orci, a congue nisi massa at...

CSS

body {
    padding: 2em;
}

/*!
 * Bootstrap v2.3.1
 *
 * Copyright 2012 Twitter, Inc
 * Licensed under the Apache License v2.0
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Designed and built with all the love in the world @twitter by @mdo and @fat.
 */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{width:auto\9;height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img,.google-maps img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,html...

JavaScript

//http://www.youtube.com/watch?v=KLacfF8P-OI
window.App = Ember.Application.create();

App.Router = Ember.Router.extend();
App.Router.map( function () {
    this.resource("precious", function () {
        this.route("m1");
        this.route("m2");
    });
});

/*
 * Common Modal View
 * 
 * Specifies a layout and shared behavior for
 * modal views. It is not directly instantiated,
 * but is extended.
 */
App.CommonModalView = Ember.View.extend({
    layoutName: 'modal_layout',
    
    didInsertElement: function() {
      this.$().modal('show');
    },
    
    willDestroyElement: function() {
      this.$().modal('hide');
    }
});

/*
 * Modal Views
 *
 * Extend CommonModalView, specify a unique title,
 * and load separate content in different templates.
 */
App.PreciousM1View = App.CommonModalView.extend({
    name: "Ooooo a modal!"
});
App.PreciousM2View = App.CommonModalView.extend({
    name: "Another Modal"
});

/*
 * Modal Route
 *
 * Share modal behavior in the parent resource
 * route.
 */
App.PreciousRoute = Ember.Route.extend({
    events: {
        cancel: function() {
            this.transitionTo('index');
        },
        
        submit: function() {
            this.transitionTo('index');
        }
    }
});