Created
August 9, 2012 03:21
-
-
Save joshkurz/3300629 to your computer and use it in GitHub Desktop.
AngularJs-twitterBootstrap-wysiHtml5
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var demoApp = angular.module('demoApp', ['ngResource'], function($locationProvider) { | |
$locationProvider.hashPrefix(''); | |
}); | |
function MainCtrl($scope, Serv) { | |
$scope.selectedItem = { | |
value: 0, | |
label: '' | |
}; | |
$scope.Wrapper = Serv; | |
} | |
demoApp.directive('richTextEditor', function( $log, $location ) { | |
var self = this; | |
var directive = { | |
restrict : "A", | |
replace : true, | |
transclude : true, | |
scope : { | |
}, | |
template : | |
"<div>" + | |
"<textarea id=\"richtexteditor-content\" style=\"height:300px;width:100%\"></textarea>"+ | |
"</div>", | |
link : function( $scope, $element, $attrs ) { | |
$scope.editor = $('#richtexteditor-content').wysihtml5(); | |
// $scope.editor = new wysihtml5.Editor( "richtexteditor-content", { | |
// toolbar : "richtexteditor-toolbar", | |
// parserRules: wysihtml5ParserRules | |
// }); | |
$scope.$parent.$watch( $attrs.content, function( newValue, oldValue ) { | |
$scope.editor.innerHTML = newValue; | |
$scope.editor.composer.setValue( newValue ); | |
}); | |
$scope.cancel = function() { | |
$scope.$parent.cancel(); | |
} | |
/* $scope.save = function() { | |
var currentTemplateContent = $encryption.encodeHtml( $scope.editor.getValue() ); | |
$scope.$parent.currentTemplate.content = currentTemplateContent; | |
$scope.$parent.save(); | |
} | |
*/ | |
$scope.isClean = function() { | |
$scope.$parent.isClean(); | |
} | |
} | |
} | |
return directive; | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ul.wysihtml5-toolbar { | |
margin: 0; | |
padding: 0; | |
display: block; | |
} | |
ul.wysihtml5-toolbar::after { | |
clear: both; | |
display: table; | |
content: ""; | |
} | |
ul.wysihtml5-toolbar > li { | |
float: left; | |
display: list-item; | |
list-style: none; | |
margin: 0 5px 10px 0; | |
} | |
ul.wysihtml5-toolbar a[data-wysihtml5-command=bold] { | |
font-weight: bold; | |
} | |
ul.wysihtml5-toolbar a[data-wysihtml5-command=italic] { | |
font-style: italic; | |
} | |
ul.wysihtml5-toolbar a[data-wysihtml5-command=underline] { | |
text-decoration: underline; | |
} | |
ul.wysihtml5-toolbar a.btn.wysihtml5-command-active { | |
background-image: none; | |
-webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05); | |
-moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05); | |
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05); | |
background-color: #E6E6E6; | |
background-color: #D9D9D9 9; | |
outline: 0; | |
} | |
ul.wysihtml5-commands-disabled .dropdown-menu { | |
display: none !important; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
!function($, wysi) { | |
"use strict"; | |
var templates = { | |
"font-styles": "<li class='dropdown'>" + | |
"<a class='btn dropdown-toggle' data-toggle='dropdown' href='#'>" + | |
"<i class='icon-font'></i> <span class='current-font'>Normal text</span> <b class='caret'></b>" + | |
"</a>" + | |
"<ul class='dropdown-menu'>" + | |
"<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='div'>Normal text</a></li>" + | |
"<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='h1'>Heading 1</a></li>" + | |
"<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='h2'>Heading 2</a></li>" + | |
"</ul>" + | |
"</li>", | |
"emphasis": "<li>" + | |
"<div class='btn-group'>" + | |
"<a class='btn' data-wysihtml5-command='bold' title='CTRL+B'>Bold</a>" + | |
"<a class='btn' data-wysihtml5-command='italic' title='CTRL+I'>Italic</a>" + | |
"<a class='btn' data-wysihtml5-command='underline' title='CTRL+U'>Underline</a>" + | |
"</div>" + | |
"</li>", | |
"lists": "<li>" + | |
"<div class='btn-group'>" + | |
"<a class='btn' data-wysihtml5-command='insertUnorderedList' title='Unordered List'><i class='icon-list'></i></a>" + | |
"<a class='btn' data-wysihtml5-command='insertOrderedList' title='Ordered List'><i class='icon-th-list'></i></a>" + | |
"<a class='btn' data-wysihtml5-command='Outdent' title='Outdent'><i class='icon-indent-right'></i></a>" + | |
"<a class='btn' data-wysihtml5-command='Indent' title='Indent'><i class='icon-indent-left'></i></a>" + | |
"</div>" + | |
"</li>", | |
"link": "<li>" + | |
"<div class='bootstrap-wysihtml5-insert-link-modal modal hide fade'>" + | |
"<div class='modal-header'>" + | |
"<a class='close' data-dismiss='modal'>×</a>" + | |
"<h3>Insert Link</h3>" + | |
"</div>" + | |
"<div class='modal-body'>" + | |
"<input value='http://' class='bootstrap-wysihtml5-insert-link-url input-xlarge'>" + | |
"</div>" + | |
"<div class='modal-body'>" + | |
"<h5>Anchor Text</h5>" + | |
"<input value='' class='anchorText input-xlarge'>" + | |
"</div>" + | |
"<div class='modal-footer'>" + | |
"<a href='#' class='btn' data-dismiss='modal'>Cancel</a>" + | |
"<a href='#' class='btn btn-primary2' data-dismiss='modal'>Insert link</a>" + | |
"</div>" + | |
"</div>" + | |
"<a class='btn' data-wysihtml5-command='createLink' title='Link'><i class='icon-share'></i></a>" + | |
"</li>", | |
"image": "<li>" + | |
"<div class='bootstrap-wysihtml5-insert-image-modal modal hide fade'>" + | |
"<div class='modal-header'>" + | |
"<a class='close' data-dismiss='modal'>×</a>" + | |
"<h3>Insert Image</h3>" + | |
"</div>" + | |
"<div class='modal-body'>" + | |
"<input value='http://' class='bootstrap-wysihtml5-insert-image-url input-xlarge'>" + | |
"</div>" + | |
"<div class='modal-footer'>" + | |
"<a href='#' class='btn' data-dismiss='modal'>Cancel</a>" + | |
"<a href='#' class='btn btn-primary' data-dismiss='modal'>Insert image</a>" + | |
"</div>" + | |
"</div>" + | |
"<a class='btn' data-wysihtml5-command='insertImage' title='Insert image'><i class='icon-picture'></i></a>" + | |
"</li>", | |
"html": | |
"<li>" + | |
"<div class='btn-group'>" + | |
"<a class='btn' data-wysihtml5-action='change_view' title='Edit HTML'><i class='icon-pencil'></i></a>" + | |
"</div>" + | |
"</li>" | |
}; | |
var defaultOptions = { | |
"font-styles": true, | |
"emphasis": true, | |
"lists": true, | |
"html": true, | |
"link": true, | |
"image": true, | |
events: {}, | |
parserRules: { | |
tags: { | |
"b": {}, | |
"i": {}, | |
"br": {}, | |
"ol": {}, | |
"ul": {}, | |
"li": {}, | |
"h1": {}, | |
"h2": {}, | |
"blockquote": {}, | |
"u": 1, | |
"img": { | |
"check_attributes": { | |
"width": "numbers", | |
"alt": "alt", | |
"src": "url", | |
"height": "numbers" | |
} | |
}, | |
"a": { | |
set_attributes: { | |
target: "_blank", | |
rel: "nofollow" | |
}, | |
check_attributes: { | |
href: "url" // important to avoid XSS | |
} | |
} | |
} | |
}, | |
stylesheets: [] | |
}; | |
var Wysihtml5 = function(el, options) { | |
this.el = el; | |
this.toolbar = this.createToolbar(el, options || defaultOptions); | |
this.editor = this.createEditor(options); | |
window.editor = this.editor; | |
$('iframe.wysihtml5-sandbox').each(function(i, el){ | |
$(el.contentWindow).off('focus.wysihtml5').on({ | |
'focus.wysihtml5' : function(){ | |
$('li.dropdown').removeClass('open'); | |
} | |
}); | |
}); | |
}; | |
Wysihtml5.prototype = { | |
constructor: Wysihtml5, | |
createEditor: function(options) { | |
options = $.extend(defaultOptions, options || {}); | |
options.toolbar = this.toolbar[0]; | |
var editor = new wysi.Editor(this.el[0], options); | |
if(options && options.events) { | |
for(var eventName in options.events) { | |
editor.on(eventName, options.events[eventName]); | |
} | |
} | |
return editor; | |
}, | |
createToolbar: function(el, options) { | |
var self = this; | |
var toolbar = $("<ul/>", { | |
'class' : "wysihtml5-toolbar", | |
'style': "display:none" | |
}); | |
for(var key in defaultOptions) { | |
var value = false; | |
if(options[key] !== undefined) { | |
if(options[key] === true) { | |
value = true; | |
} | |
} else { | |
value = defaultOptions[key]; | |
} | |
if(value === true) { | |
toolbar.append(templates[key]); | |
if(key == "html") { | |
this.initHtml(toolbar); | |
} | |
if(key == "link") { | |
this.initInsertLink(toolbar); | |
} | |
if(key == "image") { | |
this.initInsertImage(toolbar); | |
} | |
} | |
} | |
toolbar.find("a[data-wysihtml5-command='formatBlock']").click(function(e) { | |
var el = $(e.srcElement); | |
self.toolbar.find('.current-font').text(el.html()); | |
}); | |
this.el.before(toolbar); | |
return toolbar; | |
}, | |
initHtml: function(toolbar) { | |
var changeViewSelector = "a[data-wysihtml5-action='change_view']"; | |
toolbar.find(changeViewSelector).click(function(e) { | |
toolbar.find('a.btn').not(changeViewSelector).toggleClass('disabled'); | |
}); | |
}, | |
initInsertImage: function(toolbar) { | |
var self = this; | |
var insertImageModal = toolbar.find('.bootstrap-wysihtml5-insert-image-modal'); | |
var urlInput = insertImageModal.find('.bootstrap-wysihtml5-insert-image-url'); | |
var insertButton = insertImageModal.find('a.btn-primary2'); | |
var initialValue = urlInput.val(); | |
var insertImage = function() { | |
var url = urlInput.val(); | |
urlInput.val(initialValue); | |
self.editor.composer.commands.exec("insertImage", url); | |
}; | |
urlInput.keypress(function(e) { | |
if(e.which == 13) { | |
insertImage(); | |
insertImageModal.modal('hide'); | |
} | |
}); | |
insertButton.click(insertImage); | |
insertImageModal.on('shown', function() { | |
urlInput.focus(); | |
}); | |
insertImageModal.on('hide', function() { | |
self.editor.currentView.element.focus(); | |
}); | |
toolbar.find('a[data-wysihtml5-command=insertImage]').click(function() { | |
insertImageModal.modal('show'); | |
insertImageModal.on('click.dismiss.modal', '[data-dismiss="modal"]', function(e) { | |
e.stopPropagation(); | |
}); | |
return false; | |
}); | |
}, | |
initInsertLink: function(toolbar) { | |
var self = this; | |
var insertLinkModal = toolbar.find('.bootstrap-wysihtml5-insert-link-modal'); | |
var urlInput = insertLinkModal.find('.bootstrap-wysihtml5-insert-link-url'); | |
var anchorText = insertLinkModal.find('.anchorText'); | |
var insertButton = insertLinkModal.find('a.btn-primary2'); | |
var initialValue = urlInput.val(); | |
var insertLink = function() { | |
var url = urlInput.val(); | |
urlInput.val(anchorText.val()); | |
self.editor.composer.commands.exec("createLink", { | |
href: url, | |
target: "_blank", | |
rel: "nofollow", | |
value: anchorText.val(), | |
}); | |
}; | |
var pressedEnter = false; | |
urlInput.keypress(function(e) { | |
if(e.which == 13) { | |
insertLink(); | |
insertLinkModal.modal('hide'); | |
} | |
}); | |
insertButton.click(insertLink); | |
insertLinkModal.on('shown', function() { | |
urlInput.focus(); | |
}); | |
insertLinkModal.on('hide', function() { | |
self.editor.currentView.element.focus(); | |
}); | |
toolbar.find('a[data-wysihtml5-command=createLink]').click(function() { | |
insertLinkModal.modal('show'); | |
insertLinkModal.on('click.dismiss.modal', '[data-dismiss="modal"]', function(e) { | |
e.stopPropagation(); | |
}); | |
return false; | |
}); | |
} | |
}; | |
$.fn.wysihtml5 = function (options) { | |
return this.each(function () { | |
var $this = $(this); | |
$this.data('wysihtml5', new Wysihtml5($this, options)); | |
}); | |
}; | |
$.fn.wysihtml5.Constructor = Wysihtml5; | |
}(window.jQuery, window.wysihtml5); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script type="text/javascript" src="http://docs.angularjs.org/angular-resource-1.0.1.min.js"></script> | |
<script type="text/javascript" src="bootstrap-wysiHtml5.js"></script> | |
<link rel="stylesheet" type="text/css" href="http://angular-ui.github.com/lib/bootstrap/docs/assets/css/bootstrap.css" > | |
<link rel="stylesheet" type="text/css" href="bootstrap-wysiHtml5.css" > | |
<div lang="en" ng-app="demoApp" ng-controller="MainCtrl"> | |
<div rich-text-editor></div> | |
<button class="btn btn-primary">Click Me</button> | |
</div> | |
|
@joshkurz, what about Serv injection in the MainCtrl? I don't see any provider code...
Templates text style making problem , the hash tag redirect the root url ("<a class='btn dropdown-toggle' data-toggle='dropdown' href='#'>" ) please share a solution
i Got error :
angular.js:13236 TypeError: **Cannot read property 'Editor' of undefined**
at Wysihtml5.createEditor (http://localhost:42336/Scripts/bootstrap-wysihtml5.js:141:34)
at new Wysihtml5 (http://localhost:42336/Scripts/bootstrap-wysihtml5.js:120:28)
at HTMLTextAreaElement.<anonymous> (http://localhost:42336/Scripts/bootstrap-wysihtml5.js:296:37)
at Function.each (http://localhost:42336/Scripts/jquery-2.2.0.js:360:19)
at jQuery.each (http://localhost:42336/Scripts/jquery-2.2.0.js:137:17)
at jQuery.$.fn.wysihtml5 (http://localhost:42336/Scripts/bootstrap-wysihtml5.js:294:21)
at link (http://localhost:42336/Scripts/App/app.js:127:70)
at http://localhost:42336/Scripts/angular.min.js:78:461
at ka (http://localhost:42336/Scripts/angular.min.js:79:16)
at u (http://localhost:42336/Scripts/angular.min.js:66:326) <div rich-text-editor="" class="ng-isolate-scope">
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@NenadP - I have the same problem with similar directive - the users paste from Word and everything stops working.