Anonymous avatar Anonymous committed aedb654

Mass renaming + some tweaking

Comments (0)

Files changed (127)

eag-static/css/MooEditable/Editable.css

+table { border: 1px dashed #BBBBBB; font:inherit; }
+table td, table th { border: 1px dashed #BBBBBB; }
+table th { font-weight:bold ; }
+object { display:block; border: 1px dashed gray; background: url(Other/flash.png) no-repeat center center; }

eag-static/css/MooEditable/MooEditable.Charmap.css

+
+.mooeditable-ui-toolbar .charmap-item .button-icon {
+	background: transparent url(Other/character.png) no-repeat center center;
+}

eag-static/css/MooEditable/MooEditable.Extras.css

+.mooeditable-ui-toolbar .justifycenter-item .button-icon,
+.mooeditable-ui-toolbar .justifyright-item .button-icon,
+.mooeditable-ui-toolbar .justifyfull-item .button-icon,
+.mooeditable-ui-toolbar .justifyleft-item .button-icon{
+	background-image: url(images/mooeditable-extras-toolbarbuttons-tango.png);
+}
+
+.mooeditable-ui-toolbar .justifycenter-item .button-icon{ background-position: 0 0; } 
+.mooeditable-ui-toolbar .justifyfull-item .button-icon{ background-position: 0 -16px; } 
+.mooeditable-ui-toolbar .justifyleft-item .button-icon{ background-position: 0 -32px; } 
+.mooeditable-ui-toolbar .justifyright-item .button-icon{ background-position: 0 -48px; } 
+
+.mooeditable-ui-toolbar .removeformat-item .button-icon { background: transparent url(Other/removeformat.png) no-repeat center center; }
+.mooeditable-ui-toolbar .insertHorizontalRule-item .button-icon { background: transparent url(Other/hr.png) no-repeat center center; }

eag-static/css/MooEditable/MooEditable.Flash.css

+
+.mooeditable-ui-toolbar .flash-item .button-icon {
+	background: transparent url(Other/flash.png) no-repeat center center;
+}

eag-static/css/MooEditable/MooEditable.Forecolor.css

+.mooeditable-ui-toolbar .forecolor-item .button-icon{
+	background: transparent url(images/mooeditable-toolbarbuttons-silk.png) no-repeat top left;
+	background-position: 0 -192px;
+}
+
+.forecolor-overlay .overlay-content{
+    padding: 4px 0 0 4px;
+}
+
+.forecolor-overlay .forecolor-colorpicker-color{
+    line-height: 0;
+	overflow: hidden;
+	height: 12px;
+	width: 12px;
+	float: left;
+    margin: 0 4px 4px 0;
+	border: 1px solid #fff;
+	border-radius: 2px;
+	-webkit-border-radius: 2px;
+	-moz-border-radius: 2px;
+}
+
+.forecolor-overlay .forecolor-colorpicker-color:hover {
+	border-color: #000;
+}
+
+.forecolor-overlay .forecolor-colorpicker-br{
+    display: block;
+    clear: left;
+}

eag-static/css/MooEditable/MooEditable.Table.css

+
+.mooeditable-ui-toolbar .tableadd-item .button-icon {
+	background: transparent url(Other/table-add.png) no-repeat center center;
+}
+
+.mooeditable-ui-toolbar .tableedit-item .button-icon {
+	background: transparent url(Other/table-edit.png) no-repeat center center;
+}
+
+.mooeditable-ui-toolbar .tablerowadd-item .button-icon {
+	background: transparent url(Other/table-rowadd.png) no-repeat center center;
+}
+
+.mooeditable-ui-toolbar .tablerowedit-item .button-icon {
+	background: transparent url(Other/table-rowedit.png) no-repeat center center;
+}
+
+.mooeditable-ui-toolbar .tablerowspan-item .button-icon {
+	background: transparent url(Other/table-rowspan.png) no-repeat center center;
+}
+
+.mooeditable-ui-toolbar .tablerowsplit-item .button-icon {
+	background: transparent url(Other/table-rowsplit.png) no-repeat center center;
+}
+
+.mooeditable-ui-toolbar .tablerowspan-item .button-icon {
+	background: transparent url(Other/table-rowspan.png) no-repeat center center;
+}
+
+.mooeditable-ui-toolbar .tablerowdelete-item .button-icon {
+	background: transparent url(Other/table-rowdelete.png) no-repeat center center;
+}
+
+.mooeditable-ui-toolbar .tablecoladd-item .button-icon {
+	background: transparent url(Other/table-coladd.png) no-repeat center center;
+}
+
+.mooeditable-ui-toolbar .tablecoledit-item .button-icon {
+	background: transparent url(Other/table-coledit.png) no-repeat center center;
+}
+
+.mooeditable-ui-toolbar .tablecolspan-item .button-icon {
+	background: transparent url(Other/table-colspan.png) no-repeat center center;
+}
+
+.mooeditable-ui-toolbar .tablecolsplit-item .button-icon {
+	background: transparent url(Other/table-colsplit.png) no-repeat center center;
+}
+
+.mooeditable-ui-toolbar .tablecoldelete-item .button-icon {
+	background: transparent url(Other/table-coldelete.png) no-repeat center center;
+}

eag-static/css/MooEditable/MooEditable.css

+.mooeditable-container{
+	position: relative;
+	border: 2px solid #ddd;
+}
+
+.mooeditable-ui-toolbar{
+	color: inherit;
+	background-color: #eee;
+	padding: 2px;
+}
+
+.mooeditable-ui-toolbar:after{
+	content: ".";
+	display: block;
+	height: 0;
+	clear: both;
+	visibility: hidden;
+}
+
+.mooeditable-ui-toolbar .toolbar-item,
+.mooeditable-ui-toolbar .toolbar-separator{
+	display: -moz-inline-box;
+	display: inline-block;
+	vertical-align: middle;
+}
+
+.mooeditable-ui-toolbar .mooeditable-ui-button{
+	cursor: pointer;
+	border: 0;
+	width: auto;
+	height: auto;
+	margin: 2px;
+	padding: 2px;
+	vertical-align: middle;
+	color: inherit;
+	background-color: transparent;
+}
+* html .mooeditable-ui-toolbar .mooeditable-ui-button{ /* IE6 */
+	width: 24px;
+	overflow: visible;
+	padding: 2px 4px;
+}
+*:first-child+html .mooeditable-ui-toolbar .mooeditable-ui-button{ /* IE7 */
+	min-width: 24px;
+	overflow: visible;
+	padding: 2px 4px;
+}
+
+.mooeditable-ui-toolbar .mooeditable-ui-button.active,
+.mooeditable-ui-toolbar .mooeditable-ui-button.onActive{
+	color: inherit;
+	background-color: #ddd;
+}
+
+.mooeditable-ui-toolbar .mooeditable-ui-button:hover,
+.mooeditable-ui-toolbar .mooeditable-ui-button.hover{
+	color: inherit;
+	background-color: #fff;
+}
+
+.mooeditable-ui-toolbar .mooeditable-ui-button.disabled{
+	cursor: default;
+}
+
+.mooeditable-ui-toolbar .mooeditable-ui-button.disabled:hover{
+	color: inherit;
+	background-color: transparent;
+}
+
+.mooeditable-ui-toolbar .mooeditable-ui-button .button-icon{
+	display: -moz-inline-box;
+	display: inline-block;
+	width: 16px;
+	height: 16px;
+	vertical-align: middle;
+	color: inherit;
+	background: transparent url(images/mooeditable-toolbarbuttons-tango.png) no-repeat 0 -8px;
+}
+
+.mooeditable-ui-toolbar .mooeditable-ui-button .button-text{
+	display: none;
+	font-size: 13px;
+	vertical-align: middle;
+}
+
+.mooeditable-ui-toolbar .mooeditable-ui-button-text .button-icon{
+	display: none;
+}
+.mooeditable-ui-toolbar .mooeditable-ui-button-text .button-text{
+	display: inline;
+}
+
+.mooeditable-ui-toolbar .mooeditable-ui-button-icon-text{
+	width: auto;
+}
+.mooeditable-ui-toolbar .mooeditable-ui-button-icon-text .button-text{
+	display: inline;
+	margin-left: 4px;
+}
+
+.mooeditable-ui-toolbar .toolbar-separator{
+	width: 1px;
+	height: 24px;
+	margin: 2px;
+	text-indent: -999em;
+	color: inherit;
+	background-color: #fafafa;
+}
+
+.mooeditable-ui-toolbar .bold-item .button-icon{ background-position: 0 0; } 
+.mooeditable-ui-toolbar .createlink-item .button-icon{ background-position: 0 -16px; } 
+.mooeditable-ui-toolbar .indent-item .button-icon{ background-position: 0 -32px; } 
+.mooeditable-ui-toolbar .insertorderedlist-item .button-icon{ background-position: 0 -48px; } 
+.mooeditable-ui-toolbar .insertunorderedlist-item .button-icon{ background-position: 0 -64px; } 
+.mooeditable-ui-toolbar .italic-item .button-icon{ background-position: 0 -80px; } 
+.mooeditable-ui-toolbar .outdent-item .button-icon{ background-position: 0 -96px; } 
+.mooeditable-ui-toolbar .redo-item .button-icon{ background-position: 0 -112px; } 
+.mooeditable-ui-toolbar .strikethrough-item .button-icon{ background-position: 0 -128px; } 
+.mooeditable-ui-toolbar .toggleview-item .button-icon{ background-position: 0 -144px; } 
+.mooeditable-ui-toolbar .underline-item .button-icon{ background-position: 0 -160px; } 
+.mooeditable-ui-toolbar .undo-item .button-icon{ background-position: 0 -176px; } 
+.mooeditable-ui-toolbar .unlink-item .button-icon{ background-position: 0 -192px; } 
+.mooeditable-ui-toolbar .urlimage-item .button-icon{ background-position: 0 -208px; } 
+
+.mooeditable-iframe{
+	margin: 0;
+	padding: 0;
+	border: 0;
+	width: 100%;
+	vertical-align: top;
+}
+
+.mooeditable-textarea{
+	margin: 0 !important;
+	padding: 0 !important;
+	border: 0 !important;
+	width: 100% !important;
+	resize: none !important; /* disable resizable textareas in Webkit */
+	outline: 0 !important; /* disable focus ring in Safari */
+}
+
+.mooeditable-ui-dialog{
+	color: inherit;
+	background-color: #ddd;
+	position: absolute;
+	display: block;
+	cursor: default;
+	font-size: 12px;
+	z-index: 100;
+	width: 100%;
+}
+
+.mooeditable-ui-dialog .dialog-content{
+	padding: 4px 10px;
+}
+
+.mooeditable-ui-dialog .dialog-content *{
+	vertical-align: middle;
+}
+
+.mooeditable-ui-dialog input{
+	margin: 0 8px;
+}
+
+.mooeditable-ui-dialog input.text{
+	width: 300px;
+}
+
+.mooeditable-ui-button-overlay{
+	color: inherit;
+	background-color: #ddd;
+	font-size: 12px;
+	z-index: 100;
+	outline: 0;
+	-moz-outline: 0;
+	-webkit-outline: 0;
+}
+
+.mooeditable-ui-button-overlay .overlay-content{
+	padding: 10px;
+}
Add a comment to this file

eag-static/css/MooEditable/Other/character.png

Added
New image
Add a comment to this file

eag-static/css/MooEditable/Other/flash.png

Added
New image
Add a comment to this file

eag-static/css/MooEditable/Other/hr.png

Added
New image
Add a comment to this file

eag-static/css/MooEditable/Other/pagebreak.gif

Added
New image
Add a comment to this file

eag-static/css/MooEditable/Other/pagebreak.png

Added
New image
Add a comment to this file

eag-static/css/MooEditable/Other/removeformat.png

Added
New image
Add a comment to this file

eag-static/css/MooEditable/Other/table-add.png

Added
New image
Add a comment to this file

eag-static/css/MooEditable/Other/table-coladd.png

Added
New image
Add a comment to this file

eag-static/css/MooEditable/Other/table-coldelete.png

Added
New image
Add a comment to this file

eag-static/css/MooEditable/Other/table-coledit.png

Added
New image
Add a comment to this file

eag-static/css/MooEditable/Other/table-colspan.png

Added
New image
Add a comment to this file

eag-static/css/MooEditable/Other/table-colsplit.png

Added
New image
Add a comment to this file

eag-static/css/MooEditable/Other/table-edit.png

Added
New image
Add a comment to this file

eag-static/css/MooEditable/Other/table-rowadd.png

Added
New image
Add a comment to this file

eag-static/css/MooEditable/Other/table-rowdelete.png

Added
New image
Add a comment to this file

eag-static/css/MooEditable/Other/table-rowedit.png

Added
New image
Add a comment to this file

eag-static/css/MooEditable/Other/table-rowspan.png

Added
New image
Add a comment to this file

eag-static/css/MooEditable/Other/table-rowsplit.png

Added
New image
Add a comment to this file

eag-static/css/MooEditable/images/mooeditable-extras-toolbarbuttons-tango.png

Added
New image
Add a comment to this file

eag-static/css/MooEditable/images/mooeditable-toolbarbuttons-silk.png

Added
New image
Add a comment to this file

eag-static/css/MooEditable/images/mooeditable-toolbarbuttons-tango.png

Added
New image

eag-static/css/style.css

+html, body {
+    width: 100%;
+    height: 100%;
+    padding: 0;
+    margin: 0;
+    font-family: sans-serif;
+}
+
+ul, li, form {
+    padding: 0;
+    margin: 0;
+    border: 0;
+}
+
+h1 {
+    font-size: 16pt;
+    font-family: sans-serif;
+    margin-bottom: 4pt;
+}
+
+a {
+    text-decoration: underline;
+}
+
+a:hover {
+    text-decoration: none;
+}
+
+.clear {
+    clear: both;
+}
+
+.left {
+    float: left;
+}
+
+.right {
+    float: right;
+}
+
+body {
+    background-color: #cfcfda;
+}
+
+#Everything {
+    padding: 0 20px;
+}
+
+#Header {
+    padding: 8px 0;
+}
+
+#Header .logout {
+    font-size: 8pt;
+}
+
+#Header .logout a {
+    display: block;
+    background-color: #000;
+    float: right;
+    color: #fff;
+    text-decoration: none;
+    padding: 4px 8px;
+    margin-top: -4px;
+    border-radius: 3pt;
+    -moz-border-radius: 3pt;
+}
+
+#Footer {
+    border-top: 7px solid #000;
+    padding-bottom: 40px;
+}
+
+/* Menu */
+#TopMenu {
+    list-style-type: none;
+}
+
+#TopMenu li {
+    border-top-left-radius: 5pt;
+    border-top-right-radius: 5pt;
+    -moz-border-radius-topleft: 5pt;
+    -moz-border-radius-topright: 5pt;
+    background-color: #000;
+    font-size: 10pt;
+    font-weight: bold;
+    padding: 4pt 9pt 0 9pt;
+    float: left;
+}
+
+#TopMenu li a {
+    color: #cfcfda;
+    text-decoration: none;
+}
+
+#TopMenu li.active {
+    background-color: #fff;
+    border-bottom: 4px solid #fff;
+    margin-bottom: -4px;
+}
+
+#TopMenu li.active a {
+    color: #000;
+}
+
+/* Content */
+#Content {
+    border-top: 4px solid #000;
+    padding: 10px 30px 10px 30px;
+    background-color: #fff;
+}
+
+/* Actions */
+#Actions {
+    height: 16pt;
+    list-style-type: none;
+    border-top: 1px solid #ccc;
+    border-bottom: 1px solid #ccc;
+    background-color: #f5f2ff;
+    margin: 10px 0;
+}
+
+#Actions li {
+    float: left;
+    border-right: 1px solid #ccc;
+    padding: 0 1.5em;
+    height: 16pt;
+    line-height: 16pt;
+    font-size: 8pt;
+    font-weight: bold;
+}
+
+#Actions li.last {
+    border-right: 0px;
+}
+
+#Actions li a {
+    color: #6b6b70;
+}
+
+#Actions li a:hover {
+    color: #000;
+}
+
+/* Tree */
+#Tree {
+    list-style-type: none;
+    margin-bottom: 50px;
+}
+
+#Root,
+#Tree li {
+    border-radius: 5px;
+    -moz-border-radius: 5px;
+    background-color: #f0f0f0;
+    margin: 5px 0;
+    border: 1px solid #ccc;
+    padding: 0 10px;
+    line-height: 22pt;
+    font-size: 14pt;
+}
+
+#Root {
+    margin-top: 30px;
+    margin-bottom: 5px;
+}
+
+#Root .info,
+#Tree .info {
+    float: right;
+    font-size: 10pt;
+}
+
+#Root .info a,
+#Root .info span.delete,
+#Tree .info a {
+    font-weight: bold;
+    margin: 0 0 0 1.5em;
+    color: #000;
+}
+
+#Root .info .delete,
+#Tree .info .delete {
+    color: #b02d0e;
+}
+
+#Root .info span.delete {
+    color: #f0f0f0;
+}
+
+#Tree.ordering {
+}
+
+#Tree.ordering .info a {
+    visibility: hidden;
+}
+
+#Tree.ordering li {
+    background-color: #e2e2ec;
+    background-color: #dadada;
+    border: 1px solid #888;
+    cursor: move;
+}
+
+#OrderButtons {
+    margin-top: -10px;
+    margin-bottom: 30px;
+}
+
+#OrderButtons button {
+    padding: 0.2em 0.5em;
+}
+
+#OrderButtons {
+    margin-left: 3em;
+    padding: 0.3em 0.5em;
+    font-weight: bold;
+    border-top: 1px solid #ccc;
+    border-bottom: 1px solid #ccc;
+    background-color: #f5f2ff;
+}
+
+#SaveOrder {
+    font-weight: bold;
+}
+
+#Messages {
+    list-style-type: none;
+    padding-top: 1em;
+    margin-bottom: -0.5em;
+}
+
+#Messages li.error {
+    border: 1px solid #b40808;
+    padding: 3px;
+    font-size: 10pt;
+    background-color: #ffe9e4;
+    color: #940707;
+    font-weight: bold;
+}
+
+/* Forms */
+form {
+    padding-bottom: 40px;
+}
+
+fieldset {
+    border: 1px solid #ccc;
+    margin: 20px 0;
+    background-color: #f5f2ff;
+    padding: 10px 60px 20px 30px;
+}
+
+legend {
+    font-weight: bold;
+    font-size: 12pt;
+    padding: 0.2em 1em;
+    border: 1px solid #ccc;
+    background-color: #f0f0f0;
+}
+
+fieldset,
+legend {
+    -moz-border-radius: 5px;
+    border-radius: 5px;
+}
+
+label {
+    font-weight: bold;
+    display: block;
+    font-size: 11pt;
+    padding-bottom: 2px;
+}
+
+
+#ContentInfo input[type=text],
+#ContentInfo textarea,
+#PageInfo input[type=text],
+#PageInfo textarea {
+    border: 1px solid #aaa;
+    background-color: #f8f8f8;
+    padding: 3px;
+}
+
+#ContentInfo input[type=text],
+#ContentInfo select,
+#ContentInfo textarea,
+#PageInfo input[type=text],
+#PageInfo select,
+#PageInfo textarea {
+    width: 100%;
+}
+
+#ContentInfo input[type=text]:focus,
+#ContentInfo textarea:focus,
+#PageInfo input[type=text]:focus,
+#PageInfo textarea:focus {
+    background-color: #fff;
+    border: 1px solid #000;
+}
+
+.mooeditable-container select {
+    width: auto!important;
+}
+
+.mooeditable-container input {
+    font-size: small!important;
+    width: auto!important;
+}
+
+.mooeditable-container table {
+    border: 1px solid #000;
+}
+
+#ContentInfo input[type=text],
+#PageInfo input[type=text] {
+}
+
+#PageInfo textarea {
+    height: 8em;
+}
+
+#ContentInfo textarea {
+    height: 25em;
+}
+
+form input[type=submit] {
+    font-size: 16pt;
+}
+
+form p {
+    margin: 1.0em 0;
+}
+
+form ul.errorlist {
+    padding: 0;
+    margin: 0 0 -1.0em 0;
+}
+
+form ul.errorlist li {
+    font-size: 10pt;
+    color: #940707;
+    font-weight: bold;
+}
+
+.to-wysiwyg,
+.picasa-trigger {
+    cursor: pointer;
+    display: block;
+    float: right;
+    font-size: 10pt;
+}
+
+.mooeditable-container iframe {
+    background-color: #fff;
+}
+
+.mooeditable-container .picasa-trigger {
+    float: none;
+    display: inline;
+    font-weight: normal;
+}
+
+.mooeditable-container {
+    border-width: 1px!important;
+}
+
+.picasa-back {
+    width: 100%;
+    height: 100%;
+    position: fixed;
+    top: 0;
+    left: 0;
+    background-color: #000;
+    z-index: 101;
+}
+
+.picasa-wait {
+    width: 100%;
+    height: 100%;
+    background: transparent url('../img/loader.gif') no-repeat center center;
+}
+
+.picasa-window {
+    width: 640px;
+    height: 480px;
+    margin: -240px 0 0 -320px;
+    border: 2px solid #000;
+    left: 50%;
+    top: 50%;
+    background-color: #fff;
+    position: fixed;
+    z-index: 102;
+    overflow: auto;
+}
+
+.picasa-window div {
+    float: left;
+}
+
+.picasa-window h2 {
+}
Add a comment to this file

eag-static/img/loader.gif

Added
New image

eag-static/js/content.js

+window.addEvent('domready', function () {
+    var mooEditableOptions = {
+        'actions': 'bold italic underline strikethrough | '
+            + 'insertunorderedlist insertorderedlist indent outdent | '
+            + 'undo redo | createlink unlink | urlimage | forecolor | '
+            + 'toggleview | formatBlock justifyleft justifyright '
+            + 'justifycenter justifyfull | '
+            + 'tableadd tableedit tablerowadd tablerowedit tablerowspan '
+            + 'tablerowsplit tablerowdelete tablecoladd tablecoledit '
+            + 'tablecolspan tablecolsplit tablecoldelete ',
+        'externalCSS': '/eag-static/css/MooEditable/Editable.css'
+    };
+
+    function newMooWYSIWYG(textarea) {
+        var mooEdit = new MooEditable(textarea, mooEditableOptions);
+        new PicasaChoiceField(mooEdit.dialogs.urlimage.prompt.el.getElement('input'));
+    };
+
+    $('ContentInfo').getElements('textarea.semi-wysiwyg').each(function (textarea) {
+        var button = new Element('a', {'text': 'to wysiwyg', 'class': 'to-wysiwyg'})
+            .inject(textarea, 'after')
+            .addEvent('click', function (e) {
+                e.preventDefault();
+                this.dispose();
+                newMooWYSIWYG(textarea);
+                textarea.focus();
+            });
+    });
+
+    $('ContentInfo').getElements('textarea.wysiwyg').each(function (textarea) {
+        newMooWYSIWYG(textarea);
+    });
+
+    makePicasaChoiceFields('input.picasa');
+});
+

eag-static/js/mooeditable.js

+/*
+---
+
+script: MooEditable.js
+
+description: Class for creating a WYSIWYG editor, for contentEditable-capable browsers.
+
+license: MIT-style license
+
+authors:
+- Lim Chee Aun
+- Radovan Lozej
+- Ryan Mitchell
+- Olivier Refalo
+- T.J. Leahy
+
+requires:
+  core/1.2.4:
+  - Events
+  - Options
+  - Element.Event
+  - Element.Style
+  - Element.Dimensions
+  - Selectors
+
+inspiration:
+- Code inspired by Stefan's work [Safari Supports Content Editing!](http://www.xs4all.nl/~hhijdra/stefan/ContentEditable.html) from [safari gets contentEditable](http://walkah.net/blog/walkah/safari-gets-contenteditable)
+- Main reference from Peter-Paul Koch's [execCommand compatibility](http://www.quirksmode.org/dom/execCommand.html)
+- Some ideas and code inspired by [TinyMCE](http://tinymce.moxiecode.com/)
+- Some functions inspired by Inviz's [Most tiny wysiwyg you ever seen](http://forum.mootools.net/viewtopic.php?id=746), [mooWyg (Most tiny WYSIWYG 2.0)](http://forum.mootools.net/viewtopic.php?id=5740)
+- Some regex from Cameron Adams's [widgEditor](http://widgeditor.googlecode.com/)
+- Some code from Juan M Martinez's [jwysiwyg](http://jwysiwyg.googlecode.com/)
+- Some reference from MoxieForge's [PunyMCE](http://punymce.googlecode.com/)
+- IE support referring Robert Bredlau's [Rich Text Editing](http://www.rbredlau.com/drupal/node/6)
+- Tango icons from the [Tango Desktop Project](http://tango.freedesktop.org/)
+- Additional Tango icons from Jimmacs' [Tango OpenOffice](http://www.gnome-look.org/content/show.php/Tango+OpenOffice?content=54799)
+
+provides: [MooEditable, MooEditable.Selection, MooEditable.UI, MooEditable.Actions]
+
+...
+*/
+
+(function(){
+
+var blockEls = /^(H[1-6]|HR|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD)$/i;
+var urlRegex = /^(https?|ftp|rmtp|mms):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i;
+
+this.MooEditable = new Class({
+
+	Implements: [Events, Options],
+
+	options: {
+		toolbar: true,
+		cleanup: true,
+		paragraphise: true,
+		xhtml : true,
+		semantics : true,
+		actions: 'bold italic underline strikethrough | insertunorderedlist insertorderedlist indent outdent | undo redo | createlink unlink | urlimage | toggleview',
+		handleSubmit: true,
+		handleLabel: true,
+		baseCSS: 'html{ height: 100%; cursor: text; } body{ font-family: sans-serif; }',
+		extraCSS: '',
+		externalCSS: '',
+		html: '<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><style>{BASECSS} {EXTRACSS}</style>{EXTERNALCSS}</head><body>{CONTENT}</body></html>',
+		rootElement: 'p'
+	},
+
+	initialize: function(el, options){
+		this.setOptions(options);
+		this.textarea = document.id(el);
+		this.textarea.store('MooEditable', this);
+		this.actions = this.options.actions.clean().split(' ');
+		this.keys = {};
+		this.dialogs = {};
+		this.actions.each(function(action){
+			var act = MooEditable.Actions[action];
+			if (!act) return;
+			if (act.options){
+				var key = act.options.shortcut;
+				if (key) this.keys[key] = action;
+			}
+			if (act.dialogs){
+				$each(act.dialogs, function(dialog, name){
+					dialog = dialog.attempt(this);
+					dialog.name = action + ':' + name;
+					if ($type(this.dialogs[action]) != 'object') this.dialogs[action] = {};
+					this.dialogs[action][name] = dialog;
+				}, this);
+			}
+			if (act.events){
+				$each(act.events, function(fn, event){
+					this.addEvent(event, fn);
+				}, this);
+			}
+		}.bind(this));
+		this.render();
+	},
+
+	toElement: function(){
+		return this.textarea;
+	},
+
+	render: function(){
+		var self = this;
+
+		// Dimensions
+		var dimensions = this.textarea.getSize();
+
+		// Build the container
+		this.container = new Element('div', {
+			id: (this.textarea.id) ? this.textarea.id + '-mooeditable-container' : null,
+			'class': 'mooeditable-container',
+			styles: {
+				width: dimensions.x
+			}
+		});
+
+		// Override all textarea styles
+		this.textarea.addClass('mooeditable-textarea').setStyle('height', dimensions.y);
+
+		// Build the iframe
+		this.iframe = new IFrame({
+			'class': 'mooeditable-iframe',
+			frameBorder: 0,
+			src: 'javascript:""', // Workaround for HTTPs warning in IE6/7
+			styles: {
+				height: dimensions.y
+			}
+		});
+
+		this.toolbar = new MooEditable.UI.Toolbar({
+			onItemAction: function(){
+				var args = $splat(arguments);
+				var item = args[0];
+				self.action(item.name, args);
+			}
+		});
+		this.attach.delay(1, this);
+
+		// Update the event for textarea's corresponding labels
+		if (this.options.handleLabel && this.textarea.id) $$('label[for="'+this.textarea.id+'"]').addEvent('click', function(e){
+			if (self.mode != 'iframe') return;
+			e.preventDefault();
+			self.focus();
+		});
+
+		// Update & cleanup content before submit
+		if (this.options.handleSubmit){
+			this.form = this.textarea.getParent('form');
+			if (!this.form) return;
+			this.form.addEvent('submit', function(){
+				if (self.mode == 'iframe') self.saveContent();
+			});
+		}
+
+		this.fireEvent('render', this);
+	},
+
+	attach: function(){
+		var self = this;
+
+		// Assign view mode
+		this.mode = 'iframe';
+
+		// Editor iframe state
+		this.editorDisabled = false;
+
+		// Put textarea inside container
+		this.container.wraps(this.textarea);
+
+		this.textarea.setStyle('display', 'none');
+
+		this.iframe.setStyle('display', '').inject(this.textarea, 'before');
+
+		$each(this.dialogs, function(action, name){
+			$each(action, function(dialog){
+				document.id(dialog).inject(self.iframe, 'before');
+				var range;
+				dialog.addEvents({
+					open: function(){
+						range = self.selection.getRange();
+						self.editorDisabled = true;
+						self.toolbar.disable(name);
+						self.fireEvent('dialogOpen', this);
+					},
+					close: function(){
+						self.toolbar.enable();
+						self.editorDisabled = false;
+						self.focus();
+						if (range) self.selection.setRange(range);
+						self.fireEvent('dialogClose', this);
+					}
+				});
+			});
+		});
+
+		// contentWindow and document references
+		this.win = this.iframe.contentWindow;
+		this.doc = this.win.document;
+
+		// Build the content of iframe
+		var docHTML = this.options.html.substitute({
+			BASECSS: this.options.baseCSS,
+			EXTRACSS: this.options.extraCSS,
+			EXTERNALCSS: (this.options.externalCSS) ? '<link rel="stylesheet" href="' + this.options.externalCSS + '">': '',
+			CONTENT: this.cleanup(this.textarea.get('value'))
+		});
+		this.doc.open();
+		this.doc.write(docHTML);
+		this.doc.close();
+
+		// Turn on Design Mode
+		// IE fired load event twice if designMode is set
+		(Browser.Engine.trident) ? this.doc.body.contentEditable = true : this.doc.designMode = 'On';
+
+		// Mootoolize window, document and body
+		if (!this.win.$family) new Window(this.win);
+		if (!this.doc.$family) new Document(this.doc);
+		document.id(this.doc.body);
+
+		// Bind all events
+		this.doc.addEvents({
+			mouseup: this.editorMouseUp.bind(this),
+			mousedown: this.editorMouseDown.bind(this),
+			mouseover: this.editorMouseOver.bind(this),
+			mouseout: this.editorMouseOut.bind(this),
+			mouseenter: this.editorMouseEnter.bind(this),
+			mouseleave: this.editorMouseLeave.bind(this),
+			contextmenu: this.editorContextMenu.bind(this),
+			click: this.editorClick.bind(this),
+			dbllick: this.editorDoubleClick.bind(this),
+			keypress: this.editorKeyPress.bind(this),
+			keyup: this.editorKeyUp.bind(this),
+			keydown: this.editorKeyDown.bind(this),
+			focus: this.editorFocus.bind(this),
+			blur: this.editorBlur.bind(this)
+		});
+		['cut', 'copy', 'paste'].each(function(event){
+			self.doc.body.addListener(event, self['editor' + event.capitalize()].bind(self));
+		});
+		this.textarea.addEvent('keypress', this.textarea.retrieve('mooeditable:textareaKeyListener', this.keyListener.bind(this)));
+
+		// Fix window focus event not firing on Firefox 2
+		if (Browser.Engine.gecko && Browser.Engine.version == 18) this.doc.addEvent('focus', function(){
+			self.win.fireEvent('focus').focus();
+		});
+
+		// styleWithCSS, not supported in IE and Opera
+		if (!(/trident|presto/i).test(Browser.Engine.name)){
+			var styleCSS = function(){
+				self.execute('styleWithCSS', false, false);
+				self.doc.removeEvent('focus', styleCSS);
+			};
+			this.win.addEvent('focus', styleCSS);
+		}
+
+		if (this.options.toolbar){
+			document.id(this.toolbar).inject(this.container, 'top');
+			this.toolbar.render(this.actions);
+		}
+
+		this.selection = new MooEditable.Selection(this.win);
+
+		this.oldContent = this.getContent();
+
+		this.fireEvent('attach', this);
+
+		return this;
+	},
+
+	detach: function(){
+		this.saveContent();
+		this.textarea.setStyle('display', '').removeClass('mooeditable-textarea').inject(this.container, 'before');
+		this.textarea.removeEvent('keypress', this.textarea.retrieve('mooeditable:textareaKeyListener'));
+		this.container.dispose();
+		this.fireEvent('detach', this);
+		return this;
+	},
+
+	editorFocus: function(e){
+		this.oldContent = '';
+		this.fireEvent('editorFocus', [e, this]);
+	},
+
+	editorBlur: function(e){
+		this.oldContent = this.saveContent().getContent();
+		this.fireEvent('editorBlur', [e, this]);
+	},
+
+	editorMouseUp: function(e){
+		if (this.editorDisabled){
+			e.stop();
+			return;
+		}
+
+		if (this.options.toolbar) this.checkStates();
+
+		this.fireEvent('editorMouseUp', [e, this]);
+	},
+
+	editorMouseDown: function(e){
+		if (this.editorDisabled){
+			e.stop();
+			return;
+		}
+
+		this.fireEvent('editorMouseDown', [e, this]);
+	},
+
+	editorMouseOver: function(e){
+		if (this.editorDisabled){
+			e.stop();
+			return;
+		}
+
+		this.fireEvent('editorMouseOver', [e, this]);
+	},
+
+	editorMouseOut: function(e){
+		if (this.editorDisabled){
+			e.stop();
+			return;
+		}
+
+		this.fireEvent('editorMouseOut', [e, this]);
+	},
+
+	editorMouseEnter: function(e){
+		if (this.editorDisabled){
+			e.stop();
+			return;
+		}
+
+		if (this.oldContent && this.getContent() != this.oldContent){
+			this.focus();
+			this.fireEvent('editorPaste', [e, this]);
+		}
+
+		this.fireEvent('editorMouseEnter', [e, this]);
+	},
+
+	editorMouseLeave: function(e){
+		if (this.editorDisabled){
+			e.stop();
+			return;
+		}
+
+		this.fireEvent('editorMouseLeave', [e, this]);
+	},
+
+	editorContextMenu: function(e){
+		if (this.editorDisabled){
+			e.stop();
+			return;
+		}
+
+		this.fireEvent('editorContextMenu', [e, this]);
+	},
+
+	editorClick: function(e){
+		// make images selectable and draggable in Safari
+		if (Browser.Engine.webkit){
+			var el = e.target;
+			if (el.get('tag') == 'img'){
+				this.selection.selectNode(el);
+			}
+		}
+
+		this.fireEvent('editorClick', [e, this]);
+	},
+
+	editorDoubleClick: function(e){
+		this.fireEvent('editorDoubleClick', [e, this]);
+	},
+
+	editorKeyPress: function(e){
+		if (this.editorDisabled){
+			e.stop();
+			return;
+		}
+
+		this.keyListener(e);
+
+		this.fireEvent('editorKeyPress', [e, this]);
+	},
+
+	editorKeyUp: function(e){
+		if (this.editorDisabled){
+			e.stop();
+			return;
+		}
+
+		var c = e.code;
+		// 33-36 = pageup, pagedown, end, home; 45 = insert
+		if (this.options.toolbar && (/^enter|left|up|right|down|delete|backspace$/i.test(e.key) || (c >= 33 && c <= 36) || c == 45 || e.meta || e.control)){
+			if (Browser.Engines.trident4){ // Delay for less cpu usage when you are typing
+				$clear(this.checkStatesDelay);
+				this.checkStatesDelay = this.checkStates.delay(500, this);
+			} else {
+				this.checkStates();
+			}
+		}
+
+		this.fireEvent('editorKeyUp', [e, this]);
+	},
+
+	editorKeyDown: function(e){
+		if (this.editorDisabled){
+			e.stop();
+			return;
+		}
+
+		if (e.key == 'enter'){
+			if (this.options.paragraphise){
+				if (e.shift && Browser.Engine.webkit){
+					var s = this.selection;
+					var r = s.getRange();
+
+					// Insert BR element
+					var br = this.doc.createElement('br');
+					r.insertNode(br);
+
+					// Place caret after BR
+					r.setStartAfter(br);
+					r.setEndAfter(br);
+					s.setRange(r);
+
+					// Could not place caret after BR then insert an nbsp entity and move the caret
+					if (s.getSelection().focusNode == br.previousSibling){
+						var nbsp = this.doc.createTextNode('\u00a0');
+						var p = br.parentNode;
+						var ns = br.nextSibling;
+						(ns) ? p.insertBefore(nbsp, ns) : p.appendChild(nbsp);
+						s.selectNode(nbsp);
+						s.collapse(1);
+					}
+
+					// Scroll to new position, scrollIntoView can't be used due to bug: http://bugs.webkit.org/show_bug.cgi?id=16117
+					this.win.scrollTo(0, Element.getOffsets(s.getRange().startContainer).y);
+
+					e.preventDefault();
+				} else if (Browser.Engine.gecko || Browser.Engine.webkit){
+					var node = this.selection.getNode();
+					var isBlock = node.getParents().include(node).some(function(el){
+						return el.nodeName.test(blockEls);
+					});
+					if (!isBlock) this.execute('insertparagraph');
+				}
+			} else {
+				if (Browser.Engine.trident){
+					var r = this.selection.getRange();
+					var node = this.selection.getNode();
+					if (r && node.get('tag') != 'li'){
+						this.selection.insertContent('<br>');
+						this.selection.collapse(false);
+					}
+					e.preventDefault();
+				}
+			}
+		}
+
+		if (Browser.Engine.presto){
+			var ctrlmeta = e.control || e.meta;
+			if (ctrlmeta && e.key == 'x'){
+				this.fireEvent('editorCut', [e, this]);
+			} else if (ctrlmeta && e.key == 'c'){
+				this.fireEvent('editorCopy', [e, this]);
+			} else if ((ctrlmeta && e.key == 'v') || (e.shift && e.code == 45)){
+				this.fireEvent('editorPaste', [e, this]);
+			}
+		}
+
+		this.fireEvent('editorKeyDown', [e, this]);
+	},
+
+	editorCut: function(e){
+		if (this.editorDisabled){
+			e.stop();
+			return;
+		}
+
+		this.fireEvent('editorCut', [e, this]);
+	},
+
+	editorCopy: function(e){
+		if (this.editorDisabled){
+			e.stop();
+			return;
+		}
+
+		this.fireEvent('editorCopy', [e, this]);
+	},
+
+	editorPaste: function(e){
+		if (this.editorDisabled){
+			e.stop();
+			return;
+		}
+
+		this.fireEvent('editorPaste', [e, this]);
+	},
+
+	keyListener: function(e){
+		var key = (Browser.Platform.mac) ? e.meta : e.control;
+		if (!key || !this.keys[e.key]) return;
+		e.preventDefault();
+		var item = this.toolbar.getItem(this.keys[e.key]);
+		item.action(e);
+	},
+
+	focus: function(){
+		(this.mode == 'iframe' ? this.win : this.textarea).focus();
+		this.fireEvent('focus', this);
+		return this;
+	},
+
+	action: function(command, args){
+		var action = MooEditable.Actions[command];
+		if (action.command && $type(action.command) == 'function'){
+			action.command.run(args, this);
+		} else {
+			this.focus();
+			this.execute(command, false, args);
+			if (this.mode == 'iframe') this.checkStates();
+		}
+	},
+
+	execute: function(command, param1, param2){
+		if (this.busy) return;
+		this.busy = true;
+		this.doc.execCommand(command, param1, param2);
+		this.saveContent();
+		this.busy = false;
+		return false;
+	},
+
+	toggleView: function(){
+		this.fireEvent('beforeToggleView', this);
+		if (this.mode == 'textarea'){
+			this.mode = 'iframe';
+			this.iframe.setStyle('display', '');
+			this.setContent(this.textarea.value);
+			this.textarea.setStyle('display', 'none');
+		} else {
+			this.saveContent();
+			this.mode = 'textarea';
+			this.textarea.setStyle('display', '');
+			this.iframe.setStyle('display', 'none');
+		}
+		this.fireEvent('toggleView', this);
+		this.focus.delay(10, this);
+		return this;
+	},
+
+	getContent: function(){
+		return this.cleanup(this.doc.body.get('html'));
+	},
+
+	setContent: function(newContent){
+		this.doc.body.set('html', this.ensureRootElement(newContent));
+		return this;
+	},
+
+	saveContent: function(){
+		if (this.mode == 'iframe'){
+			this.textarea.set('value', this.ensureRootElement(this.getContent()));
+		}
+		return this;
+	},
+
+	ensureRootElement: function(val){
+		if (this.options.rootElement){
+			var el = new Element('div', {html: val.trim()});
+			var start = -1;
+			var create = false;
+			var html = '';
+			var length = el.childNodes.length;
+			for (i=0; i<length; i++){
+				var childNode = el.childNodes[i];
+				var nodeName = childNode.nodeName;
+				if (!nodeName.test(blockEls) && nodeName !== '#comment'){
+					if (nodeName === '#text'){
+						if (childNode.nodeValue.trim()){
+							if (start < 0) start = i;
+							html += childNode.nodeValue;
+						}
+					} else {
+						if (start < 0) start = i;
+						html += new Element('div').adopt($(childNode).clone()).get('html');
+					}
+				} else {
+					create = true;
+				}
+				if (i == (length-1)) create = true;
+				if (start >= 0 && create){
+					var newel = new Element(this.options.rootElement, {html: html});
+					el.replaceChild(newel, el.childNodes[start]);
+					for (k=start+1; k<i; k++){
+						el.removeChild(el.childNodes[k]);
+						length--;
+						i--;
+						k--;
+					}
+					start = -1;
+					create = false;
+					html = '';
+				}
+			}
+			val = el.get('html').replace(/\n\n/g, '');
+		}
+		return val;
+	},
+
+	checkStates: function(){
+		var element = this.selection.getNode();
+		if (!element) return;
+		if ($type(element) != 'element') return;
+
+		this.actions.each(function(action){
+			var item = this.toolbar.getItem(action);
+			if (!item) return;
+			item.deactivate();
+
+			var states = MooEditable.Actions[action]['states'];
+			if (!states) return;
+
+			// custom checkState
+			if ($type(states) == 'function'){
+				states.attempt([document.id(element), item], this);
+				return;
+			}
+
+			try{
+				if (this.doc.queryCommandState(action)){
+					item.activate();
+					return;
+				}
+			} catch(e){}
+
+			if (states.tags){
+				var el = element;
+				do {
+					var tag = el.tagName.toLowerCase();
+					if (states.tags.contains(tag)){
+						item.activate(tag);
+						break;
+					}
+				}
+				while ((el = Element.getParent(el)) != null);
+			}
+
+			if (states.css){
+				var el = element;
+				do {
+					var found = false;
+					for (var prop in states.css){
+						var css = states.css[prop];
+						if (Element.getStyle(el, prop).contains(css)){
+							item.activate(css);
+							found = true;
+						}
+					}
+					if (found || el.tagName.test(blockEls)) break;
+				}
+				while ((el = Element.getParent(el)) != null);
+			}
+		}.bind(this));
+	},
+
+	cleanup: function(source){
+		if (!this.options.cleanup) return source.trim();
+
+		do {
+			var oSource = source;
+
+			// Webkit cleanup
+			source = source.replace(/<br class\="webkit-block-placeholder">/gi, "<br />");
+			source = source.replace(/<span class="Apple-style-span">(.*)<\/span>/gi, '$1');
+			source = source.replace(/ class="Apple-style-span"/gi, '');
+			source = source.replace(/<span style="">/gi, '');
+
+			// Remove padded paragraphs
+			source = source.replace(/<p>\s*<br ?\/?>\s*<\/p>/gi, '<p>\u00a0</p>');
+			source = source.replace(/<p>(&nbsp;|\s)*<\/p>/gi, '<p>\u00a0</p>');
+			if (!this.options.semantics){
+				source = source.replace(/\s*<br ?\/?>\s*<\/p>/gi, '</p>');
+			}
+
+			// Replace improper BRs (only if XHTML : true)
+			if (this.options.xhtml){
+				source = source.replace(/<br>/gi, "<br />");
+			}
+
+			if (this.options.semantics){
+				//remove divs from <li>
+				if (Browser.Engine.trident){
+					source = source.replace(/<li>\s*<div>(.+?)<\/div><\/li>/g, '<li>$1</li>');
+				}
+				//remove stupid apple divs
+				if (Browser.Engine.webkit){
+					source = source.replace(/^([\w\s]+.*?)<div>/i, '<p>$1</p><div>');
+					source = source.replace(/<div>(.+?)<\/div>/ig, '<p>$1</p>');
+				}
+
+				//<p> tags around a list will get moved to after the list
+				if (['gecko', 'presto', 'webkit'].contains(Browser.Engine.name)){
+					//not working properly in safari?
+					source = source.replace(/<p>[\s\n]*(<(?:ul|ol)>.*?<\/(?:ul|ol)>)(.*?)<\/p>/ig, '$1<p>$2</p>');
+					source = source.replace(/<\/(ol|ul)>\s*(?!<(?:p|ol|ul|img).*?>)((?:<[^>]*>)?\w.*)$/g, '</$1><p>$2</p>');
+				}
+
+				source = source.replace(/<br[^>]*><\/p>/g, '</p>'); // remove <br>'s that end a paragraph here.
+				source = source.replace(/<p>\s*(<img[^>]+>)\s*<\/p>/ig, '$1\n'); // if a <p> only contains <img>, remove the <p> tags
+
+				//format the source
+				source = source.replace(/<p([^>]*)>(.*?)<\/p>(?!\n)/g, '<p$1>$2</p>\n'); // break after paragraphs
+				source = source.replace(/<\/(ul|ol|p)>(?!\n)/g, '</$1>\n'); // break after </p></ol></ul> tags
+				source = source.replace(/><li>/g, '>\n\t<li>'); // break and indent <li>
+				source = source.replace(/([^\n])<\/(ol|ul)>/g, '$1\n</$2>'); //break before </ol></ul> tags
+				source = source.replace(/([^\n])<img/ig, '$1\n<img'); // move images to their own line
+				source = source.replace(/^\s*$/g, ''); // delete empty lines in the source code (not working in opera)
+			}
+
+			// Remove leading and trailing BRs
+			source = source.replace(/<br ?\/?>$/gi, '');
+			source = source.replace(/^<br ?\/?>/gi, '');
+
+			// Remove useless BRs
+			source = source.replace(/><br ?\/?>/gi, '>');
+
+			// Remove BRs right before the end of blocks
+			source = source.replace(/<br ?\/?>\s*<\/(h1|h2|h3|h4|h5|h6|li|p)/gi, '</$1');
+
+			// Semantic conversion
+			source = source.replace(/<span style="font-weight: bold;">(.*)<\/span>/gi, '<strong>$1</strong>');
+			source = source.replace(/<span style="font-style: italic;">(.*)<\/span>/gi, '<em>$1</em>');
+			source = source.replace(/<b\b[^>]*>(.*?)<\/b[^>]*>/gi, '<strong>$1</strong>');
+			source = source.replace(/<i\b[^>]*>(.*?)<\/i[^>]*>/gi, '<em>$1</em>');
+			source = source.replace(/<u\b[^>]*>(.*?)<\/u[^>]*>/gi, '<span style="text-decoration: underline;">$1</span>');
+			source = source.replace(/<strong><span style="font-weight: normal;">(.*)<\/span><\/strong>/gi, '$1');
+			source = source.replace(/<em><span style="font-weight: normal;">(.*)<\/span><\/em>/gi, '$1');
+			source = source.replace(/<span style="text-decoration: underline;"><span style="font-weight: normal;">(.*)<\/span><\/span>/gi, '$1');
+			source = source.replace(/<strong style="font-weight: normal;">(.*)<\/strong>/gi, '$1');
+			source = source.replace(/<em style="font-weight: normal;">(.*)<\/em>/gi, '$1');
+
+			// Replace uppercase element names with lowercase
+			source = source.replace(/<[^> ]*/g, function(match){return match.toLowerCase();});
+
+			// Replace uppercase attribute names with lowercase
+			source = source.replace(/<[^>]*>/g, function(match){
+				   match = match.replace(/ [^=]+=/g, function(match2){return match2.toLowerCase();});
+				   return match;
+			});
+
+			// Put quotes around unquoted attributes
+			source = source.replace(/<[^>]*>/g, function(match){
+				   match = match.replace(/( [^=]+=)([^"][^ >]*)/g, "$1\"$2\"");
+				   return match;
+			});
+
+			//make img tags xhtml compatible <img>,<img></img> -> <img/>
+			if (this.options.xhtml){
+				source = source.replace(/<img([^>]+)(\s*[^\/])>(<\/img>)*/gi, '<img$1$2 />');
+			}
+
+			//remove double <p> tags and empty <p> tags
+			source = source.replace(/<p>(?:\s*)<p>/g, '<p>');
+			source = source.replace(/<\/p>\s*<\/p>/g, '</p>');
+
+			// Replace <br>s inside <pre> automatically added by some browsers
+			source = source.replace(/<pre[^>]*>.*?<\/pre>/gi, function(match){
+				return match.replace(/<br ?\/?>/gi, '\n');
+			});
+
+			// Final trim
+			source = source.trim();
+		}
+		while (source != oSource);
+
+		return source;
+	}
+
+});
+
+MooEditable.Selection = new Class({
+
+	initialize: function(win){
+		this.win = win;
+	},
+
+	getSelection: function(){
+		this.win.focus();
+		return (this.win.getSelection) ? this.win.getSelection() : this.win.document.selection;
+	},
+
+	getRange: function(){
+		var s = this.getSelection();
+
+		if (!s) return null;
+
+		try {
+			return s.rangeCount > 0 ? s.getRangeAt(0) : (s.createRange ? s.createRange() : null);
+		} catch(e) {
+			// IE bug when used in frameset
+			return this.doc.body.createTextRange();
+		}
+	},
+
+	setRange: function(range){
+		if (range.select){
+			$try(function(){
+				range.select();
+			});
+		} else {
+			var s = this.getSelection();
+			if (s.addRange){
+				s.removeAllRanges();
+				s.addRange(range);
+			}
+		}
+	},
+
+	selectNode: function(node, collapse){
+		var r = this.getRange();
+		var s = this.getSelection();
+
+		if (r.moveToElementText){
+			$try(function(){
+				r.moveToElementText(node);
+				r.select();
+			});
+		} else if (s.addRange){
+			collapse ? r.selectNodeContents(node) : r.selectNode(node);
+			s.removeAllRanges();
+			s.addRange(r);
+		} else {
+			s.setBaseAndExtent(node, 0, node, 1);
+		}
+
+		return node;
+	},
+
+	isCollapsed: function(){
+		var r = this.getRange();
+		if (r.item) return false;
+		return r.boundingWidth == 0 || this.getSelection().isCollapsed;
+	},
+
+	collapse: function(toStart){
+		var r = this.getRange();
+		var s = this.getSelection();
+
+		if (r.select){
+			r.collapse(toStart);
+			r.select();
+		} else {
+			toStart ? s.collapseToStart() : s.collapseToEnd();
+		}
+	},
+
+	getContent: function(){
+		var r = this.getRange();
+		var body = new Element('body');
+
+		if (this.isCollapsed()) return '';
+
+		if (r.cloneContents){
+			body.appendChild(r.cloneContents());
+		} else if ($defined(r.item) || $defined(r.htmlText)){
+			body.set('html', r.item ? r.item(0).outerHTML : r.htmlText);
+		} else {
+			body.set('html', r.toString());
+		}
+
+		var content = body.get('html');
+		return content;
+	},
+
+	getText : function(){
+		var r = this.getRange();
+		var s = this.getSelection();
+		return this.isCollapsed() ? '' : r.text || (s.toString ? s.toString() : '');
+	},
+
+	getNode: function(){
+		var r = this.getRange();
+
+		if (!Browser.Engine.trident){
+			var el = null;
+
+			if (r){
+				el = r.commonAncestorContainer;
+
+				// Handle selection a image or other control like element such as anchors
+				if (!r.collapsed)
+					if (r.startContainer == r.endContainer)
+						if (r.startOffset - r.endOffset < 2)
+							if (r.startContainer.hasChildNodes())
+								el = r.startContainer.childNodes[r.startOffset];
+
+				while ($type(el) != 'element') el = el.parentNode;
+			}
+
+			return document.id(el);
+		}
+
+		return document.id(r.item ? r.item(0) : r.parentElement());
+	},
+
+	insertContent: function(content){
+		if (Browser.Engine.trident){
+			var r = this.getRange();
+			r.pasteHTML(content);
+			r.collapse(false);
+			r.select();
+		} else {
+			this.win.document.execCommand('insertHTML', false, content);
+		}
+	}
+
+});
+
+MooEditable.UI = {};
+
+MooEditable.UI.Toolbar= new Class({
+
+	Implements: [Events, Options],
+
+	options: {
+		/*
+		onItemAction: $empty,
+		*/
+		'class': ''
+	},
+
+	initialize: function(options){
+		this.setOptions(options);
+		this.el = new Element('div', {'class': 'mooeditable-ui-toolbar ' + this.options['class']});
+		this.items = {};
+		this.content = null;
+	},
+
+	toElement: function(){
+		return this.el;
+	},
+
+	render: function(actions){
+		if (this.content){
+			this.el.adopt(this.content);
+		} else {
+			this.content = actions.map(function(action){
+				return (action == '|') ? this.addSeparator() : this.addItem(action);
+			}.bind(this));
+		}
+		return this;
+	},
+
+	addItem: function(action){
+		var self = this;
+		var act = MooEditable.Actions[action];
+		if (!act) return;
+		var type = act.type || 'button';
+		var options = act.options || {};
+		var item = new MooEditable.UI[type.camelCase().capitalize()]($extend(options, {
+			name: action,
+			'class': action + '-item toolbar-item',
+			title: act.title,
+			onAction: self.itemAction.bind(self)
+		}));
+		this.items[action] = item;
+		document.id(item).inject(this.el);
+		return item;
+	},
+
+	getItem: function(action){
+		return this.items[action];
+	},
+
+	addSeparator: function(){
+		return new Element('span', {'class': 'toolbar-separator'}).inject(this.el);
+	},
+
+	itemAction: function(){
+		this.fireEvent('itemAction', arguments);
+	},
+
+	disable: function(except){
+		$each(this.items, function(item){
+			(item.name == except) ? item.activate() : item.deactivate().disable();
+		});
+		return this;
+	},
+
+	enable: function(){
+		$each(this.items, function(item){
+			item.enable();
+		});
+		return this;
+	},
+
+	show: function(){
+		this.el.setStyle('display', '');
+		return this;
+	},
+
+	hide: function(){
+		this.el.setStyle('display', 'none');
+		return this;
+	}
+
+});
+
+MooEditable.UI.Button = new Class({
+
+	Implements: [Events, Options],
+
+	options: {
+		/*
+		onAction: $empty,
+		*/
+		title: '',
+		name: '',
+		text: 'Button',
+		'class': '',
+		shortcut: '',
+		mode: 'icon'
+	},
+
+	initialize: function(options){
+		this.setOptions(options);
+		this.name = this.options.name;
+		this.render();
+	},
+
+	toElement: function(){
+		return this.el;
+	},
+
+	render: function(){
+		var self = this;
+		var key = (Browser.Platform.mac) ? 'Cmd' : 'Ctrl';
+		var shortcut = (this.options.shortcut) ? ' ( ' + key + '+' + this.options.shortcut.toUpperCase() + ' )' : '';
+		var text = this.options.title || name;
+		var title = text + shortcut;
+		this.el = new Element('button', {
+			'class': 'mooeditable-ui-button ' + self.options['class'],
+			title: title,
+			html: '<span class="button-icon"></span><span class="button-text">' + text + '</span>',
+			events: {
+				click: self.click.bind(self),
+				mousedown: function(e){ e.preventDefault(); }
+			}
+		});
+		if (this.options.mode != 'icon') this.el.addClass('mooeditable-ui-button-' + this.options.mode);
+
+		this.active = false;
+		this.disabled = false;
+
+		// add hover effect for IE
+		if (Browser.Engine.trident) this.el.addEvents({
+			mouseenter: function(e){ this.addClass('hover'); },
+			mouseleave: function(e){ this.removeClass('hover'); }
+		});
+
+		return this;
+	},
+
+	click: function(e){
+		e.preventDefault();
+		if (this.disabled) return;
+		this.action(e);
+	},
+
+	action: function(){
+		this.fireEvent('action', [this].concat($A(arguments)));
+	},
+
+	enable: function(){
+		if (this.active) this.el.removeClass('onActive');
+		if (!this.disabled) return;
+		this.disabled = false;
+		this.el.removeClass('disabled').set({
+			disabled: false,
+			opacity: 1
+		});
+		return this;
+	},
+
+	disable: function(){
+		if (this.disabled) return;
+		this.disabled = true;
+		this.el.addClass('disabled').set({
+			disabled: true,
+			opacity: 0.4
+		});
+		return this;
+	},
+
+	activate: function(){
+		if (this.disabled) return;
+		this.active = true;
+		this.el.addClass('onActive');
+		return this;
+	},
+
+	deactivate: function(){
+		this.active = false;
+		this.el.removeClass('onActive');
+		return this;
+	}
+
+});
+
+MooEditable.UI.Dialog = new Class({
+
+	Implements: [Events, Options],
+
+	options:{
+		/*
+		onOpen: $empty,
+		onClose: $empty,
+		*/
+		'class': '',
+		contentClass: ''
+	},
+
+	initialize: function(html, options){
+		this.setOptions(options);
+		this.html = html;
+
+		var self = this;
+		this.el = new Element('div', {
+			'class': 'mooeditable-ui-dialog ' + self.options['class'],
+			html: '<div class="dialog-content ' + self.options.contentClass + '">' + html + '</div>',
+			styles: {
+				'display': 'none'
+			},
+			events: {
+				click: self.click.bind(self)
+			}
+		});
+	},
+
+	toElement: function(){
+		return this.el;
+	},
+
+	click: function(){
+		this.fireEvent('click', arguments);
+		return this;
+	},
+
+	open: function(){
+		this.el.setStyle('display', '');
+		this.fireEvent('open', this);
+		return this;
+	},
+
+	close: function(){
+		this.el.setStyle('display', 'none');
+		this.fireEvent('close', this);
+		return this;
+	}
+
+});
+
+MooEditable.UI.AlertDialog = function(alertText){
+	if (!alertText) return;
+	var html = alertText + ' <button class="dialog-ok-button">OK</button>';
+	return new MooEditable.UI.Dialog(html, {
+		'class': 'mooeditable-alert-dialog',
+		onOpen: function(){
+			var button = this.el.getElement('.dialog-ok-button');
+			(function(){
+				button.focus();
+			}).delay(10);
+		},
+		onClick: function(e){
+			e.preventDefault();
+			if (e.target.tagName.toLowerCase() != 'button') return;
+			if (document.id(e.target).hasClass('dialog-ok-button')) this.close();
+		}
+	});
+};
+
+MooEditable.UI.PromptDialog = function(questionText, answerText, fn){