Angular Hallo Directive

Directive for easy implementation of Hallo Content Editing.

HTML

<link rel="stylesheet" href="https://raw.github.com/bergie/hallo/master/examples/hallo.css">
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/font-awesome/3.0.2/css/font-awesome.css">
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css">
<script src="http://code.jquery.com/ui/1.10.2/jquery-ui.js"></script>
<script src="http://code.angularjs.org/1.1.3/angular.js"></script>
<script src="https://raw.github.com/bergie/hallo/master/deps/rangy-core-1.2.3.js"></script>
<script src="https://raw.github.com/bergie/hallo/master/examples/hallo.js"></script>
<div ng-controller="MainCtrl">
    <h1>{{ title }}</h1>
    <hr />
    <div class="alert alert-block" hallo>
        <p><a href="http://hallojs.org/">HalloJs</a> is a really cool take on content editing.</p>
        <p>While working on a client project the need for a "WYSIWYG" editor surfaced and, like other developers out there, I shuddered.</p>
        <p>WYSIWYG editors are notoriously evil; clients misuse the elements, html entities are implemented incorrectly, white backrounds end up with neon green text... fun stuff</p>
        <p><a href="http://hallojs.org/">HalloJs</a> lets me add a dead simple editor to any element on the page and, coupled with angular js, I can bind the changes to that element to a model and pass that on to ajax to update data! Winning</p>
    </div>
    <hr />
    <div hallo="{ toolbar: 'halloToolbarFixed', plugins: { 'halloformat': { 'bold' : true }, 'halloheadings': {}, 'halloreundo': {}, 'hallolists': {}, 'halloindicator': {} } }" ng-model="content">
    </div>
</div>

CSS

body { margin: 15px; }


/**
** Hallo Styles (wont load thru github
**/
div.hallotoolbar {
    border: 1px solid #babdb6;
    padding: 2px;
    background-color: #eeeeec;
    border-radius: 6px;
    font-size: 12pt;
    line-height: 1.1em;
    z-index: 500;
}

div.halloEditIndicator {
    background-color: #000000;
    color: #ffffff;
    padding: 4px;
    border-radius: 4px;
}

/* Drag n Drop */
[contenteditable] .tmp {
    opacity: 0.3
}

[contenteditable] .tmpLine{
    background-color: #ffffff;
    width: 98%;
    height: 2px;
    margin: 0 auto 10px auto;
    border-top: 2px solid #1cb8d6;
    border-bottom: 2px solid #1cb8d6;
    opacity: 1;
    padding: 1px;
}

.dropdown-menu {
    width: "200px";
    background-color: #eeeeec;
}

.dropdown-target .selected {
    background-color: #729fcf;
}

button.blockselector, button.blockselector:focus{
	display:block;
	width: 100%;
	margin:0px;
	padding: 0px;
	background: transparent;
	border: none;
	-moz-appearance: none;
	-webkit-appearance: none;
	outline: none;
}

.bigOverlay, .smallOverlay {
    display: none;
    position: absolute;
    top: 0;
    left: 0;
    background-color: rgba(28, 184, 214, 0.4);
}

.bigOverlayRight{
    display : block;
    border-right : 3px dashed rgb(28, 184, 214);
    border-left : none;
}

.bigOverlayLeft{
    display : block;
    border-left : 3px dashed rgb(28, 184, 214);
    border-right : none;
}

.smallOverlayLeft{
   border-right : 3px dashed rgb(28, 184, 214);
}

.smallOverlayRight{
    border-left : 3px dashed rgb(28, 184, 214);
}

.ui-draggable{
    cursor: move;
}

.ui-draggable-dragging{
    border: 3px solid white;
}

[contenteditable] img.ui-state-disabled {
    opacity: 1;
}

.customHelper{
    background-size: cover;
    width: 100px;
    height: 100px;
    z-index: 1050;
}

.trashcan{
    width: 50px;
    height: 50px;
    position: relative;
    top: 25px;
    left: 25px;
    background: rgba(0,0,0,0.8) url('images/trash.png') no-repeat 12px 12px;
   ...

JavaScript

var app = angular.module('myApp', []);

app.controller('MainCtrl', function($scope) {
    
    $.extend($scope,{
        title: 'Hallo Directive',
        content: "<h3>I'm editable</h3><p>Don't believe me? Just click this block and start typing!</p><p>Assuming you just dasdfid, how cool is that?!</p>"
    });
    
});

app.directive('hallo', ['$parse', function($parse){

	/**
	 * This directive allows for easy implementation 
	 * of the hallo content editing plugin
	 */
	return {
		restrict: 'AC',
		scope: true,
		compile: function(tElement, tAttrs) {
			return function(scope, elm, attr) {
              
				var params = scope.$eval(attr.hallo),
                    bound = angular.isDefined(attr.ngModel),
                    contents = bound ? scope.$eval(attr.ngModel) : elm.html();
                					
				elm
					.hallo(params)
					.html(contents)
					.addClass('editable');
                
                if(bound) {
                    model = $parse(attr.ngModel);
				    elm.bind('hallomodified', function(event, data) {
				    	scope.$apply(function(){
                            contents = data.content;
					    	model.assign(scope, contents);
					    });
				    });
                }

			}
		}
	};

}]);