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);
});
});
}
}
}
};
}]);