trying to make it work with the precompilation of assets (issue with Aloha and TinyMCE)

This commit is contained in:
did 2012-01-20 14:46:09 +01:00
parent 0f3c672777
commit 7af9ea34a6
1654 changed files with 278 additions and 280088 deletions

View File

@ -12,7 +12,7 @@ gem 'cancan', '~> 1.6.7'
gem 'mongo', '~> 1.5.2'
gem 'bson_ext', '~> 1.5.2'
gem 'mongoid', '~> 2.4.0'
gem 'locomotive_mongoid_acts_as_tree', :git => 'git@github.com:locomotivecms/mongoid_acts_as_tree.git'
gem 'locomotive_mongoid_acts_as_tree', '~> 0.1.5.8'
gem 'custom_fields', :path => '../gems/custom_fields' # DEV
# gem 'custom_fields', :git => 'git://github.com/locomotivecms/custom_fields.git', :branch => 'experimental'
gem 'kaminari'
@ -26,6 +26,7 @@ gem 'jquery-rails', '~> 1.0.16'
gem 'rails-backbone', '0.5.4'
gem 'codemirror-rails'
gem 'tinymce-rails'
gem 'locomotive-aloha-rails', :path => '../gems/aloha-rails'
gem 'flash_cookie_session', '~> 1.1.1'
gem 'locomotive_liquid', '2.2.2', :require => 'liquid'

View File

@ -1,8 +1,8 @@
GIT
remote: git@github.com:locomotivecms/mongoid_acts_as_tree.git
revision: ca494d22c3d7946385aba1153c017d9c30e9f9d3
PATH
remote: ../gems/aloha-rails
specs:
locomotive_mongoid_acts_as_tree (0.1.5.7)
locomotive-aloha-rails (0.20.1)
railties (>= 3.1)
PATH
remote: ../gems/custom_fields
@ -163,6 +163,7 @@ GEM
launchy (2.0.5)
addressable (~> 2.2.6)
locomotive_liquid (2.2.2)
locomotive_mongoid_acts_as_tree (0.1.5.8)
mail (2.3.0)
i18n (>= 0.4.0)
mime-types (~> 1.16)
@ -314,8 +315,9 @@ DEPENDENCIES
jquery-rails (~> 1.0.16)
kaminari
launchy
locomotive-aloha-rails!
locomotive_liquid (= 2.2.2)
locomotive_mongoid_acts_as_tree!
locomotive_mongoid_acts_as_tree (~> 0.1.5.8)
mimetype-fu (~> 0.1.2)
mocha (= 0.9.12)
mongo (~> 1.5.2)

View File

@ -0,0 +1,2 @@
#= require ./utils/aloha_settings
#= require aloha

View File

@ -0,0 +1 @@
#= require jquery

View File

@ -1,10 +1,16 @@
unless window.Aloha?
window.Aloha = {}
# unless window.Aloha?
# window.Aloha = {}
Aloha = window.Aloha ?= {}
Aloha.settings =
window.Aloha.settings =
logLevels: { 'error': true, 'warn': true, 'info': false, 'debug': false }
errorhandling: true
plugins:
format:
config: [ 'b', 'i', 'u','del','sub','sup', 'p', 'title', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'pre', 'removeFormat']
editables:
@ -24,4 +30,6 @@ window.Aloha.settings =
available: ['en', 'fr', 'pt-BR', 'es', 'de', 'no', 'ru', 'nl']
sidebar:
disabled: true
disabled: true

View File

@ -1,58 +0,0 @@
@import "compass/css3";
@import "compass/css3/border-radius";
@import "compass/css3/images";
@import "compass/css3/text-shadow";
@import "locomotive/shared/helpers";
#panel {
.inner {
padding: 5px 20px 20px 20px;
a {
color: #1F82BC;
@include hover-link;
}
p.explanations {
margin-top: 10px;
color: #222;
font-size: 14px;
text-align: justify;
}
p.done {
margin: 20px 0px 15px;
color: #222;
font-size: 14px;
}
fieldset {
ol {
li.question {
label {
display: inline;
font-weight: normal;
}
input[type=checkbox] {
display: inline;
width: auto;
margin-right: 10px;
}
} // li.question
li {
input {
&[type=text] { width: 302px; }
&[type=password] { width: 180px; }
}
} // li
} // ol
} // fieldset
} // inner
} // panel

View File

@ -3,5 +3,5 @@
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
* the top of the compiled file, but it's generally better to create a new file per style scope.
*= require locomotive/blueprint/screen.css
*= require ./simple.css
*= require_tree ./not_logged_in
*/

View File

@ -0,0 +1,60 @@
@import "compass/css3";
@import "compass/css3/border-radius";
@import "compass/css3/images";
@import "compass/css3/text-shadow";
@import "locomotive/shared/helpers";
body.installation {
#panel {
.inner {
padding: 5px 20px 20px 20px;
a {
color: #1F82BC;
@include hover-link;
}
p.explanations {
margin-top: 10px;
color: #222;
font-size: 14px;
text-align: justify;
}
p.done {
margin: 20px 0px 15px;
color: #222;
font-size: 14px;
}
fieldset {
ol {
li.question {
label {
display: inline;
font-weight: normal;
}
input[type=checkbox] {
display: inline;
width: auto;
margin-right: 10px;
}
} // li.question
li {
input {
&[type=text] { width: 302px; }
&[type=password] { width: 180px; }
}
} // li
} // ol
} // fieldset
} // inner
} // panel
}

View File

@ -2,7 +2,7 @@
@import "compass/css3/border-radius";
@import "compass/css3/images";
@import "compass/css3/text-shadow";
@import "buttons";
@import "../backoffice/buttons";
body { background: #000 image-url("locomotive/background/body.png") repeat 0 0; }

View File

@ -1,117 +0,0 @@
@mixin clearfix {
&:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
};
}
/* ___ rounded ___ */
@mixin rounded($side, $radius: 10px, $important: false) {
@if $important == true {
$important: !important; }
@else {
$important: ""; }
border-#{$side}-radius: $radius unquote($important);
-moz-border-radius-#{$side}: $radius unquote($important);
-webkit-border-#{$side}-radius: $radius unquote($important);
}
@mixin border-rounded($vert, $horz, $radius, $important: false) {
@if $important == true {
$important: !important; }
@else {
$important: ""; }
border-#{$vert}-#{$horz}-radius: $radius unquote($important);
-moz-border-radius-#{$vert}#{$horz}: $radius unquote($important);
-webkit-border-#{$vert}-#{$horz}-radius: $radius unquote($important);
}
@mixin full-rounded($radius: 10px) {
border-radius: $radius;
-moz-border-radius: $radius;
-webkit-border-radius: $radius;
}
/* ___ box shadow ___ */
@mixin box-shadow($hoffset, $voffset, $depth, $color) {
box-shadow: $hoffset $voffset $depth $color;
-moz-box-shadow: $hoffset $voffset $depth $color;
-webkit-box-shadow: $hoffset $voffset $depth $color;
}
@mixin box-shadow-with-inset($color_top, $color_bottom: $color_top, $important: false) {
$color_bottom: $color_top !default;
@if $important == true {
$important: " !important"; }
@else {
$important: ""; }
box-shadow: inset 0 1px 0 0 $color_top, 0 1px 0 0 $color_bottom unquote($important);
-moz-box-shadow: inset 0 1px 0 0 $color_top, 0 1px 0 0 $color_bottom unquote($important);
-webkit-box-shadow: inset 0 1px 0 0 $color_top, 0 1px 0 0 $color_bottom unquote($important);
}
@mixin no-box-shadow($important: false) {
@if $important == true {
$important: " !important"; }
@else {
$important: ""; }
box-shadow: none $important;
-moz-box-shadow: none $important;
-webkit-box-shadow: none $important;
}
@mixin popup-box {
@include full-rounded(4px);
box-shadow: inset 0 1px 0 0 rgba(255, 255, 255, 0.17), 3px 3px 5px 0 rgba(0, 0, 0, 0.41);
-moz-box-shadow: inset 0 1px 0 0 rgba(255, 255, 255, 0.17), 3px 3px 5px 0 rgba(0, 0, 0, 0.41);
-webkit-box-shadow: inset 0 1px 0 0 rgba(255, 255, 255, 0.17), 3px 3px 5px 0 rgba(0, 0, 0, 0.41);
}
/* ___ others ___ */
@mixin reset {
padding: 0px;
margin: 0px;
list-style: none;
a {
text-decoration: none;
}
}
@mixin absolute-position($vside, $vvalue, $hside, $hvalue, $display: block) {
display: $display;
position: absolute;
#{$vside}: $vvalue;
#{$hside}: $hvalue;
}
@mixin linear-background-gradient($from, $to) {
background: mix($from, $to);
background: -moz-linear-gradient(0% 100% 90deg, $to, $from);
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from($from), to($to));
}
@mixin icon($where, $width, $height, $enabled: false, $top: 0, $left: 0) {
position: relative;
width: $width;
height: $height;
line-height: $height + 1;
@if $enabled == true {
background-position: -#{$width} $where; }
@else {
background-position: 0 $where; }
top: $top;
left: $left;
}

View File

@ -1,126 +0,0 @@
/* ___ AUTOMATICALLY GENERATED: see admin/button.scss for the source file */
@import "helpers";
.button {
display: inline-block;
background: transparent url(/assets/locomotive//buttons/dark-gray-left.png) no-repeat 0 0;
padding: 0px 0px 0px 2px;
font-size: 0.9em;
color: white;
cursor: pointer;
border: none;
height: 31px;
outline: none;
span {
display: inline-block;
background: transparent url(/assets/locomotive//buttons/dark-gray-right.png) no-repeat right top;
position: relative;
top: -1px;
padding: 3px 9px 9px 4px;
line-height: 21px;
text-shadow: 1px 1px 1px #000;
outline: none;
}
&.light {
background-image: url(/assets/locomotive//buttons/light-gray-left.png);
color: #787a89;
span {
background-image: url(/assets/locomotive//buttons/light-gray-right.png);
text-shadow: 1px 1px 1px #fff;
}
}
&.small {
background: #ebedf4;
outline: none;
-moz-border-radius : 10px;
-webkit-border-radius: 10px;
height: 20px;
font-size: 0.7em;
padding: 0px 12px 0px 12px;
color: #8B8D9A !important;
text-decoration: none;
text-shadow: 1px 1px 1px #fff;
}
&.mini.add {
background: transparent;
height: 20px;
@include linear-background-gradient(#ebedf4, #d7dbe7);
@include full-rounded(4px);
@include box-shadow(1px, 1px, 1px, rgba(0, 0, 0, 0.4));
span {
background: none;
line-height: 10px;
padding: 0px 5px 0 0;
}
}
&.remove {
color: #ff092c !important;
font-size: 1.1em;
&:hover { text-decoration: underline; }
}
}
// .button {
// display: inline-block;
// background: transparent url(/assets/locomotive//buttons/dark-gray-left.png) no-repeat 0 0;
// padding: 0px 0px 0px 2px;
// font-size: 0.9em;
// color: white;
// cursor: pointer;
// border: none;
// height: 31px;
// outline: none;
// }
//
// .button span {
// display: inline-block;
// background: transparent url(/assets/locomotive//buttons/dark-gray-right.png) no-repeat right top;
// position: relative;
// top: -1px;
// padding: 3px 9px 9px 4px;
// line-height: 21px;
// text-shadow: 1px 1px 1px #000;
// outline: none;
// }
//
// .button.light {
// background-image: url(/assets/locomotive//buttons/light-gray-left.png);
// color: #787a89;
// }
//
// .button.light span {
// background-image: url(/assets/locomotive//buttons/light-gray-right.png);
// text-shadow: 1px 1px 1px #fff;
// }
//
// .button.small {
// background: #ebedf4;
// outline: none;
// -moz-border-radius : 10px;
// -webkit-border-radius: 10px;
// height: 20px;
// font-size: 0.7em;
// padding: 0px 12px 0px 12px;
// color: #8B8D9A !important;
// text-decoration: none;
// text-shadow: 1px 1px 1px #fff;
// }
//
// .button.small.add {
// }
//
// .button.remove {
// color: #ff092c !important;
// font-size: 1.1em;
// }
//
// .button.remove:hover { text-decoration: underline; }

View File

@ -1,461 +0,0 @@
/* ___ AUTOMATICALLY GENERATED: see admin/menu.scss for the source file */
@import "helpers";
/* ___ submenu: bg ___*/
#submenu {
clear: both;
position: relative;
top: -1px;
z-index: 998;
height: 60px;
margin: 0px;
padding: 0 8px;
background: transparent image-url("locomotive/menu/shadow.png") repeat-y 0 0;
/* ___ submenu items ___ */
& > ul {
@include reset;
border-top: 1px solid rgba(255, 255, 255, 0.4);
background: transparent image-url("locomotive/menu/submenu/shadow.png") repeat-x 0 0;
@include rounded(top-right, 3px);
height: 60px;
& > li {
margin: 15px 7px 0 8px;
float: left;
&.hoverable > a span {
em {
display: inline-block;
background: transparent image-url("locomotive/menu/icons.png") no-repeat 0 -16px;
width: 12px;
height: 7px;
position: relative;
top: 0px;
left: 6px;
}
}
& > a {
display: inline-block;
@include full-rounded(16px);
@include box-shadow-with-inset(rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.1));
border: 1px solid rgba(0, 0, 0, 0.4);
border-top: 1px solid rgba(0, 0, 0, 0.3);
padding: 0px 16px 0px 16px;
height: 26px;
line-height: 22px;
outline: none;
span {
color: #fff;
font-size: 0.8em;
font-weight: normal;
text-shadow: 1px 1px 1px #000;
}
&:hover {
border: 1px solid rgba(0, 0, 0, 0.9);
border-top: 1px solid rgba(0, 0, 0, 0.8);
}
&.on, &:active {
border: 1px solid rgba(0, 0, 0, 0.2);
border-top: 1px solid rgba(0, 0, 0, 0.4);
border-bottom: 1px solid transparent !important;
@include box-shadow-with-inset(rgba(0, 0, 0, 0), rgba(255, 255, 255, 0.2), true);
}
&.hover {
background: #fff !important;
border-color: transparent !important;
border-color-bottom: #fff;
padding-bottom: 0px;
@include border-rounded(bottom, left, 0px, true);
@include border-rounded(bottom, right, 0px, true);
position: relative;
z-index: 998;
span {
color: #8b8d9a;
text-shadow: none;
@include no-box-shadow(true);
}
span em {
background-position: -12px -16px;
}
& > em {
@include absolute-position(bottom, 0px, right, -11px);
width: 13px;
height: 13px;
background: transparent url(/assets/locomotive//menu/popup/bottom-right-corner.png) no-repeat 0 0;
}
}
}
}
}
/* ___ submenu: actions ___ */
& > .action {
@include absolute-position(top, 0px, right, 22px);
height: 60px;
padding-left: 20px;
z-index: 1;
background: transparent url(/assets/locomotive//menu/submenu/action-border.png) repeat-y left 0;
a {
margin-top: 18px;
display: inline-block;
background: rgba(0, 0, 0, 0.4);
@include full-rounded(16px);
padding: 0px 10px 0 15px;
height: 22px;
line-height: 20px;
text-decoration: none;
border: 1px solid transparent;
outline: none;
em {
display: inline-block;
position: relative;
background: transparent url(/assets/locomotive//menu/icons.png) no-repeat 0 0px;
height: 11px;
width: 11px;
top: 1px;
left: -5px;
}
span {
position: relative;
top: -2px;
color: #fff;
font-size: 0.7em;
text-shadow: 1px 1px 1px #000;
}
&:hover {
border-color: rgba(0, 0, 0, 1);
}
}
}
/* ___ submenu: popup ___ */
.popup {
position: absolute;
top: 42px;
min-width: 250px;
background: #fff;
@include box-shadow(0px, 0px, 10px, rgba(0, 0, 0, 0.5));
@include full-rounded(16px);
@include border-rounded(top, left, 0px);
z-index: 997;
a {
color: #1f82bc;
text-decoration: none;
&:hover { text-decoration: underline; }
}
.header {
border-bottom: 1px dotted #bbbbbd;
padding-bottom: 6px;
margin: 0px 16px;
}
.inner { padding: 8px 16px; }
h2 {
font-size: 0.7em;
font-weight: bold;
color: #1e1f26;
margin-bottom: 0px;
}
p {
margin: 0px;
padding: 10px 0 0 0px;
a {
font-size: 0.8em;
background: transparent url(/assets/locomotive//menu/popup/add.png) no-repeat left 4px;
padding-left: 12px;
}
&.edit {
padding-top: 0px;
a {
background: transparent url(/assets/locomotive//menu/popup/bullet.png) no-repeat left 5px;
}
}
}
ul {
list-style-image: url(/assets/locomotive//menu/popup/bullet.png);
margin: 0px 0px 0 15px;
li {
position: relative;
a { font-size: 0.7em; }
span {
@include absolute-position(top, 6px, right, 15px, inline);
color: #8b8d9a;
font-size: 0.7em;
}
}
&.big-links {
list-style: none;
margin: 0px;
li {
margin: 10px 0;
a {
@include full-rounded(16px);
padding: 3px 10px;
background: #ebedf4;
font-weight: bold;
font-size: 0.8em;
}
}
}
}
.footer {
background: #ebedf4;
padding: 8px 16px;
@include rounded("bottom-left", 16px);
@include rounded("bottom-right", 16px);
a {
color: #8b8d9a;
font-weight: bold;
}
}
}
}
@mixin black-submenu {
& > ul {
background: #23242b url(/assets/locomotive//menu/submenu/black-bg.png) repeat-x 0 0;
border-color: rgba(255, 255, 255, 0.2);
& > li > a {
border: 1px solid rgba(0, 0, 0, 0.2);
border-top: 1px solid rgba(0, 0, 0, 0.1);
border-bottom: 1px solid rgba(0, 0, 0, 0.6);
@include box-shadow-with-inset(rgba(255, 255, 255, 0.1));
@include linear-background-gradient(#303138, #1e1e24);
&.on, &:active {
border: 1px solid rgba(0, 0, 0, 0.4);
border-top: 1px solid rgba(0, 0, 0, 0.6);
@include linear-background-gradient(#1e1e24, #212229);
}
}
}
& > .action {
background-image: url(/assets/locomotive//menu/submenu/black-action-border.png) !important;
}
}
@mixin green-submenu {
& > ul {
background-color: #2e9a7d;
& > li > a {
@include linear-background-gradient(#258c70, #13604b);
&.on, &:active {
@include linear-background-gradient(#195e4b, #166d55);
@include box-shadow-with-inset(rgba(0, 0, 0, 0), rgba(255, 255, 255, 0.2));
}
}
}
}
@mixin blue-submenu {
& > ul {
background-color: #2579ae;
& > li > a {
@include linear-background-gradient(#1f6ea1, #135179);
&.on, &:active {
@include linear-background-gradient(#13496c, #175b88);
}
}
}
}
@mixin orange-submenu {
& > ul {
background-color: #ed8102;
& > li > a {
@include linear-background-gradient(#e07a02, #a25804);
&.on, &:active {
@include linear-background-gradient(#965201, #9d5603);
@include box-shadow-with-inset(rgba(0, 0, 0, 0), rgba(255, 255, 255, 0.2));
}
}
}
}
@mixin red-submenu {
& > ul {
background-color: #d23c45;
& > li > a {
@include linear-background-gradient(#b63e45, #89272d);
&.on, &:active {
@include linear-background-gradient(#7b292e, #972e35);
@include box-shadow-with-inset(rgba(0, 0, 0, 0), rgba(255, 255, 255, 0.2));
}
}
}
}
@mixin submenu-color($color) {
@if $color == black { @include black-submenu; }
@if $color == green { @include green-submenu; }
@if $color == blue { @include blue-submenu; }
@if $color == orange { @include orange-submenu; }
@if $color == red { @include red-submenu; }
}
/* ___ menu ___ */
#menu {
@include reset;
margin: 20px 0 0 0px;
li.item {
float: left;
position: relative;
z-index: 994;
& > span, a {
float: left;
display: block;
}
& > span {
background: transparent url(/assets/locomotive//menu/left.png) no-repeat 0 0;
width: 40px;
height: 39px;
background-position: 0 -39px;
}
&.first > span {
width: 18px;
background-position: 0 0;
}
a {
background: transparent url(/assets/locomotive//menu/right.png) no-repeat right 0px;
padding: 0px 52px 0 2px;
height: 39px;
line-height: 26px;
outline: none;
em, span { display: inline-block; position: relative; }
em {
background: transparent url(/assets/locomotive//menu/icons.png) no-repeat 0px 0px;
}
span {
top: 9px;
left: 6px;
color: #787A89;
text-shadow: #C5CFD1 1px 1px 1px;
font-size: 0.8em;
}
}
@for $i from 2 through 5 {
&.item-#{$i} { left: -35px * ($i - 1); z-index: 993 - $i; }
}
}
}
@mixin menu-color($color) {
$color-index: 1;
@if $color == green { $color-index: 1; }
@if $color == black { $color-index: 2; }
@if $color == blue { $color-index: 3; }
@if $color == orange { $color-index: 4; }
@if $color == red { $color-index: 5; }
z-index: 999;
a {
background-position: right -39px * $color-index;
span {
color: #fff;
text-shadow: none;
}
}
& > span { background-position: -40px * $color-index -39px; }
&.first > span { background-position: -18px * $color-index 0px; }
}
@mixin menu-contents-icon($enabled: false) {
@include icon(-64px, 16px, 12px, $enabled, 10px);
}
@mixin menu-assets-icon($enabled: false) {
@include icon(-48px, 20px, 16px, $enabled, 11px);
}
@mixin menu-settings-icon($enabled: false) {
@include icon(-32px, 14px, 13px, $enabled, 11px);
}
/* ___ section/color/icon associations ___ */
#menu li.contents a em { @include menu-contents-icon; }
body.contents {
$color: black;
#menu li.contents {
@include menu-color($color);
em { @include menu-contents-icon(true); }
}
#submenu { @include submenu-color($color); }
}
#menu li.assets a em { @include menu-assets-icon; }
body.assets {
$color: green;
#menu li.assets {
@include menu-color($color);
em { @include menu-assets-icon(true); }
}
#submenu { @include submenu-color($color); }
}
#menu li.settings a em { @include menu-settings-icon; }
body.settings {
$color: blue;
#menu li.settings {
@include menu-color($color);
em { @include menu-settings-icon(true); }
}
#submenu { @include submenu-color($color); }
}

View File

@ -1,82 +0,0 @@
/* ___ AUTOMATICALLY GENERATED: see admin/sites_picker.scss for the source file */
@import "helpers";
#sites-picker {
position: absolute;
top: 97px;
padding: 0px 0 0 0;
@include popup-box;
border: 1px solid #000;
background: rgba(50, 51, 59, 1);
min-width: 160px;
z-index: 999;
font-size: 12px;
p {
margin-bottom: 0px;
padding: 0 8px;
&, a {
color: #fff;
text-shadow: #000 0px 1px;
}
a {
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
&.action {
margin-top: 0px;
padding: 2px 8px 4px 8px;
text-align: right;
font-size: 11px;
}
}
ul {
@include reset;
margin: 1px 0 0 0;
li {
color: #aaa;
text-shadow: #000 0px 1px;
background: transparent url(/assets/locomotive//plugins/sites_picker_entry_bg.png) repeat-x 0 bottom;
padding: 2px 8px 6px 8px;
cursor: pointer;
a {
text-decoration: none;
color: #aaa;
}
&:hover {
&, a { color: #fff; }
}
}
}
&:before {
content: " ";
display: block;
width: 21px;
height: 13px;
position: absolute;
top: -11px;
right: 20px;
background: transparent url(/assets/locomotive//plugins/sites_picker_top_arrow.png) no-repeat 0 0;
}
}

View File

@ -24,7 +24,7 @@ class Locomotive::GlobalActionsCell < ::Locomotive::MenuCell
end
add :help, :url => '#', :class => 'tutorial', :id => 'help'
add :logout, :url => destroy_locomotive_account_session_url, :confirm => t('locomotive.messages.confirm')
add :logout, :url => destroy_locomotive_account_session_url, :confirm => t('locomotive.messages.confirm'), :method => :delete
end
def localize_label(label, options = {})

View File

@ -1,9 +1,6 @@
- content_for :head_title do
= t('locomotive.installation.common.title')
- content_for :head do
= stylesheet_link_tag 'locomotive/installation', :media => 'screen'
- title t('.title')
- if @step_done.blank?

View File

@ -1,9 +1,6 @@
- content_for :head_title do
= t('locomotive.installation.common.title')
- content_for :head do
= stylesheet_link_tag 'locomotive/installation', :media => 'screen'
- title t('.title')
= semantic_form_for(@site, :url => installation_step_url(2), :html => { :multipart => true }) do |f|

View File

@ -4,14 +4,11 @@
%head
%title= title || escape_once("#{Locomotive.config.name} &mdash; #{current_site.name}")
= javascript_include_tag 'jquery.js'
= javascript_include_tag 'locomotive/not_logged_in'
= stylesheet_link_tag 'locomotive/not_logged_in', :media => 'screen'
= yield :head
/ [if IE]
= stylesheet_link_tag 'locomotive/ie', :media => 'screen'
%body{ :class => controller.controller_name }
#wrapper
#light.container

View File

@ -83,13 +83,19 @@ x edit my site
x remove sidebar
- i18n
- insert image
- deployment
- fix integration problems
- pre-compile assets
- bugs:
x unable to toggle the "required" check_boxes for content types
- unable to sign out
- https://github.com/locomotivecms/engine/pull/281/files
- disallow to click twice on the submit form button (spinner ?)
- message to notify people if their browser is too old
- install a site by default at the first installation (without asking)
- where to put Locomotive::InlineEditorMiddleware ?

View File

@ -18,4 +18,18 @@
collection, selector = Locomotive::ContentType.collection, Locomotive::ContentType.criteria.selector
collection.update selector, { '$rename' => { 'contents_custom_fields' => 'entries_custom_fields' } }
collection.update selector, { '$rename' => { 'contents_custom_fields' => 'entries_custom_fields' } }
Installation:
1/ open Gemfile
gem 'locomotive_cms', :path => '../../Desktop/NoCoffee/LocomotiveCMS/engine/', :require => 'locomotive/engine'
gem 'unicorn'
2/ bundle exec rails g mongoid:config
3/ bundle exec rails g locomotive:install
4/ bundle exec rake assets:precompile

View File

@ -3,15 +3,6 @@ module Locomotive
source_root File.expand_path('../../../../../', __FILE__)
def copy_mongoid_config
copy_file 'config/mongoid.yml', 'config/mongoid.yml'
end
def copy_assets
directory 'public', 'public', :recursive => true
copy_file 'config/assets.yml', 'config/assets.yml'
end
def copy_initializers
@source_paths = nil # reset it for the find_in_source_paths method
@ -24,6 +15,12 @@ module Locomotive
template 'dragonfly.rb', 'config/initializers/dragonfly.rb'
end
def insert_engine_routes
route %(
mount Locomotive::Engine => '/locomotive', :as => 'locomotive' # you can change the value of the path, by default set to "/locomotive"
)
end
def remove_index_html
remove_file 'public/index.html'
end

View File

@ -8,10 +8,12 @@ The Locomotive Engine has been correctly installed in your Rails application.
- config/initializers/carrierwave.rb
- config/initializers/dragonfly.rb
- config/mongoid.yml
- config/devise.yml
- config/routes.rb
2. Launch the server
> unicorn_rails
> bundle exec unicorn_rails
3. Open your browser

View File

@ -1,6 +1,4 @@
require 'locomotive/engine'
require 'locomotive/dependencies'
puts "\t...loading core"
require 'locomotive/version'
require 'locomotive/core_ext'
@ -91,6 +89,8 @@ module Locomotive
self.app_middleware.insert_before Rack::Lock, '::Locomotive::Middlewares::Fonts', :path => %r{^/fonts}
self.app_middleware.use '::Locomotive::Middlewares::SeoTrailingSlash'
self.app_middleware.use '::Locomotive::InlineEditorMiddleware' # TODO
end
def self.configure_multi_sites

View File

@ -1,7 +1,10 @@
require 'devise'
puts "\t...loading dependencies"
require 'mongoid'
require 'mongoid/railtie'
require 'mongoid_acts_as_tree'
require 'devise'
require 'devise/orm/mongoid'
require 'kaminari'
require 'haml'
require 'liquid'
@ -20,3 +23,12 @@ require 'cancan'
require 'RMagick'
require 'cells'
require 'sanitize'
require 'compass'
require 'codemirror/rails'
require 'jquery/rails'
require 'backbone-rails'
require 'tinymce/version'
require 'tinymce/railtie'
require 'aloha/version'
require 'aloha/railtie'

View File

@ -1,5 +1,10 @@
puts "...loading Locomotive engine"
require 'locomotive/dependencies'
require 'locomotive'
$:.unshift File.dirname(__FILE__) # TODO: not sure about that, looks pretty useless
module Locomotive
class Engine < Rails::Engine
@ -7,18 +12,6 @@ module Locomotive
# config.autoload_once_paths += %W( #{config.root}/app/controllers #{config.root}/app/models #{config.root}/app/helpers #{config.root}/app/uploaders)
# initializer 'locomotive.load_controllers_and_models' do |app|
# puts "[locomotive/initializer] locomotive.load_controllers_and_models"
# end
#
# config.before_initialize do |app|
# puts "[locomotive/before_initialize] NOTHING IS INITIALIZED !!!!!"
# end
#
# config.before_configuration do |app|
# puts "[locomotive/before_configuration] NOTHING IS INITIALIZED !!!!!"
# end
initializer 'locomotive.cells' do |app|
Cell::Base.prepend_view_path("#{config.root}/app/cells")
end
@ -27,5 +20,38 @@ module Locomotive
::ActionController::Base.wrap_parameters :format => [:json]
end
initializer "Locomotive precompile hook" do |app|
# app.config.assets.precompile += %w(locomotive.js locomotive.css locomotive/inline_editor.js locomotive/inline_editor.css
# locomotive/not_logged_in.js locomotive/not_logged_in.css
# locomotive/aloha.js)
app.config.assets.precompile += %w(locomotive.js locomotive.css locomotive/inline_editor.js locomotive/inline_editor.css
locomotive/not_logged_in.js locomotive/not_logged_in.css
locomotive/aloha.js)
def compile_asset?(path)
# ignores any filename that begins with '_' (e.g. sass partials)
# all other css/js/sass/image files are processed
if File.basename(path) =~ /^[^_].*\.\w+$/
puts "Compiling: #{path}"
true
else
puts "Ignoring: #{path}"
false
end
end
app.config.assets.precompile = [ method(:compile_asset?).to_proc ]
# app.config.assets.precompile += lambda { |f| puts f.inspect; true }
# locomotive/aloha.js locomotive/aloha.css
# locomotive/aloha/img/*)
# # locomotive/utils/aloha_settings.js
# # locomotive/aloha/*.js
# # locomotive/aloha.css
# # locomotive/aloha/plugins/*.css)
end
end
end

View File

@ -5,17 +5,23 @@ module Liquid
def render(context)
if context.registers[:current_locomotive_account] && context.registers[:inline_editor]
plugins = 'common/format,common/table,common/list,common/link,common/highlighteditables,common/block,common/undo,common/contenthandler,common/paste,common/commands,common/abbr,common/horizontalruler'
%{
<meta content="true" name="inline-editor" />
<link href="/assets/locomotive/aloha/css/aloha.css" media="screen" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="/assets/locomotive/utils/aloha_settings.js"></script>
<script type="text/javascript" src="/assets/locomotive/aloha/lib/aloha.js" data-aloha-plugins="common/format,common/highlighteditables,common/list,common/link,common/undo,common/paste"></script>
#{ActionController::Base.helpers.stylesheet_link_tag 'aloha'}
#{ActionController::Base.helpers.javascript_include_tag 'locomotive/aloha', :'data-aloha-plugins' => plugins}
<script type="text/javascript">
Aloha.ready(function() \{
window.parent.application_view.set_page(#{context.registers[:page].to_presenter.as_json_for_html_view.to_json});
\});
</script>
}
else
''
@ -27,3 +33,17 @@ module Liquid
end
end
end
# = javascript_include_tag 'locomotive/not_logged_in'
# = stylesheet_link_tag 'locomotive/not_logged_in', :media => 'screen'
# <link href="/assets/locomotive/aloha/css/aloha.css" media="screen" rel="stylesheet" type="text/css" />
# <script type="text/javascript" src="/assets/locomotive/utils/aloha_settings.js"></script>
# <script type="text/javascript" src="/assets/locomotive/aloha/lib/aloha.js" data-aloha-plugins="common/format,common/highlighteditables,common/list,common/link,common/undo,common/paste"></script>
#{ActionController::Base.helpers.javascript_include_tag 'locomotive/aloha', :'data-aloha-plugins' => 'common/format,common/highlighteditables,common/list,common/link,common/undo,common/paste'}
# <script type="text/javascript" src="/assets/aloha/lib/aloha.js" data-aloha-plugins="common/format,common/highlighteditables,common/list,common/link,common/undo,common/paste"></script>

View File

@ -1,3 +1,3 @@
module Locomotive #:nodoc
VERSION = "1.0.0.rc1"
VERSION = "2.0.0.rc1"
end

View File

@ -10,59 +10,104 @@ Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.authors = ['Didier Lafforgue']
s.email = ['didier@nocoffee.fr']
s.homepage = 'http://locomotiveapp.org'
s.homepage = 'http://locomotivecms.com'
s.summary = 'A Next Generation Sexy CMS for Rails3'
s.description = 'Locomotive is a next generation CMS system with sexy admin tools, liquid templating, and inline editing powered by mongodb and rails3'
s.description = 'Locomotive is a next generation CMS system with sexy admin tools, liquid templating, and inline editing powered by mongodb and rails 3.1'
s.required_rubygems_version = '>= 1.3.6'
s.rubyforge_project = 'nowarning'
s.add_dependency 'rails', '~> 3.1.3'
s.add_dependency 'warden'
s.add_dependency 'devise', '1.3.4'
s.add_dependency 'devise_bushido_authenticatable', '1.0.0.alpha10'
s.add_dependency 'rails', '~> 3.1.3'
s.add_dependency 'mongo', '~> 1.3.1'
s.add_dependency 'bson', '~> 1.3.1'
s.add_dependency 'bson_ext', '~> 1.3.1'
s.add_dependency 'mongoid', '~> 2.0.2'
s.add_dependency 'devise', '~> 1.5.3'
s.add_dependency 'cancan', '~> 1.6.7'
s.add_dependency 'mongo', '~> 1.5.2'
s.add_dependency 'bson_ext', '~> 1.5.2'
s.add_dependency 'mongoid', '~> 2.4.0'
s.add_dependency 'locomotive_mongoid_acts_as_tree', '0.1.5.8'
s.add_dependency 'custom_fields', '~> 2.0.0.rc1'
s.add_dependency 'locomotive_mongoid_acts_as_tree', '0.1.5.7'
s.add_dependency 'kaminari'
s.add_dependency 'haml', '3.1.2'
s.add_dependency 'sass', '3.1.2'
s.add_dependency 'locomotive_liquid', '2.2.2'
s.add_dependency 'formtastic', '~> 1.2.3'
s.add_dependency 'cells', '~> 3.7.0'
s.add_dependency 'highline'
s.add_dependency 'sanitize'
s.add_dependency 'haml', '~> 3.1.3'
s.add_dependency 'sass-rails', '~> 3.1.4'
s.add_dependency 'coffee-script', '~> 2.2.0'
s.add_dependency 'uglifier', '~> 1.2.2'
s.add_dependency 'compass', '~> 0.12.alpha.4'
s.add_dependency 'jquery-rails', '~> 1.0.16'
s.add_dependency 'rails-backbone', '0.5.4'
s.add_dependency 'codemirror-rails'
s.add_dependency 'tinymce-rails'
s.add_dependency 'locomotive-aloha-rails'
s.add_dependency 'flash_cookie_session', '~> 1.1.1'
s.add_dependency 'json_pure', '1.5.1'
s.add_dependency 'bushido'
s.add_dependency 'heroku', '1.19.1'
s.add_dependency 'locomotive_liquid', '2.2.2'
s.add_dependency 'formtastic', '~> 2.0.2'
s.add_dependency 'responders', '~> 0.6.4'
s.add_dependency 'cells', '~> 3.7.1'
s.add_dependency 'RedCloth', '~> 4.2.8'
s.add_dependency 'sanitize', '~> 2.0.3'
s.add_dependency 'highline', '~> 1.6.2'
s.add_dependency 'rmagick', '2.12.2'
s.add_dependency 'carrierwave', '0.5.6'
s.add_dependency 'dragonfly', '~> 0.9.1'
s.add_dependency 'rack-cache'
s.add_dependency 'custom_fields', '1.0.0.beta.25'
s.add_dependency 'cancan', '~> 1.6.0'
s.add_dependency 'fog', '0.8.2'
s.add_dependency 'mimetype-fu'
s.add_dependency 'actionmailer-with-request'
s.add_dependency 'httparty', '0.7.8'
s.add_dependency 'RedCloth', '4.2.9'
s.add_dependency 'delayed_job_mongoid', '1.0.8'
s.add_dependency 'rmagick', '2.12.2'
s.add_dependency 'carrierwave-mongoid', '~> 0.1.3'
s.add_dependency 'fog', '~> 1.0.0'
s.add_dependency 'dragonfly', '~> 0.9.8'
s.add_dependency 'rack-cache', '~> 1.1'
s.add_dependency 'mimetype-fu', '~> 0.1.2'
s.add_dependency 'rubyzip'
s.add_dependency 'locomotive_jammit-s3'
s.add_dependency 'actionmailer-with-request', '~> 0.3.0'
s.add_dependency 'httparty', '~> 0.8.1'
s.add_dependency 'delayed_job_mongoid', '~> 1.0.8'
# s.add_dependency 'SystemTimer', :platforms => :ruby_18
# s.add_dependency 'rails', '~> 3.1.3'
# # s.add_dependency 'warden'
# s.add_dependency 'devise', '~> 1.5.3'
#
# s.add_dependency 'mongo', '~> 1.5.2'
# s.add_dependency 'bson_ext', '~> 1.5.2'
# s.add_dependency 'mongoid', '~> 2.4.0'
#
# s.add_dependency 'locomotive_mongoid_acts_as_tree', '0.1.5.7'
# s.add_dependency 'kaminari'
#
# s.add_dependency 'sass', '3.1.2'
# s.add_dependency 'locomotive_liquid', '2.2.2'
# s.add_dependency 'formtastic', '~> 1.2.3'
# s.add_dependency 'cells', '~> 3.7.0'
# s.add_dependency 'highline'
# s.add_dependency 'sanitize'
#
# s.add_dependency 'json_pure', '1.5.1'
# s.add_dependency 'bushido'
# s.add_dependency 'heroku', '1.19.1'
#
# s.add_dependency 'rmagick', '2.12.2'
# s.add_dependency 'carrierwave', '0.5.6'
# s.add_dependency 'dragonfly', '~> 0.9.1'
# s.add_dependency 'rack-cache'
#
# s.add_dependency 'custom_fields', '2.0.0.rc1'
# s.add_dependency 'cancan', '~> 1.6.0'
# s.add_dependency 'fog', '0.8.2'
# s.add_dependency 'mimetype-fu'
# s.add_dependency 'actionmailer-with-request'
# s.add_dependency 'httparty', '0.7.8'
# s.add_dependency 'RedCloth', '4.2.9'
# s.add_dependency 'delayed_job_mongoid', '1.0.8'
# s.add_dependency 'rubyzip'
# s.add_dependency 'locomotive_jammit-s3'
s.files = Dir[ 'Gemfile',
'{app}/**/*',
'{config}/**/*',
'{lib}/**/*',
'{public}/stylesheets/admin/**/*', '{public}/javascripts/admin/**/*', '{public}/images/admin/**/*',
'{public}/**/*',
'{vendor}/**/*']
s.require_path = 'lib'

View File

@ -1,209 +0,0 @@
var InlineEditorToolbar = {
element: null, // reference to the toolbar element
form: null, // reference to the form used to post changes
editingMode: false, // true means that Aloha should be enabled
drawerButton: null,
locale: 'en', // default locale
initialize: function() {
this.editingMode = window.location.href.match(/\/edit$/) != null;
this.locale = $('meta[name=locale]').attr('content');
this._buildHTML();
this.element = $('#page-toolbar');
this.form = this.element.find('form');
this.drawerButton = this.element.find('.drawer a');
this._bindEvents();
if ($.cookie('ie_toolbar_off') == '1') this.hide(0, false);
},
toggle: function(animate) {
var duration = (typeof animate == 'undefined') || animate == true ? 300 : 0;
if (this.drawerButton.hasClass('off')) this.show(duration); else this.hide(duration);
},
show: function(duration, withCookie) {
var self = this;
this.element.animate({ 'right': 0 }, duration, function() {
self.drawerButton.removeClass('off');
if ((typeof withCookie == 'undefined') || withCookie == true)
$.cookie('ie_toolbar_off', '0');
});
},
hide: function(duration, withCookie) {
var self = this;
var max = this.element.width() - 17;
this.element.animate({ 'right': -max }, duration, function() {
self.drawerButton.addClass('off');
if ((typeof withCookie == 'undefined') || withCookie == true)
$.cookie('ie_toolbar_off', '1');
});
},
updateForm: function(jEvent, aEvent) {
InlineEditorToolbar.element.find('li.save, li.cancel, li.sep:eq(1)').show();
var content = aEvent.editable.getContents().replace(/^\s*/, "").replace(/\s*$/, "");
var editableObj = $(aEvent.editable.obj[0]);
var dataId = editableObj.attr('data-element-id');
var idInput = InlineEditorToolbar.form.find('#editable-id');
var contentInput = InlineEditorToolbar.form.find('#editable-content');
idInput.attr('name', 'page[editable_elements_attributes][0][id]').val(dataId);
contentInput.attr('name', 'page[editable_elements_attributes][0][content]').val(content);
InlineEditorToolbar.show(true, false);
},
displaySpinner: function() {
this.element.find('li.save, li.cancel, li.sep:eq(1)').hide();
this.element.find('.spinner').show();
},
resetForm: function() {
this.form.find('input.auto').each(function() {
$(this).attr('name', $(this).attr('name').replace('content', '_index'));
$(this).val('');
});
this.element.find('li.save, li.cancel, li.sep:eq(1), li.spinner').hide();
},
/* ___ internal methods ___ */
_buildHTML: function() {
var csrf_token = $('meta[name=csrf-token]').attr('content'),
csrf_param = $('meta[name=csrf-param]').attr('content');
var labels = this._translations[this.locale];
var showPageUrl = $('meta[name=page-url]').attr('content');
var editPageUrl = $('meta[name=edit-page-url]').attr('content');
var nbElements = parseInt($('meta[name=page-elements-count]').attr('content'));
var formContentHTML = "<input type='hidden' name='_method' value='put' />\
<input class='auto' id='editable-id' type='hidden' name='_id' value='' />\
<input class='auto' id='editable-content' type='hidden' name='_content' value='' />";
if (csrf_param != null && csrf_token != null) {
formContentHTML += '<input name="' + csrf_param + '" value="' + csrf_token + '" type="hidden" />';
}
$('body').prepend("<div id='page-toolbar'>\
<ul>\
<li class='drawer'><a href='#'><span>&nbsp;</span></a></li>\
<li class='link home'><a href='" + editPageUrl + "'><span>" + labels['home'] + "</span></a></li>\
<li class='sep'><span>&nbsp;</span></li>\
<li class='link edit' style='" + (this.editingMode ? 'display: none' : '') + "'><a href='#'><span>" + labels['edit'] + "</span></a></li>\
<li class='link save' style='display: none'><a href='#'><span>" + labels['save'] + "</span></a></li>\
<li class='link cancel' style='display: none'><a href='#'><span>" + labels['cancel'] + "</span></a></li>\
<li class='link spinner' style='display: none'><a href='#'><span><img src='/images/admin/form/spinner.gif' /><em>" + labels['saving'] + "</em></span></a></li>\
<li class='sep' style='display: none'><span>&nbsp;</span></li>\
<li class='link back' style='" + (this.editingMode ? '' : 'display: none') + "'><a href='#'><span>" + labels['back'] + "</span></a></li>\
</ul>\
<form action='" + showPageUrl + "' accept-charset='UTF-8' method='post'>\
" + formContentHTML + "\
</form>\
</div>");
},
_bindEvents: function() {
var self = this;
this.form.live('submit', function (e) { $(this).callRemote(); e.stopPropagation(); e.preventDefault();
}).bind('ajax:complete', function() { self.resetForm();
}).bind('ajax:loading', function() { self.displaySpinner();
}).bind('ajax:failure', function() { self.resetForm();
});
this.element.find('ul li a').click(function(e) {
var classArray = $(this).parent().attr('class').split(' ');
switch(classArray[1] || classArray[0]) {
case 'home':
window.location.href = $(this).attr('href'); break;
case 'edit': // passing in editing mode
var url = window.location.href.replace(/\/$/, '/index').replace('#', '');
window.location.href = url + '/edit'; break;
case 'save': // saving changes
self.form.submit(); break;
case 'cancel': // reload the page
window.location.href = window.location.href; break;
case 'back': // back to the non edition mode
var url = window.location.href.replace(/\/edit$/, '');
window.location.href = url; break;
case 'drawer': // expand / shrink toolbar
self.toggle(); break;
}
e.preventDefault(); e.stopPropagation();
});
},
_translations: {
'en': {
'home': 'admin',
'edit': 'edit',
'save': 'save',
'cancel': 'cancel',
'back': 'edition done',
'saving': 'saving'
},
'de': {
'home': 'admin',
'edit': 'bearbeiten',
'save': 'speichern',
'cancel': 'schließen',
'back': 'bearbeiten abschließen',
'saving': 'am Speichern'
},
'fr': {
'home': 'admin',
'edit': 'editer',
'save': 'sauver',
'cancel': 'annuler',
'back': 'fin mode edition',
'saving': 'sauvegarde en cours'
},
'pt-BR': {
'home': 'admin',
'edit': 'editar',
'save': 'salvar',
'cancel': 'cancelar',
'back': 'terminar edição',
'saving': 'salvando'
},
'it': {
'home': 'admin',
'edit': 'modifica',
'save': 'salva',
'cancel': 'annulla',
'back': 'fine modifica',
'saving': 'sto salvando'
},
'ru': {
'home': 'панель управления',
'edit': 'редактирование',
'save': 'сохранение',
'cancel': 'отмена',
'back': 'закончить редактирование',
'saving': 'сохранение'
}
}
};

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
tinyMCE.addI18n('ru.advhr_dlg',{size:"\u0412\u044b\u0441\u043e\u0442\u0430",noshade:"\u0411\u0435\u0437 \u0442\u0435\u043d\u0438",width:"\u0428\u0438\u0440\u0438\u043d\u0430",normal:"\u041e\u0431\u044b\u0447\u043d\u0430\u044f",widthunits:"\u0415\u0434\u0438\u043d\u0438\u0446\u044b \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u044f"});

View File

@ -1 +0,0 @@
tinyMCE.addI18n('ru.advimage_dlg',{"image_list":"\u0421\u043f\u0438\u0441\u043e\u043a \u043a\u0430\u0440\u0442\u0438\u043d\u043e\u043a","align_right":"\u041f\u043e \u043f\u0440\u0430\u0432\u043e\u043c\u0443 \u043a\u0440\u0430\u044e","align_left":"\u041f\u043e \u043b\u0435\u0432\u043e\u043c\u0443 \u043a\u0440\u0430\u044e","align_textbottom":"\u041f\u043e \u043d\u0438\u0436\u043d\u0435\u043c\u0443 \u043a\u0440\u0430\u044e \u0442\u0435\u043a\u0441\u0442\u0430","align_texttop":"\u041f\u043e \u0432\u0435\u0440\u0445\u043d\u0435\u043c\u0443 \u043a\u0440\u0430\u044e \u0442\u0435\u043a\u0441\u0442\u0430","align_bottom":"\u041f\u043e \u043d\u0438\u0436\u043d\u0435\u043c\u0443 \u043a\u0440\u0430\u044e","align_middle":"\u041f\u043e \u0446\u0435\u043d\u0442\u0440\u0443","align_top":"\u041f\u043e \u0432\u0435\u0440\u0445\u043d\u0435\u043c\u0443 \u043a\u0440\u0430\u044e","align_baseline":"\u041f\u043e \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u043b\u0438\u043d\u0438\u0438",align:"\u0412\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435",hspace:"\u0413\u043e\u0440\u0438\u0437. \u043e\u0442\u0441\u0442\u0443\u043f",vspace:"\u0412\u0435\u0440\u0442. \u043e\u0442\u0441\u0442\u0443\u043f",dimensions:"\u0420\u0430\u0437\u043c\u0435\u0440",border:"\u0413\u0440\u0430\u043d\u0438\u0446\u0430",list:"\u0421\u043f\u0438\u0441\u043e\u043a",alt:"\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435",src:"\u0410\u0434\u0440\u0435\u0441","dialog_title":"\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f","missing_alt":"\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u0431\u0435\u0437 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f? \u0411\u0435\u0437 \u044d\u0442\u043e\u0433\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c.","example_img":"\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f",misc:"\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b",mouseout:"\u0412 \u043f\u043e\u043a\u043e\u0435",mouseover:"\u041f\u0440\u0438 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0438\u0438","alt_image":"\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435","swap_image":"\u0414\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435",map:"\u041a\u0430\u0440\u0442\u0430 \u0441\u0441\u044b\u043b\u043e\u043a",id:"\u0418\u043c\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430",rtl:"\u0421\u043f\u0440\u0430\u0432\u0430 \u043d\u0430\u043b\u0435\u0432\u043e",ltr:"\u0421\u043b\u0435\u0432\u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u043e",classes:"\u041a\u043b\u0430\u0441\u0441\u044b",style:"\u0421\u0442\u0438\u043b\u044c","long_desc":"\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043f\u043e\u043b\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435",langcode:"\u041a\u043e\u0434 \u044f\u0437\u044b\u043a\u0430",langdir:"\u041d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0430","constrain_proportions":"\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u043f\u043e\u0440\u0446\u0438\u0438",preview:"\u041f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440",title:"\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a",general:"\u041e\u0431\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b","tab_advanced":"\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e","tab_appearance":"\u041f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435","tab_general":"\u041e\u0431\u0449\u0435\u0435",width:"\u0428\u0438\u0440\u0438\u043d\u0430",height:"\u0412\u044b\u0441\u043e\u0442\u0430"});

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
tinyMCE.addI18n('ru.emotions_dlg',{cry:"\u041f\u043b\u0430\u0447\u0443",cool:"\u041a\u0440\u0443\u0442\u043e\u0439",desc:"\u0421\u043c\u0430\u0439\u043b\u044b",title:"\u0412\u044b\u0431\u043e\u0440 \u0441\u043c\u0430\u0439\u043b\u0430",yell:"\u041a\u0440\u0438\u0447\u0443",wink:"\u041f\u043e\u0434\u043c\u0438\u0433\u0438\u0432\u0430\u044e",undecided:"\u0412 \u043d\u0435\u0440\u0435\u0448\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438","tongue_out":"\u0414\u0440\u0430\u0437\u043d\u044e\u0441\u044c",surprised:"\u0423\u0434\u0438\u0432\u043b\u044f\u044e\u0441\u044c",smile:"\u0423\u043b\u044b\u0431\u0430\u044e\u0441\u044c",sealed:"\u041d\u0435\u043c \u043a\u0430\u043a \u0440\u044b\u0431\u0430","money_mouth":"\u0414\u0435\u043d\u044c\u0433\u0438",laughing:"\u0421\u043c\u0435\u044e\u0441\u044c",kiss:"\u041f\u043e\u0446\u0435\u043b\u0443\u0439",innocent:"\u0410\u043d\u0433\u0435\u043b",frown:"\u0425\u043c\u0443\u0440\u044e\u0441\u044c","foot_in_mouth":"\u0412 \u0440\u043e\u0442 \u043c\u043d\u0435 \u043d\u043e\u0433\u0438",embarassed:"\u041a\u0440\u0430\u0441\u043d\u0435\u044e",usage:"\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043a\u043b\u0430\u0432\u0438\u0448\u0438 \"\u0412\u043b\u0435\u0432\u043e\" \u0438 \"\u0412\u043f\u0440\u0430\u0432\u043e\" \u0434\u043b\u044f \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438."});

File diff suppressed because one or more lines are too long

View File

@ -1,9 +0,0 @@
tinyMCE.addI18n('ru.locomedia_dlg',{
dialog_title: 'Вставить изображение', // Insert media
upload: 'Загрузить изображение', // Upload media
loading: 'Идет загрузка...', // Loading...
uploading: 'Идет загрузка...', // Uploading...
destroying: 'Идет удаление...', // Destroying...
confirm: 'Вы уверены?', // Are you sure ?
no_items: 'Список изображений пуск.' // There are no media for now.
});

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
tinyMCE.addI18n('ru.paste_dlg',{"word_title":"\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 CTRL+V \u0434\u043b\u044f \u0432\u0441\u0442\u0430\u0432\u043a\u0438 \u0442\u0435\u043a\u0441\u0442\u0430 \u0432 \u043e\u043a\u043d\u043e.","text_linebreaks":"\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u044b \u0441\u0442\u0440\u043e\u043a","text_title":"\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 CTRL+V \u0434\u043b\u044f \u0432\u0441\u0442\u0430\u0432\u043a\u0438 \u0442\u0435\u043a\u0441\u0442\u0430 \u0432 \u043e\u043a\u043d\u043e."});

View File

@ -1 +0,0 @@
tinyMCE.addI18n('ru.searchreplace_dlg',{findwhat:"\u041f\u043e\u0438\u0441\u043a",replacewith:"\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u043d\u0430",direction:"\u041d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435",up:"\u0412\u0432\u0435\u0440\u0445 ",down:"\u0412\u043d\u0438\u0437",mcase:"\u0423\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0440\u0435\u0433\u0438\u0441\u0442\u0440",findnext:"\u041d\u0430\u0439\u0442\u0438 \u0434\u0430\u043b\u0435\u0435",allreplaced:"\u0412\u0441\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0431\u044b\u043b\u0438 \u0437\u0430\u043c\u0435\u043d\u0435\u043d\u044b.","searchnext_desc":"\u041d\u0430\u0439\u0442\u0438 \u0435\u0449\u0435",notfound:"\u041f\u043e\u0438\u0441\u043a \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d. \u0421\u043e\u043e\u0442\u0432\u0435\u0441\u0442\u0432\u0438\u0439 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e.","search_title":"\u041f\u043e\u0438\u0441\u043a","replace_title":"\u041f\u043e\u0438\u0441\u043a \u0438 \u0437\u0430\u043c\u0435\u043d\u0430",replaceall:"\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0432\u0441\u0435",replace:"\u0417\u0430\u043c\u0435\u043d\u0430"});

View File

@ -1 +0,0 @@
tinyMCE.addI18n('ru.style_dlg',{"text_lineheight":"\u0412\u044b\u0441\u043e\u0442\u0430 \u0441\u0442\u0440\u043e\u043a\u0438","text_variant":"\u0412\u0430\u0440\u0438\u0430\u043d\u0442","text_style":"\u0421\u0442\u0438\u043b\u044c","text_weight":"\u0422\u043e\u043b\u0449\u0438\u043d\u0430","text_size":"\u0420\u0430\u0437\u043c\u0435\u0440","text_font":"\u0428\u0440\u0438\u0444\u0442","text_props":"\u0422\u0435\u043a\u0441\u0442","positioning_tab":"\u041f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435","list_tab":"\u0421\u043f\u0438\u0441\u043e\u043a","border_tab":"\u0413\u0440\u0430\u043d\u0438\u0446\u0430","box_tab":"\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440","block_tab":"\u0411\u043b\u043e\u043a","background_tab":"\u0424\u043e\u043d","text_tab":"\u0422\u0435\u043a\u0441\u0442",apply:"\u041f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c",title:"\u0420\u0435\u0434\u0430\u043a\u0442\u043e\u0440 CSS \u0441\u0442\u0438\u043b\u044f",clip:"\u041e\u0442\u0441\u0435\u0447\u0435\u043d\u0438\u0435",placement:"\u0420\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u0435",overflow:"\u041f\u0435\u0440\u0435\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435",zindex:"Z-\u0438\u043d\u0434\u0435\u043a\u0441",visibility:"\u0412\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u044c","positioning_type":"\u0422\u0438\u043f",position:"\u041f\u043e\u0437\u0438\u0446\u0438\u044f","bullet_image":"\u041c\u0430\u0440\u043a\u0435\u0440","list_type":"\u0422\u0438\u043f",color:"\u0426\u0432\u0435\u0442",height:"\u0412\u044b\u0441\u043e\u0442\u0430",width:"\u0428\u0438\u0440\u0438\u043d\u0430",style:"\u0421\u0442\u0438\u043b\u044c",margin:"\u041e\u0442\u0441\u0442\u0443\u043f",left:"\u0421\u043b\u0435\u0432\u0430",bottom:"\u0421\u043d\u0438\u0437\u0443",right:"\u0421\u043f\u0440\u0430\u0432\u0430",top:"\u0412\u0432\u0435\u0440\u0445",same:"\u041e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e \u0434\u043b\u044f \u0432\u0441\u0435\u0445",padding:"\u041f\u043e\u043b\u044f","box_clear":"\u042f\u0432\u043d\u044b\u0439","box_float":"\u041f\u043b\u0430\u0432\u0430\u044e\u0449\u0438\u0439","box_height":"\u0412\u044b\u0441\u043e\u0442\u0430","box_width":"\u0428\u0438\u0440\u0438\u043d\u0430","block_display":"\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435","block_whitespace":"\u041f\u0440\u043e\u0431\u0435\u043b","block_text_indent":"\u041e\u0442\u0441\u0442\u0443\u043f \u0442\u0435\u043a\u0441\u0442\u0430","block_text_align":"\u0412\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0430","block_vertical_alignment":"\u0412\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435","block_letterspacing":"\u041e\u0442\u0441\u0442\u0443\u043f\u044b \u043c\u0435\u0436\u0434\u0443 \u0431\u0443\u043a\u0432\u0430\u043c\u0438","block_wordspacing":"\u041e\u0442\u0441\u0442\u0443\u043f\u044b \u043c\u0435\u0436\u0434\u0443 \u0441\u043b\u043e\u0432\u0430\u043c\u0438","background_vpos":"\u0412\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u044f","background_hpos":"\u0413\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u044f","background_attachment":"\u041f\u0440\u0438\u0432\u044f\u0437\u043a\u0430","background_repeat":"\u041f\u043e\u0432\u0442\u043e\u0440","background_image":"\u0424\u043e\u043d\u043e\u0432\u043e\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435","background_color":"\u0426\u0432\u0435\u0442 \u0444\u043e\u043d\u0430","text_none":"\u0411\u0435\u0437 \u0432\u0441\u0435\u0433\u043e","text_blink":"\u041c\u0435\u0440\u0446\u0430\u044e\u0449\u0438\u0439","text_case":"\u0420\u0435\u0433\u0438\u0441\u0442\u0440","text_striketrough":"\u0417\u0430\u0447\u0435\u0440\u043a\u043d\u0443\u0442\u044b\u0439","text_underline":"\u041f\u043e\u0434\u0447\u0435\u0440\u043a\u043d\u0443\u0442\u044b\u0439","text_overline":"\u0421 \u0432\u0435\u0440\u0445\u043d\u0435\u0439 \u0447\u0435\u0440\u0442\u043e\u0439","text_decoration":"\u041e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u0435","text_color":"\u0426\u0432\u0435\u0442",text:"\u0422\u0435\u043a\u0441\u0442",background:"\u0424\u043e\u043d",block:"\u0411\u043b\u043e\u043a",box:"\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440",border:"\u0413\u0440\u0430\u043d\u0438\u0446\u0430",list:"\u0421\u043f\u0438\u0441\u043e\u043a"});

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
tinyMCE.addI18n('ru.template_dlg',{title:"\u0428\u0430\u0431\u043b\u043e\u043d\u044b",label:"\u0428\u0430\u0431\u043b\u043e\u043d","desc_label":"\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435",desc:"\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d",select:"\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0448\u0430\u0431\u043b\u043e\u043d",preview:"\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440",warning:"\u0412\u043d\u0438\u043c\u0430\u043d\u0438\u0435: \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u043f\u043e\u0442\u0435\u0440\u044f\u043c \u0434\u0430\u043d\u043d\u044b\u0445/","mdate_format":"%Y.%m.%d %H:%M:%S","cdate_format":"%Y.%m.%d %H:%M:%S","months_long":"\u044f\u043d\u0432\u0430\u0440\u044c,\u0444\u0435\u0432\u0440\u0430\u043b\u044c,\u043c\u0430\u0440\u0442,\u0430\u043f\u0440\u0435\u043b\u044c,\u043c\u0430\u0439,\u0438\u044e\u043d\u044c,\u0438\u044e\u043b\u044c,\u0430\u0432\u0433\u0443\u0441\u0442,\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044c,\u043e\u043a\u0442\u044f\u0431\u0440\u044c,\u043d\u043e\u044f\u0431\u0440\u044c,\u0434\u0435\u043a\u0430\u0431\u0440\u044c","months_short":"\u044f\u043d\u0432,\u0444\u0435\u0432,\u043c\u0430\u0440\u0442,\u0430\u043f\u0440,\u043c\u0430\u0439,\u0438\u044e\u043d\u044c,\u0438\u044e\u043b\u044c,\u0430\u0432\u0433,\u0441\u0435\u043d,\u043e\u043a\u0442,\u043d\u043e\u044f,\u0434\u0435\u043a","day_long":"\u0432\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435,\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a,\u0432\u0442\u043e\u0440\u043d\u0438\u043a,\u0441\u0440\u0435\u0434\u0430,\u0447\u0435\u0442\u0432\u0435\u0440\u0433,\u043f\u044f\u0442\u043d\u0438\u0446\u0443,\u0441\u0443\u0431\u0431\u043e\u0442\u0430,\u0432\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435","day_short":"\u0432\u0441,\u043f\u043d,\u0432\u0442,\u0441\u0440,\u0447\u0442,\u043f\u0442,\u0441\u0431,\u0432\u0441"});

View File

@ -1 +0,0 @@
tinyMCE.addI18n('ru.xhtmlxtras_dlg',{"attribs_title":"\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430","option_rtl":"\u0421\u043f\u0440\u0430\u0432\u0430 \u043d\u0430\u043b\u0435\u0432\u043e","option_ltr":"\u0421\u043b\u0435\u0432\u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u043e","insert_date":"\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0434\u0430\u0442\u0443/\u0432\u0440\u0435\u043c\u044f",remove:"\u0423\u0434\u0430\u043b\u0438\u0442\u044c","title_cite_element":"\u0426\u0438\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435","title_abbr_element":"\u0421\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u0435","title_acronym_element":"\u0410\u0431\u0431\u0440\u0435\u0432\u0438\u0430\u0446\u0438\u044f","title_del_element":"\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435","title_ins_element":"\u0417\u0430\u043c\u0435\u043d\u0430","fieldset_events_tab":"\u0421\u043e\u0431\u044b\u0442\u0438\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430","fieldset_attrib_tab":"\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430","fieldset_general_tab":"\u041e\u0431\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b","events_tab":"\u0421\u043e\u0431\u044b\u0442\u0438\u044f","attrib_tab":"\u0410\u0442\u0440\u0438\u0431\u0443\u0442\u044b","general_tab":"\u041e\u0431\u0449\u0435\u0435","attribute_attrib_tab":"\u0410\u0442\u0440\u0438\u0431\u0443\u0442\u044b","attribute_events_tab":"\u0421\u043e\u0431\u044b\u0442\u0438\u044f","attribute_label_accesskey":"\u041a\u043b\u044e\u0447 \u0434\u043e\u0441\u0442\u0443\u043f\u0430","attribute_label_tabindex":"\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a","attribute_label_langcode":"\u042f\u0437\u044b\u043a","attribute_option_rtl":"\u0421\u043f\u0440\u0430\u0432\u0430 \u043d\u0430\u043b\u0435\u0432\u043e","attribute_option_ltr":"\u0421\u043b\u0435\u0432\u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u043e","attribute_label_langdir":"\u041d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0430","attribute_label_datetime":"\u0414\u0430\u0442\u0430/\u0412\u0440\u0435\u043c\u044f","attribute_label_cite":"\u0426\u0438\u0442\u0430\u0442\u0430","attribute_label_style":"\u0421\u0442\u0438\u043b\u044c","attribute_label_class":"\u041a\u043b\u0430\u0441\u0441","attribute_label_id":"\u0418\u043c\u044f","attribute_label_title":"\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a"});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
tinyMCE.addI18n('ru.simple',{"cleanup_desc":"\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u043b\u0438\u0448\u043d\u0438\u0439 \u043a\u043e\u0434","redo_desc":"\u0412\u0435\u0440\u043d\u0443\u0442\u044c (Ctrl+Y)","undo_desc":"\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c (Ctrl+Z)","numlist_desc":"\u041d\u0443\u043c\u0435\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a","bullist_desc":"\u041c\u0430\u0440\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a","striketrough_desc":"\u0417\u0430\u0447\u0435\u0440\u043a\u043d\u0443\u0442\u044b\u0439","underline_desc":"\u041f\u043e\u0434\u0447\u0435\u0440\u043a\u043d\u0443\u0442\u044b\u0439 (Ctrl+U)","italic_desc":"\u041a\u0443\u0440\u0441\u0438\u0432 (Ctrl+I)","bold_desc":"\u041f\u043e\u043b\u0443\u0436\u0438\u0440\u043d\u044b\u0439 (Ctrl+B)"});

View File

@ -6,7 +6,7 @@ require 'active_resource/railtie'
require 'sprockets/railtie'
Bundler.require
require 'locomotive'
require 'locomotive/engine'
module Dummy
class Application < Rails::Application
@ -43,8 +43,6 @@ module Dummy
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
config.middleware.use 'Locomotive::InlineEditorMiddleware'
end
end

View File

@ -1,44 +0,0 @@
.aloha-editable {
min-height: 1.2em;
outline: none;
}
.aloha-editable ::selection,
.aloha-editable ::-moz-selection {
background: #80B5F2;
color: white;
}
.aloha-editable-zerowidthfix {
padding: 0px 5px 0px 5px !important;
}
.aloha-logo {
width:37px !important;
height:25px !important;
background-image: url('../img/gentics-logo.png') !important;
}
.aloha-maximize {
background-image: url('../img/gentics-logo.png') !important;
}
.aloha-fade-out {
background-image: url('../img/fade-out.png') !important;
width:20px !important;
height:20px !important;
}
.aloha-fade-in {
background-image: url('../img/fade-in.png') !important;
width:20px !important;
height:20px !important;
}
.aloha-maximize {
width:20px !important;
height:20px !important;
background-image: url('../img/maximize.png') !important;
}
.aloha-textarea {
overflow: hidden;
border:1px solid #ccc;
padding:6px;
overflow:auto;
}

View File

@ -1,284 +0,0 @@
.aloha-sidebar-bar {
z-index: 999999999;
position: fixed;
top: 0;
left: 0;
text-align: left;
font-family: Arial, sans-serif;
font-size: 12px;
border-right: 1px solid #888;
-moz-box-shadow: 0px 0px 10px rgba(0, 0, 0, .5);
-webkit-box-shadow: 0px 0px 10px rgba(0, 0, 0, .5);
box-shadow: 0px 0px 10px rgba(0, 0, 0, .5);
}
.aloha-sidebar-bar.aloha-sidebar-right {
left: auto;
right: 0;
border-right-width: 0;
border-left: 1px solid #888;
}
.aloha-sidebar-inner {
position: relative;
background-color: #ccc;
background-image: -webkit-radial-gradient(
rgba(0, 0, 0, 0.0) 20%,
rgba(0, 0, 0, 0.2) 80%,
rgba(0, 0, 0, 0.3) 100%
);
background-image: -moz-radial-gradient(
rgba(0, 0, 0, 0.0) 20%,
rgba(0, 0, 0, 0.2) 80%,
rgba(0, 0, 0, 0.3) 100%
);
}
.aloha-sidebar-panels {
margin: 0;
padding: 15px 0;
}
.aloha-sidebar-panels li {
overflow: hidden;
margin: 0;
padding: 0 15px;
}
.aloha-sidebar-panel-top {
-webkit-border-top-left-radius: 5px;
-webkit-border-top-right-radius: 5px;
-moz-border-radius-topleft: 5px;
-moz-border-radius-topright: 5px;
}
.aloha-sidebar-panel-content.aloha-sidebar-panel-bottom {
padding-bottom: 0;
-webkit-border-bottom-left-radius: 5px;
-webkit-border-bottom-right-radius: 5px;
-moz-border-radius-bottomleft: 5px;
-moz-border-radius-bottomright: 5px;
border-bottom-width: 1px;
}
.aloha-sidebar-panel-title {
position: relative;
overflow: hidden;
padding: 8px 0 0 8px;
border: 1px solid rgba(0, 0, 0, 0.3);
border-bottom-width: 0;
background-color: #303539;
background-image: -webkit-gradient(
linear,
center top,
center bottom,
color-stop(0.00, #6c6f74),
color-stop(0.05, #4c4f54),
color-stop(0.10, #3f4448),
color-stop(0.45, #383d41),
color-stop(0.50, #303539),
color-stop(0.95, #33363b)
);
background-image: -moz-linear-gradient(
center top,
#6c6f74 0%,
#4c4f54 5%,
#3f4448 10%,
#383d41 45%,
#303539 50%,
#33363b 95%
);
color: #ccc;
cursor: pointer;
font-size: 13px;
font-weight: bold;
line-height: 1.5em;
text-shadow: 0 0 6px #23262b;
}
.aloha-sidebar-panel-title:hover {
color: #fff;
}
.aloha-sidebar-panel-title-arrow {
position: absolute;
top: 8px;
left: 8px;
width: 16px;
height: 16px;
background: url(../img/arrow.png) no-repeat center center;
opacity: 0.3;
}
.aloha-sidebar-panel-title:hover .aloha-sidebar-panel-title-arrow {
opacity: 0.9;
}
.aloha-sidebar-panel-title .aloha-sidebar-panel-title-arrow.aloha-sidebar-panel-title-arrow-down {
background-image: url(../img/arrow-down.png);
}
.aloha-sidebar-panel-title-text {
margin-left: 24px;
white-space: nowrap;
}
.aloha-sidebar-panel-content {
overflow: hidden;
height: 5px;
background: #303539;
}
.aloha-sidebar-panel-content-inner {
margin: 5px 0 0;
padding: 0;
color: #888;
background: #fff;
background-image: -webkit-radial-gradient(
rgba(0, 0, 0, 0.0) 50%,
rgba(0, 0, 0, 0.1) 90%,
rgba(0, 0, 0, 0.2) 100%
);
background-image: -moz-radial-gradient(
rgba(0, 0, 0, 0.0) 50%,
rgba(0, 0, 0, 0.1) 90%,
rgba(0, 0, 0, 0.2) 100%
);
}
.aloha-sidebar-panel-content input {
margin: 5px;
padding: 5px;
}
.aloha-sidebar-handle {
position: absolute;
top: 30px;
right: -30px;
width: 40px;
height: 30px;
overflow: hidden;
background-color: #303539;
background-image: -webkit-gradient(
linear,
center top,
center bottom,
color-stop(0.00, #6c6f74),
color-stop(0.05, #4c4f54),
color-stop(0.10, #3f4448),
color-stop(0.45, #383d41),
color-stop(0.50, #303539),
color-stop(0.95, #33363b)
);
background-image: -moz-linear-gradient(
center top,
#6c6f74 0%,
#4c4f54 5%,
#3f4448 10%,
#383d41 45%,
#303539 50%,
#33363b 95%
);
cursor: pointer;
-moz-box-shadow: 0px 0px 10px rgba(0, 0, 0, .5);
-webkit-box-shadow: 0px 0px 10px rgba(0, 0, 0, .5);
box-shadow: 0px 0px 10px rgba(0, 0, 0, .5);
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
-moz-border-radius-topright: 5px;
-moz-border-radius-bottomright: 5px;
-webkit-border-top-right-radius: 5px;
-webkit-border-bottom-right-radius: 5px;
}
.aloha-sidebar-right .aloha-sidebar-handle {
left: -30px;
border-top-right-radius: 0px;
border-bottom-right-radius: 0px;
-moz-border-radius-topright: 0px;
-moz-border-radius-bottomright: 0px;
-webkit-border-top-right-radius: 0px;
-webkit-border-bottom-right-radius: 0px;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
-moz-border-radius-topleft: 5px;
-moz-border-radius-bottomleft: 5px;
-webkit-border-top-left-radius: 5px;
-webkit-border-bottom-left-radius: 5px;
}
.aloha-sidebar-handle-icon {
display: block;
position: absolute;
top: 5px;
right: 5px;
background: url(../img/arrow.png) no-repeat center center;
width: 20px;
height: 20px;
opacity: 0.5;
}
.aloha-sidebar-right .aloha-sidebar-handle-icon {
left: 5px;
right: auto;
}
.aloha-sidebar-handle-icon.aloha-sidebar-handle-icon-left {
background-image: url(../img/arrow-left.png);
}
.aloha-sidebar-panel-parent-path {
background-color: #303539;
background-image: -webkit-gradient(
linear,
center top,
center bottom,
color-stop(0.00, #6c6f74),
color-stop(0.05, #4c4f54),
color-stop(0.10, #3f4448),
color-stop(0.45, #383d41),
color-stop(0.50, #303539),
color-stop(0.95, #33363b)
);
background-image: -moz-linear-gradient(
center top,
#6c6f74 0%,
#4c4f54 5%,
#3f4448 10%,
#383d41 45%,
#303539 50%,
#33363b 95%
);
color: #fff;
cursor: pointer;
font-size: 12px;
text-shadow: 0 0 6px #23262b;
white-space: nowrap;
line-height: 1em;
}
.aloha-sidebar-panel-parent-path:hover {
opacity: 0.9;
}
.aloha-sidebar-panel-parent-path span {
display: inline-block;
padding: 0 10px 0 5px;
background: url(../img/breadcrumb-divider.png) no-repeat right center;
opacity: 0.25;
line-height: 1.6em;
}
.aloha-sidebar-panel-parent-path span:first-child {
font-weight: bold;
opacity: 0.8;
}
.aloha-sidebar-panel-parent-path span:last-child {
background: none;
}
.aloha-sidebar-panel-parent-content {
padding: 4px;
background-image: -webkit-gradient(
linear,
center top,
center bottom,
color-stop(0.0, rgba(0, 0, 0, 0.25)),
color-stop(0.05, rgba(0, 0, 0, 0.0))
);
background-image: -moz-linear-gradient(
center top,
rgba(0, 0, 0, 0.25) 0%,
rgba(0, 0, 0, 0.0) 5%
);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,33 +0,0 @@
.aloha-floatingmenu table, .aloha-floatingmenu tr, .aloha-floatingmenu td,
.ext-root table, .ext-root tr, .ext-root td,
table.x-layer, .x-layer tr, .x-layer td,
table.x-window, .x-window tr, .x-window td,
table.x-toolbar-ct, .x-toolbar-ct tr, .x-toolbar-ct td,
table.x-toolbar-left, .x-toolbar-left tr, .x-toolbar-left td,
table.x-table-layout, .x-table-layout tr, .x-table-layout td,
table.x-toolbar-ct table, .x-toolbar-cell td, .x-table-layout-cell td {
width: 0 !important;
height: 0 !important;
border: 0 !important;
padding: 0 !important;
margin: 0 !important;
background-color: transparent !important;
}
/* reset for floatingmenu */
div.aloha-floatingmenu, div.aloha-shadow {
min-width: 0px;
}
/* more specific for browsers that support nth-child. */
.ext-root tr:nth-child(2n), .ext-root tr:nth-child(3n), .ext-root tr:nth-child(4n), .ext-root tr:nth-child(5n) {
width: 0 !important;
height: 0 !important;
border: 0 !important;
padding: 0 !important;
margin: 0 !important;
background-color: transparent !important;
}
.ext-root ol, .ext-root ul, .x-menu ul, .x-menu ol {
list-style:none;
margin:0;
padding:0;
}

View File

@ -1,357 +0,0 @@
.aloha-floatingmenu {
position: absolute;
}
.aloha-floatingmenu.fixed {
position: fixed !important;
}
.aloha-floatingmenu .x-tab-panel-header {
border-width: 0px 0px 1px 0px !important;
background: none !important;
}
.aloha-floatingmenu .x-tab-panel-header .x-tab-strip-wrap, .aloha-floatingmenu ul.x-tab-strip-top {
background: none !important;
}
.x-tab-strip-wrap ul li a:hover {
border: none;
text-decoration:none;
}
.aloha-floatingmenu .x-tab-panel-header {
padding-bottom: 0px !important;
}
.aloha-floatingmenu:hover {
background-color: #E0E0E0;
-moz-border-radius-topleft: 3px;
-moz-border-radius-topright: 3px;
-webkit-border-top-left-radius: 3px;
-webkit-border-top-right-radius: 3px;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
background: url(../img/grabhandle.png) no-repeat scroll center 5px rgba(0, 0, 0, 0.4);
}
.aloha-floatingmenu:hover .aloha-floatingmenu-pin {
display: block;
}
.aloha-floatingmenu-pin {
background: url("../img/pin.png") no-repeat scroll 0 6px transparent;
cursor: pointer;
margin-left: 5px !important;
width: 16px;
position: absolute !important;
right: 10px;
display: none;
}
.aloha-floatingmenu-pinned {
background-position: -16px 6px;
}
#aloha-floatingmenu-shadow {
position: absolute;
top: -1000;
left: -1000;
display: none;
z-index: 8800;
}
#aloha-floatingmenu-shadow.fixed {
position: fixed !important;
}
.x-tree-root-ct {
padding: 0px;
}
.x-tree-node {
list-style: none;
}
.x-tree-node-ct {
padding: 0px;
}
.aloha-button a:focus {
outline: none;
}
button.aloha-button {
background: url('../img/base.png') no-repeat !important;
}
button.aloha-button-big {
background: url('../img/base-big.png') no-repeat !important;
}
button.aloha-button-b {
background-position: 0px 0px;
}
button.aloha-button-i {
background-position: -16px 0px !important;
}
button.aloha-button-u {
background-position: -32px 0px !important;
}
button.aloha-button-del {
background-position: -48px 0px !important;
}
button.aloha-button-sub {
background-position: -64px 0px !important;
}
button.aloha-button-sup {
background-position: -80px 0px !important;
}
button.aloha-button-ul {
background-position: -256px 0px !important;
}
button.aloha-button-ol {
background-position: -272px 0px !important;
}
button.aloha-button-indent-list {
background-image: url(../img/text_indent.png) !important;
}
button.aloha-button-outdent-list {
background-image: url(../img/text_indent_remove.png) !important;
}
button.aloha-button-a {
background-position: -288px 0px !important;
}
button.aloha-button-a-remove {
background-position: -304px 0px !important;
}
button.aloha-button-p {
background-position: 0px 0 !important;
}
button.aloha-button-p-de {
background-position: 0px -42px !important;
}
button.aloha-button-h1 {
background-position: -52px 0 !important;
}
button.aloha-button-h1-de {
background-position: -52px -42px !important;
}
button.aloha-button-h2 {
background-position: -104px 0 !important;
}
button.aloha-button-h2-de {
background-position: -104px -42px !important;
}
button.aloha-button-h3 {
background-position: -156px 0 !important;
}
button.aloha-button-h3-de {
background-position: -156px -42px !important;
}
button.aloha-button-h4 {
background-position: -208px 0 !important;
}
button.aloha-button-h4-de {
background-position: -208px -42px !important;
}
button.aloha-button-h5 {
background-position: -260px 0 !important;
}
button.aloha-button-h5-de {
background-position: -260px -42px !important;
}
button.aloha-button-h6 {
background-position: -312px 0 !important;
}
button.aloha-button-h6-de {
background-position: -312px -42px !important;
}
button.aloha-button-pre {
background-position: -364px 0 !important;
}
button.aloha-button-pre-de {
background-position: -364px -42px !important;
}
button.aloha-button-title {
background-position: -416px 0 !important;
}
button.aloha-button-title-de {
background-position: -416px -42px !important;
}
button.aloha-button-table {
background-position: -96px 0 !important;
}
button.aloha-button-addColumnLeft {
background-position: -112px 0 !important;
}
button.aloha-button-addColumnRight {
background-position: -128px 0 !important;
}
button.aloha-button-addRowBefore {
background-position: -144px 0 !important;
}
button.aloha-button-addRowAfter {
background-position: -160px 0 !important;
}
button.aloha-button-deleteRows {
background-position: -176px 0 !important;
}
button.aloha-button-deleteColumns {
background-position: -192px 0 !important;
}
button.aloha-button-addPerson {
background-position: -224px 0 !important;
}
button.aloha-button-addEvent {
background-position: -208px 0 !important;
}
button.aloha-button-abbr {
background-position: -336px 0px !important;
}
button.aloha-button-row-header {
background-position: -352px 0px !important;
}
button.aloha-button-col-header {
background-position: -368px 0px !important;
}
button.aloha-button-tree {
background-position: -0 0 !important;
}
div.aloha-button a:hover {
border: 1px solid #b2cbff;
}
.aloha-floatingmenu {
display: none;
}
.aloha-floatingmenu .pressed a {
border:1px solid #ccc;
}
html body #aloha-ribbon {
z-index:90000;
position:fixed;
top:0;
left:0;
width:100%;
padding-left:0;
padding-right:0;
display: none;
}
.x-menu-list-item {
text-align:left;
}
.aloha-shadow {
-moz-box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.3);
-webkit-box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.3);
box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.3);
}
ul.aloha-multisplit button.aloha-button {
background-image: url(../img/base-multi.png) !important;
background-repeat: no-repeat;
background-position: 0 0;
width: 54px !important;
height: 44px !important;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
}
.aloha-multisplit {
float: left;
list-style: none;
}
ul.aloha-multisplit, div.aloha-multisplit-wrapper {
width: 232px;
height: 46px;
overflow: hidden;
margin: 0px;
padding: 0px;
}
div.aloha-multisplit-wrapper {
width: 248px;
}
ul.aloha-multisplit li {
float: left;
padding: 0px 1px;
margin: 0px;
}
ul.aloha-multisplit button.aloha-multisplit-wide {
font: 11px tahoma,arial,helvetica;
height: 18px !important;
width: 234px !important;
border: 0;
border-top: 1px solid #cccccc;
cursor: pointer;
background-color: white;
background-repeat: no-repeat;
background-position: 6px 1px !important;
text-align: left;
margin-left: -2px;
padding-left: 26px;
}
button.aloha-multisplit-toggle {
float: right;
margin: 0;
padding: 0;
width: 15px;
height: 12px;
margin-top: 32px;
cursor: pointer;
border: 0;
}
button.aloha-multisplit-toggle-open {
background-image: url(../img/multisplit-open.gif);
}
button.aloha-multisplit-toggle-close {
background-image: url(../img/multisplit-close.gif);
}
ul.aloha-multisplit button {
border: 1px solid #cccccc;
margin: 1px;
cursor: pointer;
}
ul.aloha-multisplit button:hover {
border: 1px solid #666666;
}
ul.aloha-multisplit button.aloha-multisplit-wide:hover {
border: 0;
border-top: 1px solid #cccccc;
}
ul.aloha-multisplit .aloha-multisplit-activeitem button {
border: 2px solid #3B73D7;
}
ul.aloha-multisplit-expanded {
position: absolute;
top: 0px;
left: 0px;
z-index: 20000;
background-color: white;
border: 1px solid #afafaf;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
}
ul.aloha-multisplit button.aloha-button-removeFormat {
background-image: url(../img/removeformat.png) !important;
}
/**
* combo-list box
*/
.x-combo-list {
text-align: left;
}
.x-combo-list-inner {
padding: 3px;
}
.x-combo-list-inner .loading-indicator {
margin: 0;
}
.x-combo-selected {
color: #fff !important;
background-color: #3B73D7 !important;
}
/**
* ui-attribute field
*/
.x-form-field.x-form-text {
color: #333 !important;
padding: 3px;
}
.x-form-field.x-form-text::selection {
color: #fff;
background: #3B73D7;
}
.x-form-field.x-form-text::-moz-selection {
color: #fff;
background: #3B73D7;
}
.x-form-field.x-form-text::-webkit-selection {
color: #fff;
background: #3B73D7;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 770 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 790 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 719 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 509 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 330 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 929 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 351 B

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,246 +0,0 @@
/*!
* CommandManager file is part of Aloha Editor Project http://aloha-editor.org
* Copyright (c) 2010-2011 Gentics Software GmbH, aloha@gentics.com
* Contributors http://aloha-editor.org/contribution.php
* Licensed unter the terms of http://www.aloha-editor.org/license.html
*//*
* Aloha Editor is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.*
*
* Aloha Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with CommandManager program. If not, see <http://www.gnu.org/licenses/>.
*/
define( [ 'aloha/core', 'aloha/registry', 'aloha/engine', 'util/dom', 'aloha/contenthandlermanager' ],
function( Aloha, Registry, Engine, Dom, ContentHandlerManager ) {
// Action: What the command does when executed via execCommand(). Every command defined
// in CommandManager specification has an action defined for it in the relevant section. For example,
// the bold command's action generally makes the current selection bold, or removes bold if
// the selection is already bold. An editing toolbar might provide buttons that execute the
// action for a command if clicked, or a script might run an action without user interaction
// to achieve some particular effect.
//
// Indeterminate: A boolean value returned by queryCommandIndeterm(), depending on the
// current state of the document. Generally, a command that has a state defined will be
// indeterminate if the state is true for part but not all of the current selection, and a
// command that has a value defined will be indeterminate if different parts of the
// selection have different values. An editing toolbar might display a button or control
// in a special way if the command is indeterminate, like showing a "bold" button as
// partially depressed, or leaving a font size selector blank instead of showing the font
// size of the current selection. As a rule, a command can only be indeterminate if its
// state is false, supposing it has a state.
//
// State: A boolean value returned by queryCommandState(), depending on the current state
// of the document. The state of a command is true if it is already in effect, in some
// sense specific to the command. Most commands that have a state defined will take opposite
// actions depending on whether the state is true or false, such as making the selection
// bold if the state is false and removing bold if the state is true. Others will just
// have no effect if the state is true, like the justifyCenter command. Still others will
// have the same effect regardless, like the styleWithCss command. An editing toolbar might
// display a button or control differently depending on the state and indeterminacy of the
// command.
//
// Value: A string returned by queryCommandValue(), depending on the current state of the
// document. A command usually has a value instead of a state if the property it modifies
// can take more than two different values, like the foreColor command. If the command is
// indeterminate, its value is generally based on the start of the selection. Otherwise,
// in most cases the value holds true for the entire selection, but see the justifyCenter
// command and its three companions for an exception. An editing toolbar might display the
// value of a command as selected in a drop-down or filled in in a text box, if the command
// isn't indeterminate.
//
// Relevant CSS property: CommandManager is defined for certain inline formatting commands, and
// is used in algorithms specific to those commands. It is an implementation detail, and
// is not exposed to authors. If a command does not have a relevant CSS property
// specified, it defaults to null.
var CommandManager = {
execCommand: function( commandId, showUi, value, range ) {
// Read current selection if not passed
if ( !range ) {
if ( !Aloha.getSelection().getRangeCount() ) {
return;
}
range = Aloha.getSelection().getRangeAt( 0 );
}
// For the insertHTML command we provide contenthandler API
if ( commandId == 'insertHTML' ) {
//if (typeof Aloha.settings.contentHandler.insertHtml === 'undefined') {
// use all registered content handler; used for copy & paste atm (or write log message)
// Aloha.settings.contentHandler.insertHtml = Aloha.defaults.contentHandler.insertHtml;
//}
value = ContentHandlerManager.handleContent( value, {
contenthandler: Aloha.settings.contentHandler.insertHtml
});
}
Engine.execCommand( commandId, showUi, value, range );
// Read range after engine modification
range = Aloha.getSelection().getRangeAt( 0 );
// FIX: doCleanup should work with W3C range
var startnode = range.commonAncestorContainer.parentNode;
var rangeObject = new window.GENTICS.Utils.RangeObject();
rangeObject.startContainer = range.startContainer;
rangeObject.startOffset = range.startOffset;
rangeObject.endContainer = range.endContainer;
rangeObject.endOffset = range.endOffset;
Dom.doCleanup({merge:true, removeempty: false}, rangeObject, startnode);
rangeObject.select();
Aloha.trigger('aloha-command-executed', commandId);
},
// If command is available and not disabled or the active range is not null
// the command is enabled
queryCommandEnabled: function( commandId, range ) {
// Take current selection if not passed
if ( !range ) {
if ( !Aloha.getSelection().getRangeCount() ) {
return;
}
range = Aloha.getSelection().getRangeAt(0);
}
return Engine.queryCommandEnabled( commandId, range );
},
// "Return true if command is indeterminate, otherwise false."
queryCommandIndeterm: function( commandId, range ) {
// Take current selection if not passed
if ( !range ) {
if ( !Aloha.getSelection().getRangeCount() ) {
return;
}
range = Aloha.getSelection().getRangeAt(0);
}
return Engine.queryCommandIndeterm( commandId, range );
},
queryCommandState: function( commandId, range ) {
// Take current selection if not passed
if ( !range ) {
if ( !Aloha.getSelection().getRangeCount() ) {
return;
}
range = Aloha.getSelection().getRangeAt(0);
}
return Engine.queryCommandState( commandId, range );
},
// "When the queryCommandSupported(command) method on the HTMLDocument
// interface is invoked, the user agent must return true if command is
// supported, and false otherwise."
queryCommandSupported: function( commandId ) {
return Engine.queryCommandSupported( commandId );
},
queryCommandValue: function( commandId, range ) {
// Take current selection if not passed
if ( !range ) {
if ( !Aloha.getSelection().getRangeCount() ) {
return;
}
range = Aloha.getSelection().getRangeAt(0);
}
// "Return command's value."
return Engine.queryCommandValue( commandId, range );
},
querySupportedCommands: function() {
var
commands = [],
command;
for ( command in Engine.commands ) {
commands.push( command );
}
return commands;
}
};
// create an instance
CommandManager = new ( Registry.extend( CommandManager ) )();
/**
* Executes a registered command.
* http://aryeh.name/spec/editing/editing.html#methods-of-the-htmldocument-interface
* @method
* @param command name of the command
* @param showUI has no effect for Aloha Editor and is only here because in spec...
* @param value depends on the used command and it impementation
* @range optional a range on which the command will be executed if not specified
* the current selection will be used as range
*/
Aloha.execCommand = CommandManager.execCommand;
/**
* Check wheater the command in enabled.
* If command is not supported, raise a NOT_SUPPORTED_ERR exception.
* @param command name of the command
* @return true if command is enabled, false otherwise.
*/
Aloha.queryCommandEnabled = CommandManager.queryCommandEnabled;
/**
* Check if the command has an indetermed state.
* If command is not supported, a NOT_SUPPORTED_ERR exception is thrown
* If command has no indeterminacy, INVALID_ACCESS_ERR exception is thrown
* If command is not enabled, return false.
* @param command name of the command
* @range optional a range on which the command will be executed if not specified
* the current selection will be used as range
* @return true if command is indeterminate, otherwise false.
*/
Aloha.queryCommandIndeterm = CommandManager.queryCommandIndeterm;
/**
* Returns the state of a given command
* If command is not supported, a NOT_SUPPORTED_ERR exception is thrown
* If command has no state, an INVALID_ACCESS_ERR exception is thrown
* If command is not enabled, return false
* If the state override for command is set, it returns the state
* @param command name of the command
* @return state override or true if command's state is true, otherwise false.
*/
Aloha.queryCommandState = CommandManager.queryCommandState;
/**
* Check if a given command is supported
* @return true if command is supported, and false otherwise.
*/
Aloha.queryCommandSupported = CommandManager.queryCommandSupported;
/**
* Returns the Value of a given Command
* If command is not supported, a NOT_SUPPORTED_ERR exception is thrown
* If command is not enabled, returns an empty string
* If command is "fontSize" and its value override is set, an integer
* number of pixels is returned as font size for the result.
* If the value override for command is set, it returns that.
* @return command's value.
*/
Aloha.queryCommandValue = CommandManager.queryCommandValue;
Aloha.querySupportedCommands = CommandManager.querySupportedCommands;
return CommandManager;
});

View File

@ -1,330 +0,0 @@
/*!
* This file is part of Aloha Editor Project http://aloha-editor.org
* Copyright © 2010-2011 Gentics Software GmbH, aloha@gentics.com
* Contributors http://aloha-editor.org/contribution.php
* Licensed unter the terms of http://www.aloha-editor.org/license.html
*//*
* Aloha Editor is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.*
*
* Aloha Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(
['aloha/core', 'util/class', 'aloha/jquery'],
function(Aloha, Class, jQuery ) {
var
// $ = jQuery,
// Aloha = window.Aloha,
console = window.console;
// Class = window.Class
// GENTICS = window.GENTICS;
/**
* This is the aloha Log
* @namespace Aloha
* @class Log
* @singleton
*/
var alohaConsole = Class.extend({
/**
* Initialize the logging
* @hide
*/
init: function() {
// initialize the logging settings (if not present)
if (typeof Aloha.settings.logLevels === 'undefined' || !Aloha.settings.logLevels) {
Aloha.settings.logLevels = {'error' : true, 'warn' : true};
}
// initialize the logHistory settings (if not present)
if (typeof Aloha.settings.logHistory === 'undefined' || !Aloha.settings.logHistory) {
Aloha.settings.logHistory = {};
}
// set the default values for the loghistory
if (!Aloha.settings.logHistory.maxEntries) {
Aloha.settings.logHistory.maxEntries = 100;
}
if (!Aloha.settings.logHistory.highWaterMark) {
Aloha.settings.logHistory.highWaterMark = 90;
}
if (!Aloha.settings.logHistory.levels) {
Aloha.settings.logHistory.levels = {'error' : true, 'warn' : true};
}
this.flushLogHistory();
Aloha.trigger('aloha-logger-ready');
},
/**
* Log History as array of Message Objects. Every object has the properties
* 'level', 'component' and 'message'
* @property
* @type Array
* @hide
*/
logHistory: [],
/**
* Flag, which is set as soon as the highWaterMark for the log history is reached.
* This flag is reset on every call of flushLogHistory()
* @hide
*/
highWaterMarkReached: false,
/**
* Logs a message to the console
* @method
* @param {String} level Level of the log ('error', 'warn' or 'info', 'debug')
* @param {String} component Component that calls the log
* @param {String} message log message
*/
log: function(level, component, message) {
// log ('Logging message');
if ( typeof component === 'undefined' ) {
message = level;
}
if ( typeof component !== 'string' && component && component.toString ) {
component = component.toString();
}
// log ('warn', 'Warning message');
if ( typeof message === 'undefined' ) {
message = component;
component = undefined;
}
if (typeof level === 'undefined' || !level) {
level = 'log';
}
level = level.toLowerCase();
if ( typeof Aloha.settings.logLevels === "undefined" ) {
return;
}
// now check whether the log level is activated
if ( !Aloha.settings.logLevels[ level ] ) {
return;
}
component = component || "Unkown Aloha Component";
this.addToLogHistory({'level' : level, 'component' : component, 'message' : message, 'date' : new Date()});
switch (level) {
case 'error':
if (window.console && console.error) {
// FIXME:
// Using console.error rather than throwing an error is very
// problematic because we get not stack.
// We ought to consider doing the following:
// throw component + ': ' + message;
if(!component && !message) {
console.error("Error occured without message and component");
} else {
console.error(component + ': ' + message);
}
}
break;
case 'warn':
if (window.console && console.warn) {
console.warn(component + ': ' + message);
}
break;
case 'info':
if (window.console && console.info) {
console.info(component + ': ' + message);
}
break;
case 'debug':
if (window.console && console.log) {
console.log(component + ' [' + level + ']: ' + message);
}
break;
default:
if (window.console && console.log) {
console.log(component + ' [' + level + ']: ' + message);
}
break;
}
},
/**
* Log a message of log level 'error'
* @method
* @param {String} component Component that calls the log
* @param {String} message log message
*/
error: function(component, message) {
this.log('error', component, message);
},
/**
* Log a message of log level 'warn'
* @method
* @param {String} component Component that calls the log
* @param {String} message log message
*/
warn: function(component, message) {
this.log('warn', component, message);
},
/**
* Log a message of log level 'info'
* @method
* @param {String} component Component that calls the log
* @param {String} message log message
*/
info: function(component, message) {
this.log('info', component, message);
},
/**
* Log a message of log level 'debug'
* @param {String} component Component that calls the log
* @param {String} message log message
*/
debug: function(component, message) {
this.log('debug', component, message);
},
/**
* Methods to mark function as deprecated for developers.
* @param {String} component String that calls the log
* @param {String} message log message
*/
deprecated: function(component, message) {
this.log( 'warn', component, message );
// help the developer to locate the call.
if ( Aloha.settings.logLevels[ 'deprecated' ] ) {
throw new Error ( message );
}
},
/**
* Check whether the given log level is currently enabled
* @param {String} level
* @return true when log level is enabled, false if not
*/
isLogLevelEnabled: function(level) {
return Aloha.settings && Aloha.settings.logLevels && Aloha.settings.logLevels[level];
},
/**
* Check whether error logging is enabled
* @return true if error logging is enabled, false if not
*/
isErrorEnabled: function() {
return this.isLogLevelEnabled('error');
},
/**
* Check whether warn logging is enabled
* @return true if warn logging is enabled, false if not
*/
isWarnEnabled: function() {
return this.isLogLevelEnabled('warn');
},
/**
* Check whether info logging is enabled
* @return true if info logging is enabled, false if not
*/
isInfoEnabled: function() {
return this.isLogLevelEnabled('info');
},
/**
* Check whether debug logging is enabled
* @return true if debug logging is enabled, false if not
*/
isDebugEnabled: function() {
return this.isLogLevelEnabled('debug');
},
/**
* Add the given entry to the log history. Check whether the highWaterMark has been reached, and fire an event if yes.
* @param {Object} entry entry to be added to the log history
* @hide
*/
addToLogHistory: function(entry) {
if ( !Aloha.settings.logHistory ) {
this.init();
}
// when maxEntries is set to something illegal, we do nothing (log history is disabled)
// check whether the level is one we like to have logged
if ( Aloha.settings.logHistory.maxEntries <= 0
|| !Aloha.settings.logHistory.levels[ entry.level ]
) {
return;
}
// first add the entry as last element to the history array
this.logHistory.push( entry );
// check whether the highWaterMark was reached, if so, fire an event
if ( !this.highWaterMarkReached ) {
if ( this.logHistory.length >= Aloha.settings.logHistory.maxEntries * Aloha.settings.logHistory.highWaterMark / 100 ) {
// fire the event
Aloha.trigger('aloha-log-full');
// set the flag (so we will not fire the event again until the logHistory is flushed)
this.highWaterMarkReached = true;
}
}
// check whether the log is full and eventually remove the oldest entries
while ( this.logHistory.length > Aloha.settings.logHistory.maxEntries ) {
this.logHistory.shift();
}
},
/**
* Get the log history
* @return log history as array of objects
* @hide
*/
getLogHistory: function() {
return this.logHistory;
},
/**
* Flush the log history. Remove all log entries and reset the flag for the highWaterMark
* @return void
* @hide
*/
flushLogHistory: function() {
this.logHistory = [];
this.highWaterMarkReached = false;
}
});
/**
* Create the Log object
* @hide
*/
alohaConsole = new alohaConsole();
// add to log namespace for compatiblility.
return Aloha.Log = Aloha.Console = alohaConsole;
});

View File

@ -1,65 +0,0 @@
/*!
* Aloha Editor
* Author & Copyright (c) 2010 Gentics Software GmbH
* aloha-sales@gentics.com
* Licensed unter the terms of http://www.aloha-editor.com/license.html
*/
define(
['aloha/jquery', 'aloha/registry'],
function( jQuery, Registry ) {
/**
* Create an contentHandler from the given definition. Acts as a factory method
* for contentHandler.
*
* @param {Object} definition
*/
return new ( Registry.extend({
createHandler: function( definition ) {
if ( typeof definition.handleContent != 'function' ) {
throw 'ContentHandler has no function handleContent().';
}
var AbstractContentHandler = Class.extend({
handleContent: function( content ) {
// Implement in subclass!
}
}, definition);
return new AbstractContentHandler();
},
handleContent: function ( content, options ) {
var handler,
handlers = this.getEntries();
if ( typeof options.contenthandler === 'undefined') {
options.contenthandler = [];
for ( handler in handlers ) {
if ( handlers.hasOwnProperty(handler) ) {
options.contenthandler.push(handler);
}
}
}
for ( handler in handlers ) {
if ( handlers.hasOwnProperty(handler) ) {
if (jQuery.inArray( handler, options.contenthandler ) < 0 ) {
continue;
}
if ( typeof handlers[handler].handleContent === 'function') {
content = handlers[handler].handleContent( content, options );
} else {
console.error( 'A valid content handler needs the method handleContent.' );
}
}
}
return content;
}
}))();
});

View File

@ -1,560 +0,0 @@
/*!
* This file is part of Aloha Editor Project http://aloha-editor.org
* Copyright © 2010-2011 Gentics Software GmbH, aloha@gentics.com
* Contributors http://aloha-editor.org/contribution.php
* Licensed unter the terms of http://www.aloha-editor.org/license.html
*//*
* Aloha Editor is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.*
*
* Aloha Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(
[
'aloha/jquery',
'aloha/pluginmanager'
],
function ( jQuery, PluginManager ) {
//----------------------------------------
// Private variables
//----------------------------------------
/**
* Hash table that will be populated through the loadPlugins method.
* Maps the names of plugins with their urls for easy assess in the getPluginsUrl method
*/
var pluginPaths = {};
/**
* Base Aloha Object
* @namespace Aloha
* @class Aloha The Aloha base object, which contains all the core functionality
* @singleton
*/
jQuery.extend(true, Aloha, {
/**
* The Aloha Editor Version we are using
* It should be set by us and updated for the particular branch
* @property
*/
version: '0.10.0',
/**
* Array of editables that are managed by Aloha
* @property
* @type Array
*/
editables: [],
/**
* The currently active editable is referenced here
* @property
* @type Aloha.Editable
*/
activeEditable: null,
/**
* settings object, which will contain all Aloha settings
* @cfg {Object} object Aloha's settings
*/
settings: {},
/**
* defaults object, which will contain all Aloha defaults
* @cfg {Object} object Aloha's settings
*/
defaults: {},
/**
* Namespace for ui components
*/
ui: {},
/**
* This represents the name of the users OS. Could be:
* 'Mac', 'Linux', 'Win', 'Unix', 'Unknown'
* @property
* @type string
*/
OSName: 'Unknown',
/**
* Which stage is the aloha init process at?
* @property
* @type string
*/
stage: 'loadingAloha',
/**
* A list of loaded plugin names. Available after the
* "loadPlugins" stage.
*
* @property
* @type array
* @internal
*/
loadedPlugins: [],
requirePaths: [],
/**
* Initialize the initialization process
*/
init: function () {
// merge defaults and settings and provide all in settings
Aloha.settings = jQuery.extendObjects( true, {}, Aloha.defaults, Aloha.settings );
// initialize rangy. This is probably necessary here,
// because due to the current loading mechanism, rangy
// doesn't initialize itself in all browsers
if (window.rangy) {
window.rangy.init();
}
// Load & Initialise
Aloha.stage = 'loadPlugins';
Aloha.loadPlugins(function(){
Aloha.stage = 'initAloha';
Aloha.initAloha(function(){
Aloha.stage = 'initPlugins';
Aloha.initPlugins(function(){
Aloha.stage = 'initGui';
Aloha.initGui(function(){
Aloha.stage = 'alohaReady';
Aloha.trigger('aloha-ready');
});
});
});
});
},
/**
* Load Plugins
*/
loadPlugins: function (next) {
// contains an array like [common/format, common/block]
var configuredPluginsWithBundle = this.getPluginsToBeLoaded();
if (configuredPluginsWithBundle.length) {
var paths = {},
pluginNames = [],
requiredInitializers = [],
pathsToPlugins = {};
// Background: We do not use CommonJS packages for our Plugins
// as this breaks the loading order when these modules have
// other dependencies.
// We "emulate" the commonjs modules with the path mapping.
/* require(
* { paths: {
* 'format': 'plugins/common/format/lib',
* 'format/nls': 'plugins/common/format/nls',
* ... for every plugin ...
* }
* },
* ['format/format-plugin', ... for every plugin ...],
* next <-- when everything is loaded, we continue
*/
jQuery.each(configuredPluginsWithBundle, function (i, configuredPluginWithBundle) {
var tmp, bundleName, pluginName, bundlePath = '';
tmp = configuredPluginWithBundle.split('/');
bundleName = tmp[0];
pluginName = tmp[1];
// TODO assertion if pluginName or bundleName NULL _-> ERROR!!
if (Aloha.settings.basePath) {
bundlePath = Aloha.settings.basePath;
}
if (Aloha.settings.bundles && Aloha.settings.bundles[bundleName]) {
bundlePath += Aloha.settings.bundles[bundleName];
} else {
bundlePath += '../plugins/' + bundleName;
}
pluginNames.push(pluginName);
paths[pluginName] = bundlePath + '/' + pluginName + '/lib';
pathsToPlugins[pluginName] = bundlePath + '/' + pluginName;
// As the "nls" path lies NOT inside /lib/, but is a sibling to /lib/, we need
// to register it explicitely. The same goes for the "css" folder.
jQuery.each(['nls', 'css', 'vendor', 'res'], function() {
paths[pluginName + '/' + this] = bundlePath + '/' + pluginName + '/' + this;
});
requiredInitializers.push(pluginName + '/' + pluginName + '-plugin');
});
this.loadedPlugins = pluginNames;
this.requirePaths = paths;
// Main Require.js loading call, which fetches all the plugins.
require(
{
context: 'aloha',
paths: paths,
locale: this.settings.locale || this.defaults.locale || 'en'
},
requiredInitializers,
next
);
pluginPaths = pathsToPlugins;
} else {
next();
}
},
/**
* Fetches plugins the user wants to have loaded. Returns all plugins the user
* has specified with the data-plugins property as array, with the bundle
* name in front.
*
* @return array
* @internal
*/
getPluginsToBeLoaded: function() {
// look for data-aloha-plugins attributes and load values
var
plugins = jQuery('[data-aloha-plugins]').data('aloha-plugins');
// Determine Plugins
if ( typeof plugins === 'string' && plugins !== "") {
return plugins.replace(/\s+/g, '').split(',');
}
// Return
return [];
},
/**
* Returns list of loaded plugins (without Bundle name)
*
* @return array
*/
getLoadedPlugins: function() {
return this.loadedPlugins;
},
/**
* Returns true if a certain plugin is loaded, false otherwise.
*/
isPluginLoaded: function(pluginName) {
var found = false;
jQuery.each(this.loadedPlugins, function() {
if (pluginName.toString() === this.toString()) {
found = true;
}
});
return found;
},
/**
* Initialise Aloha
*/
initAloha: function(next){
// check browser version on init
// this has to be revamped, as
if (jQuery.browser.webkit && parseFloat(jQuery.browser.version) < 532.5 || // Chrome/Safari 4
jQuery.browser.mozilla && parseFloat(jQuery.browser.version) < 1.9 || // FF 3.5
jQuery.browser.msie && jQuery.browser.version < 7 || // IE 7
jQuery.browser.opera && jQuery.browser.version < 11 ) { // right now, Opera needs some work
if (window.console && window.console.log) {
window.console.log( 'Your browser is not supported.' );
}
}
// register the body click event to blur editables
jQuery('html').mousedown(function(e) {
// if an Ext JS modal is visible, we don't want to loose the focus on
// the editable as we assume that the user must have clicked somewhere
// in the modal... where else could he click?
// loosing the editable focus in this case hinders correct table
// column/row deletion, as the table module will clean it's selection
// as soon as the editable is deactivated. Fusubscriberthermore you'd have to
// refocus the editable again, which is just strange UX
if (Aloha.activeEditable && !Aloha.isMessageVisible() && !Aloha.eventHandled) {
Aloha.activeEditable.blur();
Aloha.activeEditable = null;
}
}).mouseup(function(e) {
Aloha.eventHandled = false;
});
// Initialise the base path to the aloha files
Aloha.settings.base = Aloha.getAlohaUrl();
// initialize the Log
Aloha.Log.init();
// initialize the error handler for general javascript errors
if ( Aloha.settings.errorhandling ) {
window.onerror = function (msg, url, linenumber) {
Aloha.Log.error(Aloha, 'Error message: ' + msg + '\nURL: ' + url + '\nLine Number: ' + linenumber);
// TODO eventually add a message to the message line?
return true;
};
}
// OS detection
if (navigator.appVersion.indexOf('Win') != -1) {
Aloha.OSName = 'Win';
}
if (navigator.appVersion.indexOf('Mac') != -1) {
Aloha.OSName = 'Mac';
}
if (navigator.appVersion.indexOf('X11') != -1) {
Aloha.OSName = 'Unix';
}
if (navigator.appVersion.indexOf('Linux') != -1) {
Aloha.OSName = 'Linux';
}
try {
// this will disable browsers image resizing facilities
// disable resize handles
var supported;
try {
supported = document.queryCommandSupported( 'enableObjectResizing' );
} catch ( e ) {
supported = false;
Aloha.Log.log( 'enableObjectResizing is not supported.' );
}
if ( supported ) {
document.execCommand( 'enableObjectResizing', false, false);
Aloha.Log.log( 'enableObjectResizing disabled.' );
}
} catch (e) {
Aloha.Log.error( e, 'Could not disable enableObjectResizing' );
// this is just for others, who will not support disabling enableObjectResizing
}
// Forward
next();
},
/**
* Loads plugins Aloha
* @return void
*/
initPlugins: function (next) {
PluginManager.init(function(){
next();
}, this.getLoadedPlugins() );
},
/**
* Loads GUI components
* @return void
*/
initGui: function (next) {
Aloha.RepositoryManager.init();
// activate registered editables
for (var i = 0, editablesLength = Aloha.editables.length; i < editablesLength; i++) {
if ( !Aloha.editables[i].ready ) {
Aloha.editables[i].init();
}
}
// Forward
next();
},
/**
* Activates editable and deactivates all other Editables
* @param {Editable} editable the Editable to be activated
* @return void
*/
activateEditable: function (editable) {
// blur all editables, which are currently active
for (var i = 0, editablesLength = Aloha.editables.length; i < editablesLength; i++) {
if (Aloha.editables[i] != editable && Aloha.editables[i].isActive) {
Aloha.editables[i].blur();
}
}
Aloha.activeEditable = editable;
},
/**
* Returns the current Editable
* @return {Editable} returns the active Editable
*/
getActiveEditable: function() {
return Aloha.activeEditable;
},
/**
* deactivated the current Editable
* @return void
*/
deactivateEditable: function () {
if ( typeof Aloha.activeEditable === 'undefined' || Aloha.activeEditable === null ) {
return;
}
// blur the editable
Aloha.activeEditable.blur();
Aloha.activeEditable = null;
},
/**
* Gets an editable by an ID or null if no Editable with that ID registered.
* @param {string} id the element id to look for.
* @return {Aloha.Editable} editable
*/
getEditableById: function (id) {
// if the element is a textarea than route to the editable div
if (jQuery('#'+id).get(0).nodeName.toLowerCase() === 'textarea' ) {
id = id + '-aloha';
}
// serach all editables for id
for (var i = 0, editablesLength = Aloha.editables.length; i < editablesLength; i++) {
if (Aloha.editables[i].getId() == id) {
return Aloha.editables[i];
}
}
return null;
},
/**
* Checks wheater an object is a registered Aloha Editable.
* @param {jQuery} obj the jQuery object to be checked.
* @return {boolean}
*/
isEditable: function (obj) {
for (var i=0, editablesLength = Aloha.editables.length; i < editablesLength; i++) {
if ( Aloha.editables[i].originalObj.get(0) === obj ) {
return true;
}
}
return false;
},
/**
* Logs a message to the console
* @param level Level of the log ("error", "warn" or "info", "debug")
* @param component Component that calls the log
* @param message log message
* @return void
* @hide
*/
log: function(level, component, message) {
if (typeof Aloha.Log !== "undefined")
Aloha.Log.log(level, component, message);
},
/**
* Register the given editable
* @param editable editable to register
* @return void
* @hide
*/
registerEditable: function (editable) {
Aloha.editables.push(editable);
},
/**
* Unregister the given editable. It will be deactivated and removed from editables.
* @param editable editable to unregister
* @return void
* @hide
*/
unregisterEditable: function (editable) {
// Find the index
var id = Aloha.editables.indexOf( editable );
// Remove it if really found!
if (id != -1) {
Aloha.editables.splice(id, 1);
}
},
/**
* String representation
* @hide
*/
toString: function () {
return 'Aloha';
},
/**
* Check whether at least one editable was modified
* @method
* @return {boolean} true when at least one editable was modified, false if not
*/
isModified: function () {
// check if something needs top be saved
for (var i = 0; i < Aloha.editables.length; i++) {
if (Aloha.editables[i].isModified && Aloha.editables[i].isModified()) {
return true;
}
}
return false;
},
/**
* Determines the Aloha Url
* @method
* @return {String} alohaUrl
*/
getAlohaUrl: function( suffix ) {
// aloha base path is defined by a script tag with 2 data attributes
var requireJs = jQuery('[data-aloha-plugins]'),
baseUrl = ( requireJs.length ) ? requireJs[0].src.replace( /\/?aloha.js$/ , '' ) : '';
return baseUrl;
},
/**
* Gets the Plugin Url
* @method
* @param {String} name
* @return {String} url
*/
getPluginUrl: function (name) {
var url;
if (name) {
url = pluginPaths[name];
if(url) {
//Check if url is absolute and attach base url if it is not
if(!url.match("^(\/|http[s]?:).*")) {
url = Aloha.getAlohaUrl() + '/' + url;
}
}
}
return url;
}
});
return Aloha;
});

View File

@ -1,194 +0,0 @@
//Add ECMA262-5 method binding if not supported natively
//
if (!('bind' in Function.prototype)) {
Function.prototype.bind= function(owner) {
var that= this;
if (arguments.length<=1) {
return function() {
return that.apply(owner, arguments);
};
} else {
var args= Array.prototype.slice.call(arguments, 1);
return function() {
return that.apply(owner, arguments.length===0? args : args.concat(Array.prototype.slice.call(arguments)));
};
}
};
}
// Add ECMA262-5 string trim if not supported natively
//
if (!('trim' in String.prototype)) {
String.prototype.trim= function() {
return this.replace(/^\s+/, '').replace(/\s+$/, '');
};
}
// Add ECMA262-5 Array methods if not supported natively
//
if (!('indexOf' in Array.prototype)) {
Array.prototype.indexOf= function(find, i /*opt*/) {
if (i===undefined) i= 0;
if (i<0) i+= this.length;
if (i<0) i= 0;
for (var n= this.length; i<n; i++)
if (i in this && this[i]===find)
return i;
return -1;
};
}
if (!('lastIndexOf' in Array.prototype)) {
Array.prototype.lastIndexOf= function(find, i /*opt*/) {
if (i===undefined) i= this.length-1;
if (i<0) i+= this.length;
if (i>this.length-1) i= this.length-1;
for (i++; i-->0;) /* i++ because from-argument is sadly inclusive */
if (i in this && this[i]===find)
return i;
return -1;
};
}
if (!('forEach' in Array.prototype)) {
Array.prototype.forEach= function(action, that /*opt*/) {
for (var i= 0, n= this.length; i<n; i++)
if (i in this)
action.call(that, this[i], i, this);
};
}
if (!('map' in Array.prototype)) {
Array.prototype.map= function(mapper, that /*opt*/) {
var other= new Array(this.length);
for (var i= 0, n= this.length; i<n; i++)
if (i in this)
other[i]= mapper.call(that, this[i], i, this);
return other;
};
}
if (!('filter' in Array.prototype)) {
Array.prototype.filter= function(filter, that /*opt*/) {
var other= [], v;
for (var i=0, n= this.length; i<n; i++)
if (i in this && filter.call(that, v= this[i], i, this))
other.push(v);
return other;
};
}
if (!('every' in Array.prototype)) {
Array.prototype.every= function(tester, that /*opt*/) {
for (var i= 0, n= this.length; i<n; i++)
if (i in this && !tester.call(that, this[i], i, this))
return false;
return true;
};
}
if (!('some' in Array.prototype)) {
Array.prototype.some= function(tester, that /*opt*/) {
for (var i= 0, n= this.length; i<n; i++)
if (i in this && tester.call(that, this[i], i, this))
return true;
return false;
};
}
if (!Node) {
// http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-1841493061
var Node = {
'ELEMENT_NODE' : 1,
'ATTRIBUTE_NODE': 2,
'TEXT_NODE': 3,
'CDATA_SECTION_NODE': 4,
'ENTITY_REFERENCE_NODE': 5,
'ENTITY_NODE': 6,
'PROCESSING_INSTRUCTION_NODE': 7,
'COMMENT_NODE': 8,
'DOCUMENT_NODE': 9,
'DOCUMENT_TYPE_NODE': 10,
'DOCUMENT_FRAGMENT_NODE': 11,
'NOTATION_NODE': 12,
//The two nodes are disconnected. Order between disconnected nodes is always implementation-specific.
'DOCUMENT_POSITION_DISCONNECTED': 0x01,
//The second node precedes the reference node.
'DOCUMENT_POSITION_PRECEDING': 0x02,
//The node follows the reference node.
'DOCUMENT_POSITION_FOLLOWING': 0x04,
//The node contains the reference node. A node which contains is always preceding, too.
'DOCUMENT_POSITION_CONTAINS': 0x08,
//The node is contained by the reference node. A node which is contained is always following, too.
'DOCUMENT_POSITION_CONTAINED_BY': 0x10,
//The determination of preceding versus following is implementation-specific.
'DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC': 0x20
};
}
// http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-compareDocumentPosition
// FIXME: Check if the DOMNode prototype can be set.
window.compareDocumentPosition = function(node1, node2) {
if ('compareDocumentPosition' in document.documentElement ) {
return node1.compareDocumentPosition(node2);
}
if (!("contains" in document.documentElement)) {
throw 'compareDocumentPosition nor contains is not supported by this browser.';
}
if (node1 == node2) return 0;
//if they don't have the same parent, there's a disconnect
if (getRootParent(node1) != getRootParent(node2)) return 1;
//use this if both nodes have a sourceIndex (text nodes don't)
if ("sourceIndex" in node1 && "sourceIndex" in node2) {
return comparePosition(node1, node2);
}
//document will definitely contain the other node
if (node1 == document) return 20;
else if (node2 == document) return 10;
//get sourceIndexes to use for both nodes
var useNode1 = getUseNode(node1), useNode2 = getUseNode(node2);
//call this function again to get the result
var result = comparePosition(useNode1, useNode2);
//clean up if needed
if (node1 != useNode1) useNode1.parentNode.removeChild(useNode1);
if (node2 != useNode2) useNode2.parentNode.removeChild(useNode2);
return result;
//node.ownerDocument gives the document object, which isn't the right info for a disconnect
function getRootParent(node) {
do { var parent = node; }
while (node = node.parentNode);
return parent;
}
//Compare Position - MIT Licensed, John Resig; http://ejohn.org/blog/comparing-document-position/
//Already checked for equality and disconnect
function comparePosition(node1, node2) {
return (node1.contains(node2) && 16) +
(node2.contains(node1) && 8) +
(node1.sourceIndex >= 0 && node2.sourceIndex >= 0 ?
(node1.sourceIndex < node2.sourceIndex && 4) +
(node1.sourceIndex > node2.sourceIndex && 2) :
1);
}
//get a node with a sourceIndex to use
function getUseNode(node) {
//if the node already has a sourceIndex, use that node
if ("sourceIndex" in node) return node;
//otherwise, insert a comment (which has a sourceIndex but minimal DOM impact) before the node and use that
return node.parentNode.insertBefore(document.createComment(""), node);
}
};
if (!('getComputedStyle' in window)) {
window.getComputedStyle = function (node, style) {
if( node.currentStyle ) {
return node.currentStyle;
}
return null;
}
}

View File

@ -1,280 +0,0 @@
define([],
function(){
var shims = {
// Function bind
bind: function(owner){
var obj = this.obj || this;
var native_method = Function.prototype.bind;
var args= Array.prototype.slice.call(arguments, 1);
if(native_method){
return native_method.apply(obj, arguments);
}
else{
return function() {
return obj.apply(owner, arguments.length===0? args : args.concat(Array.prototype.slice.call(arguments)));
}
}
},
// String trim
trim: function(){
var obj = this.obj || this;
var native_method = String.prototype.trim;
if(native_method){
return native_method.call(obj);
}
else {
return obj.replace(/^\s+/, '').replace(/\s+$/, '');
}
},
// Array methods
indexOf: function(find, i /*opt*/){
var obj = this.obj || this;
var native_method = Array.prototype.indexOf;
if(native_method){
return native_method.call(obj, find, i);
}
else {
if (i===undefined) i= 0;
if (i<0) i+= obj.length;
if (i<0) i= 0;
for (var n = obj.length; i<n; i++)
if (i in obj && obj[i]===find)
return i;
return -1;
}
},
forEach: function(action, that /*opt*/){
var obj = this.obj || this;
var native_method = Array.prototype.forEach;
if(native_method){
return native_method.call(obj, action, that);
}
else {
for (var i= 0, n = obj.length; i<n; i++)
if (i in obj)
action.call(that, obj[i], i, obj);
}
},
map: function(mapper, that /*opt*/, chain /*opt */){
var obj = this.obj || this;
var native_method = Array.prototype.map;
var returnWrapper = (typeof arguments[arguments.length - 1] == "boolean") ? Array.prototype.pop.call(arguments) : false;
var result = [];
if(native_method){
result = native_method.call(obj, mapper, that);
}
else {
var other= new Array(obj.length);
for (var i= 0, n= obj.length; i<n; i++)
if (i in obj)
other[i]= mapper.call(that, obj[i], i, obj);
result = other;
}
return returnWrapper ? $_(result) : result;
},
filter: function(filterFunc, that /*opt*/, chain /*opt */){
var obj = this.obj || this;
var native_method = Array.prototype.filter;
var returnWrapper = (typeof arguments[arguments.length - 1] == "boolean") ? Array.prototype.pop.call(arguments) : false;
var result = [];
if(native_method){
result = native_method.call(obj, filterFunc, that);
}
else {
var other= [], v;
for (var i=0, n= obj.length; i<n; i++)
if (i in obj && filterFunc.call(that, v= obj[i], i, obj))
other.push(v);
result = other;
}
return returnWrapper ? $_(result) : result;
},
every: function(tester, that /*opt*/) {
var obj = this.obj || this;
var native_method = Array.prototype.every;
if(native_method){
return native_method.call(obj, tester, that);
}
else {
for (var i= 0, n= obj.length; i<n; i++)
if (i in obj && !tester.call(that, obj[i], i, obj))
return false;
return true;
}
},
some: function(tester, that /*opt*/){
var obj = this.obj || this;
var native_method = Array.prototype.some;
if(native_method){
return native_method.call(obj, tester, that);
}
else {
for (var i= 0, n= obj.length; i<n; i++)
if (i in obj && tester.call(that, obj[i], i, obj))
return true;
return false;
}
},
// Since IE7 doesn't support 'hasAttribute' method on nodes
// TODO: raise an exception if the object is not an node
hasAttribute: function(attr){
var obj = this.obj || this;
var native_method = obj.hasAttribute;
if(native_method){
return obj.hasAttribute(attr);
}
else {
return (typeof obj.attributes[attr] != "undefined")
}
}
};
var $_ = function(obj) {
var wrapper = function() {};
wrapper.prototype = shims;
var wrapper_instance = new wrapper();
wrapper_instance.obj = obj;
return wrapper_instance;
};
for (var shim in shims) {
$_[shim] = shims[shim];
}
// Node constants
// http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-1841493061
if(typeof Node != 'undefined'){
$_.Node = Node;
}
else {
$_.Node = {
'ELEMENT_NODE' : 1,
'ATTRIBUTE_NODE': 2,
'TEXT_NODE': 3,
'CDATA_SECTION_NODE': 4,
'ENTITY_REFERENCE_NODE': 5,
'ENTITY_NODE': 6,
'PROCESSING_INSTRUCTION_NODE': 7,
'COMMENT_NODE': 8,
'DOCUMENT_NODE': 9,
'DOCUMENT_TYPE_NODE': 10,
'DOCUMENT_FRAGMENT_NODE': 11,
'NOTATION_NODE': 12,
//The two nodes are disconnected. Order between disconnected nodes is always implementation-specific.
'DOCUMENT_POSITION_DISCONNECTED': 0x01,
//The second node precedes the reference node.
'DOCUMENT_POSITION_PRECEDING': 0x02,
//The node follows the reference node.
'DOCUMENT_POSITION_FOLLOWING': 0x04,
//The node contains the reference node. A node which contains is always preceding, too.
'DOCUMENT_POSITION_CONTAINS': 0x08,
//The node is contained by the reference node. A node which is contained is always following, too.
'DOCUMENT_POSITION_CONTAINED_BY': 0x10,
//The determination of preceding versus following is implementation-specific.
'DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC': 0x20
}
};
// http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-compareDocumentPosition
// FIXME: Check if the DOMNode prototype can be set.
$_.compareDocumentPosition = function(node1, node2) {
if ('compareDocumentPosition' in document.documentElement ) {
return node1.compareDocumentPosition(node2);
}
if (!("contains" in document.documentElement)) {
throw 'compareDocumentPosition nor contains is not supported by this browser.';
}
if (node1 == node2) return 0;
//if they don't have the same parent, there's a disconnect
if (getRootParent(node1) != getRootParent(node2)) return 1;
//use this if both nodes have a sourceIndex (text nodes don't)
if ("sourceIndex" in node1 && "sourceIndex" in node2) {
return comparePosition(node1, node2);
}
//document will definitely contain the other node
if (node1 == document) return 20;
else if (node2 == document) return 10;
//get sourceIndexes to use for both nodes
var useNode1 = getUseNode(node1), useNode2 = getUseNode(node2);
//call this function again to get the result
var result = comparePosition(useNode1, useNode2);
//clean up if needed
if (node1 != useNode1) useNode1.parentNode.removeChild(useNode1);
if (node2 != useNode2) useNode2.parentNode.removeChild(useNode2);
return result;
//node.ownerDocument gives the document object, which isn't the right info for a disconnect
function getRootParent(node) {
do { var parent = node; }
while (node = node.parentNode);
return parent;
}
//Compare Position - MIT Licensed, John Resig; http://ejohn.org/blog/comparing-document-position/
//Already checked for equality and disconnect
function comparePosition(node1, node2) {
return (node1.contains(node2) && 16) +
(node2.contains(node1) && 8) +
(node1.sourceIndex >= 0 && node2.sourceIndex >= 0 ?
(node1.sourceIndex < node2.sourceIndex && 4) +
(node1.sourceIndex > node2.sourceIndex && 2) :
1);
}
//get a node with a sourceIndex to use
function getUseNode(node) {
//if the node already has a sourceIndex, use that node
if ("sourceIndex" in node) return node;
//otherwise, insert a comment (which has a sourceIndex but minimal DOM impact) before the node and use that
return node.parentNode.insertBefore(document.createComment(""), node);
}
};
$_.getComputedStyle = function(node, style){
if('getComputedStyle' in window) {
return window.getComputedStyle(node, style);
}
else {
if( node.currentStyle ) {
return node.currentStyle;
}
return null;
}
};
return $_;
});

View File

@ -1,878 +0,0 @@
/*!
* This file is part of Aloha Editor Project http://aloha-editor.org
* Copyright © 2010-2011 Gentics Software GmbH, aloha@gentics.com
* Contributors http://aloha-editor.org/contribution.php
* Licensed unter the terms of http://www.aloha-editor.org/license.html
*
* Aloha Editor is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* ( at your option ) any later version.*
*
* Aloha Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define( [
'aloha/core',
'util/class',
'aloha/jquery',
'aloha/pluginmanager',
'aloha/floatingmenu',
'aloha/selection',
'aloha/markup',
'aloha/contenthandlermanager',
'aloha/console'
], function( Aloha, Class, jQuery, PluginManager, FloatingMenu, Selection,
Markup, ContentHandlerManager, console ) {
var unescape = window.unescape,
GENTICS = window.GENTICS,
// True, if the next editable activate event should not be handled
ignoreNextActivateEvent = false;
// default supported and custom content handler settings
// @TODO move to new config when implemented in Aloha
Aloha.defaults.contentHandler = {};
Aloha.defaults.contentHandler.initEditable = [ 'sanitize' ];
Aloha.defaults.contentHandler.getContents = [ 'sanitize' ];
// The insertHtml contenthandler ( paste ) will, by default, use all
// registered content handlers.
//Aloha.defaults.contentHandler.insertHtml = void 0;
if ( typeof Aloha.settings.contentHandler === 'undefined' ) {
Aloha.settings.contentHandler = {};
}
var defaultContentSerializer = function(editableElement){
return jQuery(editableElement).html();
};
var contentSerializer = defaultContentSerializer;
/**
* Editable object
* @namespace Aloha
* @class Editable
* @method
* @constructor
* @param {Object} obj jQuery object reference to the object
*/
Aloha.Editable = Class.extend( {
_constructor: function( obj ) {
// check wheter the object has an ID otherwise generate and set
// globally unique ID
if ( !obj.attr( 'id' ) ) {
obj.attr( 'id', GENTICS.Utils.guid() );
}
// store object reference
this.obj = obj;
this.originalObj = obj;
this.ready = false;
// delimiters, timer and idle for smartContentChange
// smartContentChange triggers -- tab: '\u0009' - space: '\u0020' - enter: 'Enter'
this.sccDelimiters = [ ':', ';', '.', '!', '?', ',',
unescape( '%u0009' ), unescape( '%u0020' ), 'Enter' ];
this.sccIdle = 5000;
this.sccDelay = 500;
this.sccTimerIdle = false;
this.sccTimerDelay = false;
// see keyset http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-20071221/keyset.html
this.keyCodeMap = {
93 : "Apps", // The Application key
18 : "Alt", // The Alt ( Menu ) key.
20 : "CapsLock", // The Caps Lock ( Capital ) key.
17 : "Control", // The Control ( Ctrl ) key.
40 : "Down", // The Down Arrow key.
35 : "End", // The End key.
13 : "Enter", // The Enter key.
112 : "F1", // The F1 key.
113 : "F2", // The F2 key.
114 : "F3", // The F3 key.
115 : "F4", // The F4 key.
116 : "F5", // The F5 key.
117 : "F6", // The F6 key.
118 : "F7", // The F7 key.
119 : "F8", // The F8 key.
120 : "F9", // The F9 key.
121 : "F10", // The F10 key.
122 : "F11", // The F11 key.
123 : "F12", // The F12 key.
// Anybody knows the keycode for F13-F24?
36 : "Home", // The Home key.
45 : "Insert", // The Insert ( Ins ) key.
37 : "Left", // The Left Arrow key.
224 : "Meta", // The Meta key.
34 : "PageDown", // The Page Down ( Next ) key.
33 : "PageUp", // The Page Up key.
19 : "Pause", // The Pause key.
44 : "PrintScreen", // The Print Screen ( PrintScrn, SnapShot ) key.
39 : "Right", // The Right Arrow key.
145 : "Scroll", // The scroll lock key
16 : "Shift", // The Shift key.
38 : "Up", // The Up Arrow key.
91 : "Win", // The left Windows Logo key.
92 : "Win" // The right Windows Logo key.
};
this.placeholderClass = 'aloha-placeholder';
Aloha.registerEditable( this );
this.init();
},
/**
* Initialize the editable
* @return void
* @hide
*/
init: function() {
var me = this;
// TODO make editables their own settings.
this.settings = Aloha.settings;
// smartContentChange settings
// @TODO move to new config when implemented in Aloha
if ( Aloha.settings && Aloha.settings.smartContentChange ) {
if ( Aloha.settings.smartContentChange.delimiters ) {
this.sccDelimiters = Aloha.settings.smartContentChange.delimiters;
} /* else {
this.sccDelimiters = this.sccDelimiters;
} */
if ( Aloha.settings.smartContentChange.idle ) {
this.sccIdle = Aloha.settings.smartContentChange.idle;
} /* else {
this.sccIdle = this.sccIdle;
} */
if ( Aloha.settings.smartContentChange.delay ) {
this.sccDelay = Aloha.settings.smartContentChange.delay;
} /* else {
this.sccDelay = this.sccDelay;
} */
}
// check if Aloha can handle the obj as Editable
if ( !this.check( this.obj ) ) {
//Aloha.log( 'warn', this, 'Aloha cannot handle {' + this.obj[0].nodeName + '}' );
this.destroy();
return;
}
// apply content handler to clean up content
var content = me.obj.html();
if ( typeof Aloha.settings.contentHandler.initEditable === 'undefined' ) {
Aloha.settings.contentHandler.initEditable = Aloha.defaults.contentHandler.initEditable;
}
content = ContentHandlerManager.handleContent( content, {
contenthandler: Aloha.settings.contentHandler.initEditable
} );
me.obj.html( content );
// only initialize the editable when Aloha is fully ready ( including plugins )
Aloha.bind( 'aloha-ready', function() {
// initialize the object
me.obj.addClass( 'aloha-editable' ).contentEditable( true );
// add focus event to the object to activate
me.obj.mousedown( function( e ) {
// check whether the mousedown was already handled
if ( !Aloha.eventHandled ) {
Aloha.eventHandled = true;
return me.activate( e );
}
} );
me.obj.mouseup( function( e ) {
Aloha.eventHandled = false;
} );
me.obj.focus( function( e ) {
return me.activate( e );
} );
// by catching the keydown we can prevent the browser from doing its own thing
// if it does not handle the keyStroke it returns true and therefore all other
// events ( incl. browser's ) continue
me.obj.keydown( function( event ) {
me.keyCode = event.which;
return Markup.preProcessKeyStrokes( event );
} );
// handle keypress
me.obj.keypress( function( event ) {
// triggers a smartContentChange to get the right charcode
// To test try http://www.w3.org/2002/09/tests/keys.html
Aloha.activeEditable.smartContentChange( event );
} );
// handle shortcut keys
me.obj.keyup( function( event ) {
if ( event.keyCode === 27 ) {
Aloha.deactivateEditable();
return false;
}
} );
// register the onSelectionChange Event with the Editable field
me.obj.contentEditableSelectionChange( function( event ) {
Selection.onChange( me.obj, event );
return me.obj;
} );
// mark the editable as unmodified
me.setUnmodified();
// we don't do the sanitizing on aloha ready, since some plugins add elements into the content and bind events to it.
// if we sanitize by replacing the html, all events would get lost. TODO: think about a better solution for the sanitizing, without
// destroying the events
// // apply content handler to clean up content
// var content = me.obj.html();
// if ( typeof Aloha.settings.contentHandler.initEditable === 'undefined' ) {
// Aloha.settings.contentHandler.initEditable = Aloha.defaults.contentHandler.initEditable;
// }
// content = ContentHandlerManager.handleContent( content, {
// contenthandler: Aloha.settings.contentHandler.initEditable
// } );
// me.obj.html( content );
me.snapshotContent = me.getContents();
// FF bug: check for empty editable contents ( no <br>; no whitespace )
if ( jQuery.browser.mozilla ) {
me.initEmptyEditable();
}
me.initPlaceholder();
me.ready = true;
// throw a new event when the editable has been created
/**
* @event editableCreated fires after a new editable has been created, eg. via $( '#editme' ).aloha()
* The event is triggered in Aloha's global scope Aloha
* @param {Event} e the event object
* @param {Array} a an array which contains a reference to the currently created editable on its first position
*/
Aloha.trigger( 'aloha-editable-created', [ me ] );
} );
},
/**
* True, if this editable is active for editing
* @property
* @type boolean
*/
isActive: false,
/**
* stores the original content to determine if it has been modified
* @hide
*/
originalContent: null,
/**
* every time a selection is made in the current editable the selection has to
* be saved for further use
* @hide
*/
range: undefined,
/**
* Check if object can be edited by Aloha Editor
* @return {boolean } editable true if Aloha Editor can handle else false
* @hide
*/
check: function() {
/* TODO check those elements
'map', 'meter', 'object', 'output', 'progress', 'samp',
'time', 'area', 'datalist', 'figure', 'kbd', 'keygen',
'mark', 'math', 'wbr', 'area',
*/
// Extract El
var me = this,
obj = this.obj,
el = obj.get( 0 ),
nodeName = el.nodeName.toLowerCase(),
// supported elements
textElements = [ 'a', 'abbr', 'address', 'article', 'aside',
'b', 'bdo', 'blockquote', 'cite', 'code', 'command',
'del', 'details', 'dfn', 'div', 'dl', 'em', 'footer',
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'i',
'ins', 'menu', 'nav', 'p', 'pre', 'q', 'ruby',
'section', 'small', 'span', 'strong', 'sub', 'sup',
'var' ],
i, div;
for ( i = 0; i < textElements.length; i++ ) {
if ( nodeName === textElements[ i ] ) {
return true;
}
}
// special handled elements
switch ( nodeName ) {
case 'label':
case 'button':
// TODO need some special handling.
break;
case 'textarea':
// Create a div alongside the textarea
div = jQuery( '<div id="' + this.getId() +
'-aloha" class="aloha-textarea" />' )
.insertAfter( obj );
// Resize the div to the textarea and
// Populate the div with the value of the textarea
// Then, hide the textarea
div.height( obj.height() )
.width( obj.width() )
.html( obj.val() );
obj.hide();
// Attach a onsubmit to the form to place the HTML of the
// div back into the textarea
obj.parents( 'form:first' ).submit( function() {
obj.val( me.getContents() );
} );
// Swap textarea reference with the new div
this.obj = div;
// Supported
return true;
default:
break;
}
// the following elements are not supported
/*
'canvas', 'audio', 'br', 'embed', 'fieldset', 'hgroup', 'hr',
'iframe', 'img', 'input', 'map', 'script', 'select', 'style',
'svg', 'table', 'ul', 'video', 'ol', 'form', 'noscript',
*/
return false;
},
/**
* Init Placeholder
*
* @return void
*/
initPlaceholder: function() {
if ( Aloha.settings.placeholder && this.isEmpty() ) {
this.addPlaceholder();
}
},
/**
* Check if the conteneditable is empty.
*
* @return {Boolean}
*/
isEmpty: function() {
var editableTrimedContent = jQuery.trim( this.getContents() ),
onlyBrTag = ( editableTrimedContent === '<br>' ) ? true : false;
return ( editableTrimedContent.length === 0 || onlyBrTag );
},
/**
* Check if the editable div is not empty. Fixes a FF browser bug
* see issue: https://github.com/alohaeditor/Aloha-Editor/issues/269
*
* @return {undefined}
*/
initEmptyEditable: function( ) {
var obj = this.obj;
if ( this.empty( this.getContents() ) ) {
jQuery( obj ).prepend( '<br class="aloha-cleanme" />' );
}
},
/**
* Add placeholder in editable
*
* @return void
*/
addPlaceholder: function() {
var div = jQuery( '<div>' ),
span = jQuery( '<span>' ),
el,
obj = this.obj;
if ( GENTICS.Utils.Dom.allowsNesting( obj[0], div[0] ) ) {
el = div;
} else {
el = span;
}
jQuery( obj ).append( el.addClass( this.placeholderClass ) );
jQuery.each(
Aloha.settings.placeholder,
function( selector, selectorConfig ) {
if ( obj.is( selector ) ) {
el.html( selectorConfig );
}
}
);
// remove browser br
jQuery( 'br', obj ).remove();
// delete div, span, el;
},
/**
* remove placeholder from contenteditable. If setCursor is true,
* will also set the cursor to the start of the selection. However,
* this will be ASYNCHRONOUS, so if you rely on the fact that
* the placeholder is removed after calling this method, setCursor
* should be false ( or not set )
*
* @return void
*/
removePlaceholder: function( obj, setCursor ) {
var placeholderClass = this.placeholderClass,
range;
// // remove browser br
// jQuery( 'br', obj ).remove();
// set the cursor // remove placeholder
if ( setCursor === true ) {
range = Selection.getRangeObject();
if ( !range.select ) {
return;
}
range.startContainer = range.endContainer = obj.get( 0 );
range.startOffset = range.endOffset = 0;
range.select();
window.setTimeout( function() {
jQuery( '.' + placeholderClass, obj ).remove();
}, 20 );
} else {
jQuery( '.' + placeholderClass, obj ).remove();
}
},
/**
* destroy the editable
* @return void
*/
destroy: function() {
// leave the element just to get sure
if ( this === Aloha.getActiveEditable() ) {
this.blur();
// also hide the floating menu if the current editable was active
FloatingMenu.hide();
}
// special handled elements
switch ( this.originalObj.get( 0 ).nodeName.toLowerCase() ) {
case 'label':
case 'button':
// TODO need some special handling.
break;
case 'textarea':
// restore content to original textarea
this.originalObj.val( this.getContents() );
this.obj.remove();
this.originalObj.show();
break;
default:
break;
}
// now the editable is not ready any more
this.ready = false;
// remove the placeholder if needed.
this.removePlaceholder( this.obj );
// initialize the object and disable contentEditable
// unbind all events
// TODO should only unbind the specific handlers.
this.obj.removeClass( 'aloha-editable' )
.contentEditable( false )
.unbind( 'mousedown click dblclick focus keydown keypress keyup' );
/* TODO remove this event, it should implemented as bind and unbind
// register the onSelectionChange Event with the Editable field
this.obj.contentEditableSelectionChange( function( event ) {
Aloha.Selection.onChange( me.obj, event );
return me.obj;
} );
*/
// throw a new event when the editable has been created
/**
* @event editableCreated fires after a new editable has been destroyes, eg. via $( '#editme' ).mahalo()
* The event is triggered in Aloha's global scope Aloha
* @param {Event} e the event object
* @param {Array} a an array which contains a reference to the currently created editable on its first position
*/
Aloha.trigger( 'aloha-editable-destroyed', [ this ] );
// finally register the editable with Aloha
Aloha.unregisterEditable( this );
},
/**
* marks the editables current state as unmodified. Use this method to inform the editable
* that it's contents have been saved
* @method
*/
setUnmodified: function() {
this.originalContent = this.getContents();
},
/**
* check if the editable has been modified during the edit process#
* @method
* @return boolean true if the editable has been modified, false otherwise
*/
isModified: function() {
return this.originalContent !== this.getContents();
},
/**
* String representation of the object
* @method
* @return Aloha.Editable
*/
toString: function() {
return 'Aloha.Editable';
},
/**
* check whether the editable has been disabled
*/
isDisabled: function() {
return !this.obj.contentEditable()
|| this.obj.contentEditable() === 'false';
},
/**
* disable this editable
* a disabled editable cannot be written on by keyboard
*/
disable: function() {
return this.isDisabled() || this.obj.contentEditable( false );
},
/**
* enable this editable
* reenables a disabled editable to be writteable again
*/
enable: function() {
return this.isDisabled() && this.obj.contentEditable( true );
},
/**
* activates an Editable for editing
* disables all other active items
* @method
*/
activate: function( e ) {
// get active Editable before setting the new one.
var oldActive = Aloha.getActiveEditable();
// We need to ommit this call when this flag is set to true.
// This flag will only be set to true before the removePlaceholder method
// is called since that method invokes a focus event which will again trigger
// this method. We want to avoid double invokation of this method.
if ( ignoreNextActivateEvent ) {
ignoreNextActivateEvent = false;
return;
}
// handle special case in which a nested editable is focused by a click
// in this case the "focus" event would be triggered on the parent element
// which actually shifts the focus away to it's parent. this if is here to
// prevent this situation
if ( e && e.type === 'focus' && oldActive !== null
&& oldActive.obj.parent().get( 0 ) === e.currentTarget ) {
return;
}
// leave immediately if this is already the active editable
if ( this.isActive || this.isDisabled() ) {
// we don't want parent editables to be triggered as well, so return false
return;
}
this.obj.addClass( 'aloha-editable-active' );
Aloha.activateEditable( this );
ignoreNextActivateEvent = true;
this.removePlaceholder ( this.obj, true );
ignoreNextActivateEvent = false;
this.isActive = true;
/**
* @event editableActivated fires after the editable has been activated by clicking on it.
* This event is triggered in Aloha's global scope Aloha
* @param {Event} e the event object
* @param {Array} a an array which contains a reference to last active editable on its first position, as well
* as the currently active editable on it's second position
*/
// trigger a 'general' editableActivated event
Aloha.trigger( 'aloha-editable-activated', {
'oldActive' : oldActive,
'editable' : this
} );
},
/**
* handle the blur event
* this must not be attached to the blur event, which will trigger far too often
* eg. when a table within an editable is selected
* @hide
*/
blur: function() {
this.obj.blur();
this.isActive = false;
this.initPlaceholder();
this.obj.removeClass( 'aloha-editable-active' );
/**
* @event editableDeactivated fires after the editable has been activated by clicking on it.
* This event is triggered in Aloha's global scope Aloha
* @param {Event} e the event object
* @param {Array} a an array which contains a reference to this editable
*/
Aloha.trigger( 'aloha-editable-deactivated', { editable : this } );
/**
* @event smartContentChanged
*/
Aloha.activeEditable.smartContentChange( { type : 'blur' }, null );
},
/**
* check if the string is empty
* used for zerowidth check
* @return true if empty or string is null, false otherwise
* @hide
*/
empty: function( str ) {
// br is needed for chrome
return ( null === str )
|| ( jQuery.trim( str ) === '' || str === '<br/>' );
},
/**
* Get the contents of this editable as a HTML string
* @method
* @return contents of the editable
*/
getContents: function( asObject ) {
var clonedObj = this.obj.clone( false );
// do core cleanup
clonedObj.find( '.aloha-cleanme' ).remove();
this.removePlaceholder( clonedObj );
PluginManager.makeClean( clonedObj );
return asObject ? clonedObj.contents() : contentSerializer(clonedObj[0]);
},
/**
* Get the id of this editable
* @method
* @return id of this editable
*/
getId: function() {
return this.obj.attr( 'id' );
},
/**
* Generates and signals a smartContentChange event.
*
* A smart content change occurs when a special editing action, or a
* combination of interactions are performed by the user during the
* course of editing within an editable.
* The smart content change event would therefore signal to any
* component that is listening to this event, that content has been
* inserted into the editable that may need to be prococessed in a
* special way
* This is used for smart actions within the content/while editing.
* @param {Event} event
* @hide
*/
smartContentChange: function( event ) {
var me = this,
uniChar = null,
re,
match;
// ignore meta keys like crtl+v or crtl+l and so on
if ( event && ( event.metaKey || event.crtlKey || event.altKey ) ) {
return false;
}
if ( event && event.originalEvent ) {
// regex to strip unicode
re = new RegExp( "U\\+(\\w{4})" );
match = re.exec( event.originalEvent.keyIdentifier );
// Use keyIdentifier if available
if ( event.originalEvent.keyIdentifier && 1 === 2 ) {
// @fixme: Because of "&& 1 === 2" above, all the below is
// unreachable code
if ( match !== null ) {
uniChar = unescape( '%u' + match[1] );
}
if ( uniChar === null ) {
uniChar = event.originalEvent.keyIdentifier;
}
// FF & Opera don't support keyIdentifier
} else {
// Use among browsers reliable which http://api.jquery.com/keypress
uniChar = ( this.keyCodeMap[ this.keyCode ] ||
String.fromCharCode( event.which ) || 'unknown' );
}
}
// handle "Enter" -- it's not "U+1234" -- when returned via "event.originalEvent.keyIdentifier"
// reference: http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-20071221/keyset.html
if ( jQuery.inArray( uniChar, this.sccDelimiters ) >= 0 ) {
clearTimeout( this.sccTimerIdle );
clearTimeout( this.sccTimerDelay );
this.sccTimerDelay = setTimeout( function() {
Aloha.trigger( 'aloha-smart-content-changed', {
'editable' : me,
'keyIdentifier' : event.originalEvent.keyIdentifier,
'keyCode' : event.keyCode,
'char' : uniChar,
'triggerType' : 'keypress', // keypress, timer, blur, paste
'snapshotContent' : me.getSnapshotContent()
} );
console.debug( 'Aloha.Editable',
'smartContentChanged: event type keypress triggered' );
/*
var r = Aloha.Selection.rangeObject;
if ( r.isCollapsed()
&& r.startContainer.nodeType == 3 ) {
var posDummy = jQuery( '<span id="GENTICS-Aloha-PosDummy" />' );
GENTICS.Utils.Dom.insertIntoDOM(
posDummy,
r,
this.obj,
null,
false,
false
);
console.log( posDummy.offset().top, posDummy.offset().left );
GENTICS.Utils.Dom.removeFromDOM(
posDummy,
r,
false
);
r.select();
}
*/
}, this.sccDelay );
} else if ( event && event.type === 'paste' ) {
Aloha.trigger( 'aloha-smart-content-changed', {
'editable' : me,
'keyIdentifier' : null,
'keyCode' : null,
'char' : null,
'triggerType' : 'paste',
'snapshotContent' : me.getSnapshotContent()
} );
} else if ( event && event.type === 'blur' ) {
Aloha.trigger( 'aloha-smart-content-changed', {
'editable' : me,
'keyIdentifier' : null,
'keyCode' : null,
'char' : null,
'triggerType' : 'blur',
'snapshotContent' : me.getSnapshotContent()
} );
} else if ( uniChar !== null ) {
// in the rare case idle time is lower then delay time
clearTimeout( this.sccTimerDelay );
clearTimeout( this.sccTimerIdle );
this.sccTimerIdle = setTimeout( function() {
Aloha.trigger( 'aloha-smart-content-changed', {
'editable' : me,
'keyIdentifier' : null,
'keyCode' : null,
'char' : null,
'triggerType' : 'idle',
'snapshotContent' : me.getSnapshotContent()
} );
}, this.sccIdle );
}
},
/**
* Get a snapshot of the active editable as a HTML string
* @hide
* @return snapshot of the editable
*/
getSnapshotContent: function() {
var ret = this.snapshotContent;
this.snapshotContent = this.getContents();
return ret;
}
} );
/**
* Sets the serializer function to be used for the contents of all editables.
*
* The default content serializer will just call the jQuery.html()
* function on the editable element (which gets the innerHTML property).
*
* This method is a static class method and will affect the result
* of editable.getContents() for all editables that have been or
* will be constructed.
*
* @param serializerFunction
* A function that accepts a DOM element and returns the serialized
* XHTML of the element contents (excluding the start and end tag of
* the passed element).
*/
Aloha.Editable.setContentSerializer = function( serializerFunction ) {
contentSerializer = serializerFunction;
};
} );

File diff suppressed because it is too large Load Diff

View File

@ -1,86 +0,0 @@
/*!
* This file is part of Aloha Editor Project http://aloha-editor.org
* Copyright <EFBFBD> 2010-2011 Gentics Software GmbH, aloha@gentics.com
* Contributors http://aloha-editor.org/contribution.php
* Licensed unter the terms of http://www.aloha-editor.org/license.html
*//*
* Aloha Editor is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.*
*
* Aloha Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define( [
'aloha/jquery',
'aloha/ext',
'aloha/repositorymanager',
'aloha/console',
'i18n!aloha/nls/i18n'
], function ( jQuery, Ext, RepositoryManager, console ) {
Ext.data.AlohaProxy = function () {
// Must define a dummy api with "read" action to satisfy
// Ext.data.Api#prepare *before* calling super
var api = {};
api[ Ext.data.Api.actions.read ] = true;
Ext.data.AlohaProxy.superclass.constructor.call( this, { api: api } );
this.params = {
queryString : null,
objectTypeFilter : null,
filter : null,
inFolderId : null,
orderBy : null,
maxItems : null,
skipCount : null,
renditionFilter : null,
repositoryId : null
};
};
var i18n = Aloha.require( 'i18n!aloha/nls/i18n' );
Ext.extend( Ext.data.AlohaProxy, Ext.data.DataProxy, {
doRequest: function ( action, rs, params, reader, cb, scope, arg ) {
jQuery.extend( this.params, params );
try {
RepositoryManager.query( this.params, function ( items ) {
cb.call( scope, reader.readRecords( items ), arg, true );
} );
} catch ( ex ) {
console.error( 'Ext.data.AlohaProxy',
'An error occured while querying repositories.' );
this.fireEvent( 'loadexception', this, null, arg, ex );
this.fireEvent( 'exception', this, 'response', action, arg, null, ex );
return false;
}
},
setObjectTypeFilter: function ( otFilter ) {
this.params.objectTypeFilter = otFilter;
},
getObjectTypeFilter: function () {
return this.params.objectTypeFilter;
},
setParams: function ( p ) {
jQuery.extend( this.params, p );
}
} );
} );

View File

@ -1,50 +0,0 @@
/*!
* This file is part of Aloha Editor Project http://aloha-editor.org
* Copyright <EFBFBD> 2010-2011 Gentics Software GmbH, aloha@gentics.com
* Contributors http://aloha-editor.org/contribution.php
* Licensed unter the terms of http://www.aloha-editor.org/license.html
*//*
* Aloha Editor is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.*
*
* Aloha Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(
['aloha/ext'],
function(Ext) {
Ext.data.AlohaObjectReader = function(meta, recordType) {
meta = {};
Ext.applyIf(meta, {
idProperty: 'id',
root: 'items',
totalProperty: 'results',
// TODO implement all defined optional attributes
fields: [
'id',
'url',
'name',
'type',
'weight',
'path',
'repositoryId'
]
});
Ext.data.JsonReader.superclass.constructor.call(this, meta, meta.fields);
};
Ext.extend(Ext.data.AlohaObjectReader, Ext.data.JsonReader, {
// extend of necessary
});
});

View File

@ -1,77 +0,0 @@
/*!
* This file is part of Aloha Editor Project http://aloha-editor.org
* Copyright (c) 2010-2011 Gentics Software GmbH, aloha@gentics.com
* Contributors http://aloha-editor.org/contribution.php
* Licensed unter the terms of http://www.aloha-editor.org/license.html
*//*
* Aloha Editor is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.*
*
* Aloha Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(
['aloha/ext', 'aloha/repositorymanager'],
function(Ext, RepositoryManager) {
Ext.tree.AlohaTreeLoader = function(config) {
Ext.apply(this, config);
Ext.tree.AlohaTreeLoader.superclass.constructor.call(this);
};
Ext.extend( Ext.tree.AlohaTreeLoader, Ext.tree.TreeLoader, {
paramOrder: ['node', 'id'],
nodeParameter: 'id',
directFn : function(node, id, callback) {
var
params = {
inFolderId: node.id,
objectTypeFilter: this.objectTypeFilter,
repositoryId: node.repositoryId
};
RepositoryManager.getChildren ( params, function( items ) {
var response = {};
response = {
status: true,
scope: this,
argument: {callback: callback, node: node}
};
if(typeof callback === 'function'){
callback(items, response);
}
});
},
createNode: function(node) {
if ( node.name ) {
node.text = node.name;
}
if ( node.hasMoreItems ) {
node.leaf = !node.hasMoreItems;
}
if ( node.objectType ) {
node.cls = node.objectType;
}
return Ext.tree.TreeLoader.prototype.createNode.call(this, node);
},
objectTypeFilter : null,
setObjectTypeFilter : function (otFilter) {
this.objectTypeFilter = otFilter;
},
getObjectTypeFilter : function () {
return this.objectTypeFilter;
}
});
});

View File

@ -1,32 +0,0 @@
/*!
* This file is part of Aloha Editor Project http://aloha-editor.org
* Copyright (c) 2010-2011 Gentics Software GmbH, aloha@gentics.com
* Contributors http://aloha-editor.org/contribution.php
* Licensed unter the terms of http://www.aloha-editor.org/license.html
*//*
* Aloha Editor is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.*
*
* Aloha Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define('aloha/ext',[], function() {
// Ext seems to have an onClick handler that uses
// QuickTips, but the handler doesn't initialize
// QuickTips and therefore causes an error.
// The bug occurred with the Gentics Content Node
// integration, but if it's really a bug in Ext, then
// it's a good idea to always initialize QuickTips here.
Ext.QuickTips.init();
return Ext;
});

File diff suppressed because it is too large Load Diff

View File

@ -1,546 +0,0 @@
/*!
* This file is part of Aloha Editor
* Author & Copyright (c) 2010 Gentics Software GmbH, aloha@gentics.com
* Licensed unter the terms of http://www.aloha-editor.com/license.html
*/
(function(window, undefined) {
var
jQuery = window.alohaQuery || window.jQuery, $ = jQuery,
// GENTICS = window.GENTICS,
// Aloha = window.Aloha,
DOMUtils, TextRangeUtils, selection, DOMRange, RangeIterator, DOMSelection;
/*
* Only execute the following code if we are in IE (check for
* document.attachEvent, this is a microsoft event and therefore only available
* in IE).
*/
if(document.attachEvent && document.selection) {
/*!
* DOM Ranges for Internet Explorer (m2)
*
* Copyright (c) 2009 Tim Cameron Ryan
* Released under the MIT/X License
* available at http://code.google.com/p/ierange/
*/
/*
Range reference:
http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html
http://mxr.mozilla.org/mozilla-central/source/content/base/src/nsRange.cpp
https://developer.mozilla.org/En/DOM:Range
Selection reference:
http://trac.webkit.org/browser/trunk/WebCore/page/DOMSelection.cpp
TextRange reference:
http://msdn.microsoft.com/en-us/library/ms535872.aspx
Other links:
http://jorgenhorstink.nl/test/javascript/range/range.js
http://jorgenhorstink.nl/2006/07/05/dom-range-implementation-in-ecmascript-completed/
http://dylanschiemann.com/articles/dom2Range/dom2RangeExamples.html
*/
//[TODO] better exception support
/*
DOM functions
*/
DOMUtils = {
findChildPosition: function (node) {
for (var i = 0; node = node.previousSibling; i++)
continue;
return i;
},
isDataNode: function (node) {
return node && node.nodeValue !== null && node.data !== null;
},
isAncestorOf: function (parent, node) {
return !DOMUtils.isDataNode(parent) &&
(parent.contains(DOMUtils.isDataNode(node) ? node.parentNode : node) ||
node.parentNode == parent);
},
isAncestorOrSelf: function (root, node) {
return DOMUtils.isAncestorOf(root, node) || root == node;
},
findClosestAncestor: function (root, node) {
if (DOMUtils.isAncestorOf(root, node))
while (node && node.parentNode != root)
node = node.parentNode;
return node;
},
getNodeLength: function (node) {
return DOMUtils.isDataNode(node) ? node.length : node.childNodes.length;
},
splitDataNode: function (node, offset) {
if (!DOMUtils.isDataNode(node))
return false;
var newNode = node.cloneNode(false);
node.deleteData(offset, node.length);
newNode.deleteData(0, offset);
node.parentNode.insertBefore(newNode, node.nextSibling);
}
};
/*
Text Range utilities
functions to simplify text range manipulation in ie
*/
TextRangeUtils = {
convertToDOMRange: function (textRange, document) {
var domRange,adoptBoundary;
adoptBoundary = function(domRange, textRange, bStart) {
// iterate backwards through parent element to find anchor location
var cursorNode = document.createElement('a'),
cursor = textRange.duplicate(),
parent;
cursor.collapse(bStart);
parent = cursor.parentElement();
do {
parent.insertBefore(cursorNode, cursorNode.previousSibling);
cursor.moveToElementText(cursorNode);
} while (cursor.compareEndPoints(bStart ? 'StartToStart' : 'StartToEnd', textRange) > 0 && cursorNode.previousSibling);
// when we exceed or meet the cursor, we've found the node
if (cursor.compareEndPoints(bStart ? 'StartToStart' : 'StartToEnd', textRange) == -1 && cursorNode.nextSibling) {
// data node
cursor.setEndPoint(bStart ? 'EndToStart' : 'EndToEnd', textRange);
domRange[bStart ? 'setStart' : 'setEnd'](cursorNode.nextSibling, cursor.text.length);
} else {
// element
domRange[bStart ? 'setStartBefore' : 'setEndBefore'](cursorNode);
}
cursorNode.parentNode.removeChild(cursorNode);
};
// return a DOM range
domRange = new DOMRange(document);
adoptBoundary(domRange, textRange, true);
adoptBoundary(domRange, textRange, false);
return domRange;
},
convertFromDOMRange: function (domRange) {
function adoptEndPoint(textRange, domRange, bStart) {
// find anchor node and offset
var container = domRange[bStart ? 'startContainer' : 'endContainer'],
offset = domRange[bStart ? 'startOffset' : 'endOffset'], textOffset = 0,
anchorNode = DOMUtils.isDataNode(container) ? container : container.childNodes[offset],
anchorParent = DOMUtils.isDataNode(container) ? container.parentNode : container,
cursorNode, cursor;
// visible data nodes need a text offset
if (container.nodeType == 3 || container.nodeType == 4) {
textOffset = offset;
}
// create a cursor element node to position range (since we can't select text nodes)
cursorNode = domRange._document.createElement('a');
anchorParent.insertBefore(cursorNode, anchorNode);
cursor = domRange._document.body.createTextRange();
cursor.moveToElementText(cursorNode);
cursorNode.parentNode.removeChild(cursorNode);
// move range
textRange.setEndPoint(bStart ? 'StartToStart' : 'EndToStart', cursor);
textRange[bStart ? 'moveStart' : 'moveEnd']('character', textOffset);
}
// return an IE text range
var textRange = domRange._document.body.createTextRange();
adoptEndPoint(textRange, domRange, true);
adoptEndPoint(textRange, domRange, false);
return textRange;
}
};
/*
DOM Range
*/
DOMRange = function(document) {
// save document parameter
this._document = document;
// initialize range
//[TODO] this should be located at document[0], document[0]
this.startContainer = this.endContainer = document.body;
this.endOffset = DOMUtils.getNodeLength(document.body);
};
DOMRange.START_TO_START = 0;
DOMRange.START_TO_END = 1;
DOMRange.END_TO_END = 2;
DOMRange.END_TO_START = 3;
DOMRange.prototype = {
// public properties
startContainer: null,
startOffset: 0,
endContainer: null,
endOffset: 0,
commonAncestorContainer: null,
collapsed: false,
// private properties
_document: null,
// private methods
_refreshProperties: function () {
// collapsed attribute
this.collapsed = (this.startContainer == this.endContainer && this.startOffset == this.endOffset);
// find common ancestor
var node = this.startContainer;
while (node && node != this.endContainer && !DOMUtils.isAncestorOf(node, this.endContainer))
node = node.parentNode;
this.commonAncestorContainer = node;
},
// range methods
//[TODO] collapse if start is after end, end is before start
setStart: function(container, offset) {
this.startContainer = container;
this.startOffset = offset;
this._refreshProperties();
},
setEnd: function(container, offset) {
this.endContainer = container;
this.endOffset = offset;
this._refreshProperties();
},
setStartBefore: function (refNode) {
// set start to beore this node
this.setStart(refNode.parentNode, DOMUtils.findChildPosition(refNode));
},
setStartAfter: function (refNode) {
// select next sibling
this.setStart(refNode.parentNode, DOMUtils.findChildPosition(refNode) + 1);
},
setEndBefore: function (refNode) {
// set end to beore this node
this.setEnd(refNode.parentNode, DOMUtils.findChildPosition(refNode));
},
setEndAfter: function (refNode) {
// select next sibling
this.setEnd(refNode.parentNode, DOMUtils.findChildPosition(refNode) + 1);
},
selectNode: function (refNode) {
this.setStartBefore(refNode);
this.setEndAfter(refNode);
},
selectNodeContents: function (refNode) {
this.setStart(refNode, 0);
this.setEnd(refNode, DOMUtils.getNodeLength(refNode));
},
collapse: function (toStart) {
if (toStart)
this.setEnd(this.startContainer, this.startOffset);
else
this.setStart(this.endContainer, this.endOffset);
},
// editing methods
cloneContents: function () {
// clone subtree
return (function cloneSubtree(iterator) {
for (var node, frag = document.createDocumentFragment(); node = iterator.next(); ) {
node = node.cloneNode(!iterator.hasPartialSubtree());
if (iterator.hasPartialSubtree())
node.appendChild(cloneSubtree(iterator.getSubtreeIterator()));
frag.appendChild(node);
}
return frag;
})(new RangeIterator(this));
},
extractContents: function () {
// cache range and move anchor points
var range = this.cloneRange();
if (this.startContainer != this.commonAncestorContainer)
this.setStartAfter(DOMUtils.findClosestAncestor(this.commonAncestorContainer, this.startContainer));
this.collapse(true);
// extract range
return (function extractSubtree(iterator) {
for (var node, frag = document.createDocumentFragment(); node = iterator.next(); ) {
if ( iterator.hasPartialSubtree() ) {
node = node.cloneNode(false);
}
else {
iterator.remove();
}
if (iterator.hasPartialSubtree())
node.appendChild(extractSubtree(iterator.getSubtreeIterator()));
frag.appendChild(node);
}
return frag;
})(new RangeIterator(range));
},
deleteContents: function () {
// cache range and move anchor points
var range = this.cloneRange();
if (this.startContainer != this.commonAncestorContainer)
this.setStartAfter(DOMUtils.findClosestAncestor(this.commonAncestorContainer, this.startContainer));
this.collapse(true);
// delete range
(function deleteSubtree(iterator) {
while (iterator.next()) {
if ( iterator.hasPartialSubtree() ) {
deleteSubtree(iterator.getSubtreeIterator());
}
else {
iterator.remove();
}
}
})(new RangeIterator(range));
},
insertNode: function (newNode) {
// set original anchor and insert node
if (DOMUtils.isDataNode(this.startContainer)) {
DOMUtils.splitDataNode(this.startContainer, this.startOffset);
this.startContainer.parentNode.insertBefore(newNode, this.startContainer.nextSibling);
} else {
this.startContainer.insertBefore(newNode, this.startContainer.childNodes[this.startOffset]);
}
// resync start anchor
this.setStart(this.startContainer, this.startOffset);
},
surroundContents: function (newNode) {
// extract and surround contents
var content = this.extractContents();
this.insertNode(newNode);
newNode.appendChild(content);
this.selectNode(newNode);
},
// other methods
compareBoundaryPoints: function (how, sourceRange) {
// get anchors
var containerA, offsetA, containerB, offsetB;
switch (how) {
case DOMRange.START_TO_START:
case DOMRange.START_TO_END:
containerA = this.startContainer;
offsetA = this.startOffset;
break;
case DOMRange.END_TO_END:
case DOMRange.END_TO_START:
containerA = this.endContainer;
offsetA = this.endOffset;
break;
}
switch (how) {
case DOMRange.START_TO_START:
case DOMRange.END_TO_START:
containerB = sourceRange.startContainer;
offsetB = sourceRange.startOffset;
break;
case DOMRange.START_TO_END:
case DOMRange.END_TO_END:
containerB = sourceRange.endContainer;
offsetB = sourceRange.endOffset;
break;
}
// compare
return containerA.sourceIndex < containerB.sourceIndex ? -1 :
containerA.sourceIndex == containerB.sourceIndex ?
offsetA < offsetB ? -1 : offsetA == offsetB ? 0 : 1
: 1;
},
cloneRange: function () {
// return cloned range
var range = new DOMRange(this._document);
range.setStart(this.startContainer, this.startOffset);
range.setEnd(this.endContainer, this.endOffset);
return range;
},
detach: function () {
//[TODO] Releases Range from use to improve performance.
},
toString: function () {
return TextRangeUtils.convertFromDOMRange(this).text;
},
createContextualFragment: function (tagString) {
// parse the tag string in a context node
var
content = (DOMUtils.isDataNode(this.startContainer) ? this.startContainer.parentNode : this.startContainer).cloneNode(false),
fragment;
content.innerHTML = tagString;
// return a document fragment from the created node
for (fragment = this._document.createDocumentFragment(); content.firstChild; )
fragment.appendChild(content.firstChild);
return fragment;
}
};
/*
Range iterator
*/
RangeIterator = function(range) {
this.range = range;
if (range.collapsed) {
return;
}
//[TODO] ensure this works
// get anchors
var root = range.commonAncestorContainer;
this._next = range.startContainer == root && !DOMUtils.isDataNode(range.startContainer) ?
range.startContainer.childNodes[range.startOffset] :
DOMUtils.findClosestAncestor(root, range.startContainer);
this._end = range.endContainer == root && !DOMUtils.isDataNode(range.endContainer) ?
range.endContainer.childNodes[range.endOffset] :
DOMUtils.findClosestAncestor(root, range.endContainer).nextSibling;
};
RangeIterator.prototype = {
// public properties
range: null,
// private properties
_current: null,
_next: null,
_end: null,
// public methods
hasNext: function () {
return !!this._next;
},
next: function () {
// move to next node
var current = this._current = this._next;
this._next = this._current && this._current.nextSibling != this._end ?
this._current.nextSibling : null;
// check for partial text nodes
if (DOMUtils.isDataNode(this._current)) {
if (this.range.endContainer == this._current)
(current = current.cloneNode(true)).deleteData(this.range.endOffset, current.length - this.range.endOffset);
if (this.range.startContainer == this._current)
(current = current.cloneNode(true)).deleteData(0, this.range.startOffset);
}
return current;
},
remove: function () {
var end, start;
// check for partial text nodes
if (DOMUtils.isDataNode(this._current) &&
(this.range.startContainer == this._current || this.range.endContainer == this._current)) {
start = this.range.startContainer == this._current ? this.range.startOffset : 0;
end = this.range.endContainer == this._current ? this.range.endOffset : this._current.length;
this._current.deleteData(start, end - start);
} else
this._current.parentNode.removeChild(this._current);
},
hasPartialSubtree: function () {
// check if this node be partially selected
return !DOMUtils.isDataNode(this._current) &&
(DOMUtils.isAncestorOrSelf(this._current, this.range.startContainer) ||
DOMUtils.isAncestorOrSelf(this._current, this.range.endContainer));
},
getSubtreeIterator: function () {
// create a new range
var subRange = new DOMRange(this.range._document);
subRange.selectNodeContents(this._current);
// handle anchor points
if (DOMUtils.isAncestorOrSelf(this._current, this.range.startContainer))
subRange.setStart(this.range.startContainer, this.range.startOffset);
if (DOMUtils.isAncestorOrSelf(this._current, this.range.endContainer))
subRange.setEnd(this.range.endContainer, this.range.endOffset);
// return iterator
return new RangeIterator(subRange);
}
};
/*
DOM Selection
*/
//[NOTE] This is a very shallow implementation of the Selection object, based on Webkit's
// implementation and without redundant features. Complete selection manipulation is still
// possible with just removeAllRanges/addRange/getRangeAt.
DOMSelection = function (document) {
// save document parameter
this._document = document;
// add DOM selection handler
var selection = this;
document.attachEvent('onselectionchange', function () { selection._selectionChangeHandler(); });
};
DOMSelection.prototype = {
// public properties
rangeCount: 0,
// private properties
_document: null,
// private methods
_selectionChangeHandler: function () {
// check if there exists a range
this.rangeCount = this._selectionExists(this._document.selection.createRange()) ? 1 : 0;
},
_selectionExists: function (textRange) {
// checks if a created text range exists or is an editable cursor
return textRange.compareEndPoints('StartToEnd', textRange) !== 0 ||
textRange.parentElement().isContentEditable;
},
// public methods
addRange: function (range) {
// add range or combine with existing range
var selection = this._document.selection.createRange(), textRange = TextRangeUtils.convertFromDOMRange(range);
if (!this._selectionExists(selection))
{
// select range
textRange.select();
}
else
{
// only modify range if it intersects with current range
if (textRange.compareEndPoints('StartToStart', selection) == -1)
if (textRange.compareEndPoints('StartToEnd', selection) > -1 &&
textRange.compareEndPoints('EndToEnd', selection) == -1)
selection.setEndPoint('StartToStart', textRange);
else
if (textRange.compareEndPoints('EndToStart', selection) < 1 &&
textRange.compareEndPoints('EndToEnd', selection) > -1)
selection.setEndPoint('EndToEnd', textRange);
selection.select();
}
},
removeAllRanges: function () {
// remove all ranges
this._document.selection.empty();
},
getRangeAt: function (index) {
// return any existing selection, or a cursor position in content editable mode
var textRange = this._document.selection.createRange();
if (this._selectionExists(textRange))
return TextRangeUtils.convertToDOMRange(textRange, this._document);
return null;
},
toString: function () {
// get selection text
return this._document.selection.createRange().text;
}
};
/*
scripting hooks
*/
document.createRange = function () {
return new DOMRange(document);
};
selection = new DOMSelection(document);
window.getSelection = function () {
return selection;
};
//[TODO] expose DOMRange/DOMSelection to window.?
}
})(window);

View File

@ -1,324 +0,0 @@
/*!
* This file is part of Aloha Editor Project http://aloha-editor.org
* Copyright © 2010-2011 Gentics Software GmbH, aloha@gentics.com
* Contributors http://aloha-editor.org/contribution.php
* Licensed unter the terms of http://www.aloha-editor.org/license.html
*//*
* Aloha Editor is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.*
*
* Aloha Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(
[ 'aloha/core', 'aloha/selection', 'aloha/jquery', 'aloha/console' ],
function( Aloha, Selection, jQuery, console ) {
var
// $ = jQuery,
// Aloha = window.Aloha,
// console = window.console,
XMLSerializer = window.XMLSerializer;
/**
* jQuery between Extension
*
* insert either html code, a dom object OR a jQuery object inside of an existing text node.
* if the chained jQuery object is not a text node, nothing will happen.
*
* @param content HTML Code, DOM object or jQuery object to be inserted
* @param offset character offset from the start where the content should be inserted
*/
jQuery.fn.between = function(content, offset) {
var
offSize,
fullText;
if (this[0].nodeType !== 3) {
// we are not in a text node, just insert the element at the corresponding position
offSize = this.children().size();
if (offset > offSize) {
offset = offSize;
}
if (offset <= 0) {
this.prepend(content);
} else {
this.children().eq(offset -1).after(content);
}
} else {
// we are in a text node so we have to split it at the correct position
if (offset <= 0) {
this.before(content);
} else if (offset >= this[0].length) {
this.after(content);
} else {
fullText = this[0].data;
this[0].data = fullText.substring(0, offset);
this.after(fullText.substring(offset, fullText.length));
this.after(content);
}
}
};
/**
* Make the object contenteditable. Care about browser version (name of contenteditable attribute depends on it)
*/
jQuery.fn.contentEditable = function( b ) {
// ie does not understand contenteditable but contentEditable
// contentEditable is not xhtml compatible.
var $el = jQuery(this);
var ce = 'contenteditable';
// Check
if (jQuery.browser.msie && parseInt(jQuery.browser.version,10) == 7 ) {
ce = 'contentEditable';
}
if (typeof b === 'undefined' ) {
// For chrome use this specific attribute. The old ce will only
// return 'inherit' for nested elements of a contenteditable.
// The isContentEditable is a w3c standard compliant property which works in IE7,8,FF36+, Chrome 12+
if (typeof $el[0] === 'undefined' ) {
console.error('The jquery object did not contain any valid elements.');
return undefined;
}
if (typeof $el[0].isContentEditable === 'undefined') {
console.warn('Could not determine whether the is editable or not. I assume it is.');
return true;
} else {
return $el[0].isContentEditable;
}
} else if (b === '') {
$el.removeAttr(ce);
} else {
if (b && b !== 'false') {
b = 'true';
} else {
b = 'false';
}
$el.attr(ce, b);
}
return $el;
};
/**
* jQuery Aloha Plugin
*
* turn all dom elements to continous text
* @return jQuery object for the matched elements
* @api
*/
jQuery.fn.aloha = function() {
var $this = jQuery( this );
Aloha.bind( 'aloha-ready', function() {
$this.each( function() {
// create a new aloha editable object for each passed object
if ( !Aloha.isEditable( this ) ) {
new Aloha.Editable( jQuery( this ) );
}
});
});
// Chain
return $this;
};
/**
* jQuery destroy elements as editable
*
* destroy all mached elements editable capabilities
* @return jQuery object for the matched elements
* @api
*/
jQuery.fn.mahalo = function() {
return this.each(function() {
if (Aloha.isEditable(this)) {
Aloha.getEditableById(jQuery(this).attr('id')).destroy();
}
});
};
/**
* jQuery Extension
* new Event which is triggered whenever a selection (length >= 0) is made in
* an Aloha Editable element
*/
jQuery.fn.contentEditableSelectionChange = function(callback) {
var that = this;
// update selection when keys are pressed
this.keyup(function(event){
var rangeObject = Selection.getRangeObject();
callback(event);
});
// update selection on doubleclick (especially important for the first automatic selection, when the Editable is not active yet, but is at the same time activated as the selection occurs
this.dblclick(function(event) {
callback(event);
});
// update selection when text is selected
this.mousedown(function(event){
// remember that a selection was started
that.selectionStarted = true;
});
jQuery(document).mouseup(function(event) {
Selection.eventOriginalTarget = that;
if (that.selectionStarted) {
callback(event);
}
Selection.eventOriginalTarget = false;
that.selectionStarted = false;
});
return this;
};
/**
* Fetch the outerHTML of an Element
* @version 1.0.0
* @date February 01, 2011
* @package jquery-sparkle {@link http://www.balupton/projects/jquery-sparkle}
* @author Benjamin Arthur Lupton {@link http://balupton.com}
* @copyright 2011 Benjamin Arthur Lupton {@link http://balupton.com}
* @license MIT License {@link http://creativecommons.org/licenses/MIT/}
* @return {String} outerHtml
*/
jQuery.fn.outerHtml = jQuery.fn.outerHtml || function(){
var
$el = jQuery(this),
el = $el.get(0);
if (typeof el.outerHTML != 'undefined') {
return el.outerHTML;
} else {
try {
// Gecko-based browsers, Safari, Opera.
return (new XMLSerializer()).serializeToString(el);
} catch (e) {
try {
// Internet Explorer.
return el.xml;
} catch (e) {}
}
}
};
jQuery.fn.zap = function () {
return this.each(function(){ jQuery(this.childNodes).insertBefore(this); }).remove();
};
jQuery.fn.textNodes = function(excludeBreaks, includeEmptyTextNodes) {
var
ret = [],
doSomething = function(el){
if (
(el.nodeType === 3 && jQuery.trim(el.data) && !includeEmptyTextNodes) ||
(el.nodeType === 3 && includeEmptyTextNodes) ||
(el.nodeName =="BR" && !excludeBreaks)) {
ret.push(el);
} else {
for (var i=0, childLength = el.childNodes.length; i < childLength; ++i) {
doSomething(el.childNodes[i]);
}
}
};
doSomething(this[0]);
return jQuery(ret);
};
/**
* extendObjects is like jQuery.extend, but it does not extend arrays
*/
jQuery.extendObjects = jQuery.fn.extendObjects = function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;
// Handle a deep copy situation
if ( typeof target === "boolean" ) {
deep = target;
target = arguments[1] || {};
// skip the boolean and the target
i = 2;
}
// Handle case when target is a string or something (possible in deep copy)
if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
target = {};
}
// extend jQuery itself if only one argument is passed
if ( length === i ) {
target = this;
--i;
}
for ( ; i < length; i++ ) {
// Only deal with non-null/undefined values
if ( (options = arguments[ i ]) != null ) {
// Extend the base object
for ( name in options ) {
src = target[ name ];
copy = options[ name ];
// Prevent never-ending loop
if ( target === copy ) {
continue;
}
// Recurse if we're merging plain objects or arrays
if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
if ( copyIsArray ) {
copyIsArray = false;
clone = src && jQuery.isArray(src) ? src : [];
} else {
clone = src && jQuery.isPlainObject(src) ? src : {};
}
// Never move original objects, clone them
if (jQuery.isArray(copy)) {
// don't extend arrays
target[ name ] = copy;
} else {
target[ name ] = jQuery.extendObjects( deep, clone, copy );
}
// Don't bring in undefined values
} else if ( copy !== undefined ) {
target[ name ] = copy;
}
}
}
}
// Return the modified object
return target;
};
jQuery.isBoolean = function(b) {
return b === true || b === false;
},
jQuery.isNumeric = function(o) {
return ! isNaN (o-0);
}
});

View File

@ -1,24 +0,0 @@
/*!
* This file is part of Aloha Editor Project http://aloha-editor.org
* Copyright (c) 2010-2011 Gentics Software GmbH, aloha@gentics.com
* Contributors http://aloha-editor.org/contribution.php
* Licensed unter the terms of http://www.aloha-editor.org/license.html
*
* Aloha Editor is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.*
*
* Aloha Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// define jquery and ext modules. They need to be available in global namespace
define('aloha/jquery',[], function() {
return Aloha.jQuery;
});

View File

@ -1,115 +0,0 @@
/*!
* This file is part of Aloha Editor Project http://aloha-editor.org
* Copyright © 2010-2011 Gentics Software GmbH, aloha@gentics.com
* Contributors http://aloha-editor.org/contribution.php
* Licensed unter the terms of http://www.aloha-editor.org/license.html
*//*
* Aloha Editor is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.*
*
* Aloha Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// use specified jQuery or load jQuery
define(
[ 'aloha/jquery' ],
function( jQuery ) {
//PATCH FOR A JQUERY BUG IN 1.6.1 & 1.6.2
//An additional sanity check was introduced to prevent IE from crashing when cache[id] does not exist
jQuery.data = ( function( jQuery ) {
return function( elem, name, data, pvt /* Internal Use Only */ ) {
if ( !jQuery.acceptData( elem ) ) {
return;
}
var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache,
// We have to handle DOM nodes and JS objects differently because IE6-7
// can't GC object references properly across the DOM-JS boundary
isNode = elem.nodeType,
// Only DOM nodes need the global jQuery cache; JS object data is
// attached directly to the object so GC can occur automatically
cache = isNode ? jQuery.cache : elem,
// Only defining an ID for JS objects if its cache already exists allows
// the code to shortcut on the same path as a DOM node with no cache
id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando;
// Avoid doing any more work than we need to when trying to get data on an
// object that has no data at all
//if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) {
if ( (!id || (pvt && id && (!cache[id] || !cache[ id ][ internalKey ]))) && getByName && data === undefined ) {
return;
}
if ( !id ) {
// Only DOM nodes need a new unique ID for each element since their data
// ends up in the global cache
if ( isNode ) {
elem[ jQuery.expando ] = id = ++jQuery.uuid;
} else {
id = jQuery.expando;
}
}
if ( !cache[ id ] ) {
cache[ id ] = {};
// TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery
// metadata on plain JS objects when the object is serialized using
// JSON.stringify
if ( !isNode ) {
cache[ id ].toJSON = jQuery.noop;
}
}
// An object can be passed to jQuery.data instead of a key/value pair; this gets
// shallow copied over onto the existing cache
if ( typeof name === "object" || typeof name === "function" ) {
if ( pvt ) {
cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name);
} else {
cache[ id ] = jQuery.extend(cache[ id ], name);
}
}
thisCache = cache[ id ];
// Internal jQuery data is stored in a separate object inside the object's data
// cache in order to avoid key collisions between internal data and user-defined
// data
if ( pvt ) {
if ( !thisCache[ internalKey ] ) {
thisCache[ internalKey ] = {};
}
thisCache = thisCache[ internalKey ];
}
if ( data !== undefined ) {
thisCache[ jQuery.camelCase( name ) ] = data;
}
// TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should
// not attempt to inspect the internal events object using jQuery.data, as this
// internal data object is undocumented and subject to change.
if ( name === "events" && !thisCache[name] ) {
return thisCache[ internalKey ] && thisCache[ internalKey ].events;
}
return getByName ? thisCache[ jQuery.camelCase( name ) ] : thisCache;
};
})( jQuery );
});

View File

@ -1,898 +0,0 @@
/*!
* This file is part of Aloha Editor Project http://aloha-editor.org
* Copyright © 2010-2011 Gentics Software GmbH, aloha@gentics.com
* Contributors http://aloha-editor.org/contribution.php
* Licensed unter the terms of http://www.aloha-editor.org/license.html
*//*
* Aloha Editor is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.*
*
* Aloha Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(
[ 'aloha/core', 'util/class', 'aloha/jquery' ],
function( Aloha, Class, jQuery ) {
var
// Aloha = window.Aloha,
// Class = window.Class,
GENTICS = window.GENTICS;
/**
* Markup object
*/
Aloha.Markup = Class.extend({
/**
* Key handlers for special key codes
*/
keyHandlers: {},
/**
* Add a key handler for the given key code
* @param keyCode key code
* @param handler handler function
*/
addKeyHandler: function (keyCode, handler) {
if (!this.keyHandlers[keyCode]) {
this.keyHandlers[keyCode] = [];
}
this.keyHandlers[keyCode].push(handler);
},
insertBreak: function () {
var range = Aloha.Selection.rangeObject,nonWSIndex,nextTextNode,newBreak;
if (!range.isCollapsed()) {
this.removeSelectedMarkup();
}
newBreak = jQuery('<br/>');
GENTICS.Utils.Dom.insertIntoDOM(newBreak, range, Aloha.activeEditable.obj);
nextTextNode = GENTICS.Utils.Dom.searchAdjacentTextNode(newBreak.parent().get(0), GENTICS.Utils.Dom.getIndexInParent(newBreak.get(0)) + 1, false);
if (nextTextNode) {
// trim leading whitespace
nonWSIndex = nextTextNode.data.search(/\S/);
if (nonWSIndex > 0) {
nextTextNode.data = nextTextNode.data.substring(nonWSIndex);
}
}
range.startContainer = range.endContainer = newBreak.get(0).parentNode;
range.startOffset = range.endOffset = GENTICS.Utils.Dom.getIndexInParent(newBreak.get(0)) + 1;
range.correctRange();
range.clearCaches();
range.select();
},
/**
* first method to handle key strokes
* @param event DOM event
* @param rangeObject as provided by Aloha.Selection.getRangeObject();
* @return "Aloha.Selection"
*/
preProcessKeyStrokes: function(event) {
if (event.type != 'keydown') {
return false;
}
var rangeObject = Aloha.Selection.rangeObject,
handlers,
i;
if (this.keyHandlers[event.keyCode]) {
handlers = this.keyHandlers[event.keyCode];
for ( i = 0; i < handlers.length; ++i) {
if (!handlers[i](event)) {
return false;
}
}
}
// handle left (37) and right (39) keys for block detection
if (event.keyCode === 37 || event.keyCode === 39) {
return this.processCursor(rangeObject, event.keyCode);
}
// BACKSPACE
if (event.keyCode === 8) {
event.preventDefault(); // prevent history.back() even on exception
Aloha.execCommand( 'delete', false );
return false;
}
// DELETE
if (event.keyCode === 46) {
Aloha.execCommand( 'forwarddelete', false );
return false;
}
// ENTER
if (event.keyCode === 13 ) {
if (event.shiftKey) {
Aloha.execCommand( 'insertlinebreak', false );
return false;
} else {
Aloha.execCommand( 'insertparagraph', false );
return false;
}
}
return true;
},
/**
* Processing of cursor keys
* will currently detect blocks (elements with contenteditable=false)
* and selects them (normally the cursor would jump right past them)
*
* For each block an 'aloha-block-selected' event will be triggered.
*
* @param range the current range object
* @param keyCode keyCode of current keypress
* @return false if a block was found to prevent further events, true otherwise
*/
processCursor: function(range, keyCode) {
var rt = range.getRangeTree(), // RangeTree reference
i = 0,
cursorLeft = keyCode === 37,
cursorRight = keyCode === 39,
nextSiblingIsBlock = false, // check whether the next sibling is a block (contenteditable = false)
cursorIsWithinBlock = false, // check whether the cursor is positioned within a block (contenteditable = false)
cursorAtLastPos = false, // check if the cursor is within the last position of the currently active dom element
obj; // will contain references to dom objects
if ( !range.isCollapsed() ) {
return true;
}
for (;i < rt.length; i++) {
if ( typeof rt[i].domobj !== 'undefined' ) {
cursorAtLastPos = range.startOffset === rt[i].domobj.length;
if (cursorAtLastPos) {
nextSiblingIsBlock = jQuery( rt[i].domobj.nextSibling ).attr('contenteditable') === 'false';
cursorIsWithinBlock = jQuery( rt[i].domobj ).parents('[contenteditable=false]').length > 0;
if ( cursorRight && nextSiblingIsBlock ) {
obj = rt[i].domobj.nextSibling;
GENTICS.Utils.Dom.selectDomNode( obj );
Aloha.trigger( 'aloha-block-selected', obj );
Aloha.Selection.preventSelectionChanged();
return false;
}
if ( cursorLeft && cursorIsWithinBlock ) {
obj = jQuery( rt[i].domobj ).parents('[contenteditable=false]').get(0);
GENTICS.Utils.Dom.selectDomNode( obj );
Aloha.trigger( 'aloha-block-selected', obj );
Aloha.Selection.preventSelectionChanged();
return false;
}
}
}
}
},
/**
* method handling shiftEnter
* @param Aloha.Selection.SelectionRange of the current selection
* @return void
*/
processShiftEnter: function(rangeObject) {
this.insertHTMLBreak(rangeObject.getSelectionTree(), rangeObject);
},
/**
* method handling Enter
* @param Aloha.Selection.SelectionRange of the current selection
* @return void
*/
processEnter: function(rangeObject) {
if (rangeObject.splitObject) {
// now comes a very evil hack for ie, when the enter is pressed in a text node in an li element, we just append an empty text node
// if (jQuery.browser.msie
// && GENTICS.Utils.Dom
// .isListElement(rangeObject.splitObject)) {
// jQuery(rangeObject.splitObject).append(
// jQuery(document.createTextNode('')));
// }
this.splitRangeObject(rangeObject);
} else { // if there is no split object, the Editable is the paragraph type itself (e.g. a p or h2)
this.insertHTMLBreak(rangeObject.getSelectionTree(), rangeObject);
}
},
/**
* Insert the given html markup at the current selection
* @param html html markup to be inserted
*/
insertHTMLCode: function (html) {
var rangeObject = Aloha.Selection.rangeObject;
this.insertHTMLBreak(rangeObject.getSelectionTree(), rangeObject, jQuery(html));
},
/**
* insert an HTML Break <br /> into current selection
* @param Aloha.Selection.SelectionRange of the current selection
* @return void
*/
insertHTMLBreak: function(selectionTree, rangeObject, inBetweenMarkup) {
var i, treeLength, el, jqEl, jqElBefore, jqElAfter, tmpObject, offset, checkObj;
inBetweenMarkup = inBetweenMarkup ? inBetweenMarkup: jQuery('<br/>');
for ( i = 0, treeLength = selectionTree.length; i < treeLength; i++) {
el = selectionTree[i];
jqEl = el.domobj ? jQuery(el.domobj) : undefined;
if (el.selection !== 'none') { // before cursor, leave this part inside the splitObject
if (el.selection == 'collapsed') {
// collapsed selection found (between nodes)
if (i > 0) {
// not at the start, so get the element to the left
jqElBefore = jQuery(selectionTree[i-1].domobj);
// and insert the break after it
jqElBefore.after(inBetweenMarkup);
} else {
// at the start, so get the element to the right
jqElAfter = jQuery(selectionTree[1].domobj);
// and insert the break before it
jqElAfter.before(inBetweenMarkup);
}
// now set the range
rangeObject.startContainer = rangeObject.endContainer = inBetweenMarkup[0].parentNode;
rangeObject.startOffset = rangeObject.endOffset = GENTICS.Utils.Dom.getIndexInParent(inBetweenMarkup[0]) + 1;
rangeObject.correctRange();
} else if (el.domobj && el.domobj.nodeType === 3) { // textNode
// when the textnode is immediately followed by a blocklevel element (like p, h1, ...) we need to add an additional br in between
if (el.domobj.nextSibling
&& el.domobj.nextSibling.nodeType == 1
&& Aloha.Selection.replacingElements[el.domobj.nextSibling.nodeName
.toLowerCase()]) {
// TODO check whether this depends on the browser
jqEl.after('<br/>');
}
if (this.needEndingBreak()) {
// when the textnode is the last inside a blocklevel element
// (like p, h1, ...) we need to add an additional br as very
// last object in the blocklevel element
checkObj = el.domobj;
while (checkObj) {
if (checkObj.nextSibling) {
checkObj = false;
} else {
// go to the parent
checkObj = checkObj.parentNode;
// found a blocklevel or list element, we are done
if (GENTICS.Utils.Dom.isBlockLevelElement(checkObj) || GENTICS.Utils.Dom.isListElement(checkObj)) {
break;
}
// reached the limit object, we are done
if (checkObj === rangeObject.limitObject) {
checkObj = false;
}
}
}
// when we found a blocklevel element, insert a break at the
// end. Mark the break so that it is cleaned when the
// content is fetched.
if (checkObj) {
jQuery(checkObj).append('<br class="aloha-cleanme"/>');
}
}
// insert the break
jqEl.between(inBetweenMarkup, el.startOffset);
// correct the range
// count the number of previous siblings
offset = 0;
tmpObject = inBetweenMarkup[0];
while (tmpObject) {
tmpObject = tmpObject.previousSibling;
offset++;
}
rangeObject.startContainer = inBetweenMarkup[0].parentNode;
rangeObject.endContainer = inBetweenMarkup[0].parentNode;
rangeObject.startOffset = offset;
rangeObject.endOffset = offset;
rangeObject.correctRange();
} else if (el.domobj && el.domobj.nodeType === 1) { // other node, normally a break
if (jqEl.parent().find('br.aloha-ephemera').length === 0) {
// but before putting it, remove all:
jQuery(rangeObject.limitObject).find('br.aloha-ephemera').remove();
// now put it:
jQuery(rangeObject.commonAncestorContainer).append(this.getFillUpElement(rangeObject.splitObject));
}
jqEl.after(inBetweenMarkup);
// now set the selection. Since we just added one break do the currect el
// the new position must be el's position + 1. el's position is the index
// of the el in the selection tree, which is i. then we must add
// another +1 because we want to be AFTER the object, not before. therefor +2
rangeObject.startContainer = rangeObject.commonAncestorContainer;
rangeObject.endContainer = rangeObject.startContainer;
rangeObject.startOffset = i+2;
rangeObject.endOffset = i+2;
rangeObject.update();
}
}
}
rangeObject.select();
},
/**
* Check whether blocklevel elements need breaks at the end to visibly render a newline
* @return true if an ending break is necessary, false if not
*/
needEndingBreak: function () {
// currently, all browser except IE need ending breaks
return !jQuery.browser.msie;
},
/**
* Get the currently selected text or false if nothing is selected (or the selection is collapsed)
* @return selected text
*/
getSelectedText: function () {
var rangeObject = Aloha.Selection.rangeObject;
if (rangeObject.isCollapsed()) {
return false;
}
return this.getFromSelectionTree(rangeObject.getSelectionTree(), true);
},
/**
* Recursive function to get the selected text from the selection tree starting at the given level
* @param selectionTree array of selectiontree elements
* @param astext true when the contents shall be fetched as text, false for getting as html markup
* @return selected text from that level (incluiding all sublevels)
*/
getFromSelectionTree: function (selectionTree, astext) {
var text = '', i, treeLength, el, clone;
for ( i = 0, treeLength = selectionTree.length; i < treeLength; i++) {
el = selectionTree[i];
if (el.selection == 'partial') {
if (el.domobj.nodeType === 3) {
// partial text node selected, get the selected part
text += el.domobj.data.substring(el.startOffset, el.endOffset);
} else if (el.domobj.nodeType === 1 && el.children) {
// partial element node selected, do the recursion into the children
if (astext) {
text += this.getFromSelectionTree(el.children, astext);
} else {
// when the html shall be fetched, we create a clone of the element and remove all the children
clone = jQuery(el.domobj).clone(false).empty();
// then we do the recursion and add the selection into the clone
clone.html(this.getFromSelectionTree(el.children, astext));
// finally we get the html of the clone
text += clone.outerHTML();
}
}
} else if (el.selection == 'full') {
if (el.domobj.nodeType === 3) {
// full text node selected, get the text
text += jQuery(el.domobj).text();
} else if (el.domobj.nodeType === 1 && el.children) {
// full element node selected, get the html of the node and all children
text += astext ? jQuery(el.domobj).text() : jQuery(el.domobj).outerHTML();
}
}
}
return text;
},
/**
* Get the currently selected markup or false if nothing is selected (or the selection is collapsed)
* @return selected markup
*/
getSelectedMarkup: function () {
var rangeObject = Aloha.Selection.rangeObject;
if (rangeObject.isCollapsed()) {
return false;
}
return this.getFromSelectionTree(rangeObject.getSelectionTree(), false);
},
/**
* Remove the currently selected markup
*/
removeSelectedMarkup: function () {
var rangeObject = Aloha.Selection.rangeObject, newRange;
if (rangeObject.isCollapsed()) {
return;
}
newRange = new Aloha.Selection.SelectionRange();
// remove the selection
this.removeFromSelectionTree(rangeObject.getSelectionTree(), newRange);
// do a cleanup now (starting with the commonancestorcontainer)
newRange.update();
GENTICS.Utils.Dom.doCleanup({'merge' : true, 'removeempty' : true}, Aloha.Selection.rangeObject);
Aloha.Selection.rangeObject = newRange;
// need to set the collapsed selection now
newRange.correctRange();
newRange.update();
newRange.select();
Aloha.Selection.updateSelection();
},
/**
* Recursively remove the selected items, starting with the given level in the selectiontree
* @param selectionTree current level of the selectiontree
* @param newRange new collapsed range to be set after the removal
*/
removeFromSelectionTree: function (selectionTree, newRange) {
// remember the first found partially selected element node (in case we need
// to merge it with the last found partially selected element node)
var firstPartialElement, newdata, i, el, adjacentTextNode, treeLength;
// iterate through the selection tree
for (i = 0, treeLength = selectionTree.length; i < treeLength; i++) {
el = selectionTree[i];
// check the type of selection
if (el.selection == 'partial') {
if (el.domobj.nodeType === 3) {
// partial text node selected, so remove the selected portion
newdata = '';
if (el.startOffset > 0) {
newdata += el.domobj.data.substring(0, el.startOffset);
}
if (el.endOffset < el.domobj.data.length) {
newdata += el.domobj.data.substring(el.endOffset, el.domobj.data.length);
}
el.domobj.data = newdata;
// eventually set the new range (if not done before)
if (!newRange.startContainer) {
newRange.startContainer = newRange.endContainer = el.domobj;
newRange.startOffset = newRange.endOffset = el.startOffset;
}
} else if (el.domobj.nodeType === 1 && el.children) {
// partial element node selected, so do the recursion into the children
this.removeFromSelectionTree(el.children, newRange);
if (firstPartialElement) {
// when the first parially selected element is the same type
// of element, we need to merge them
if (firstPartialElement.nodeName == el.domobj.nodeName) {
// merge the nodes
jQuery(firstPartialElement).append(jQuery(el.domobj).contents());
// and remove the latter one
jQuery(el.domobj).remove();
}
} else {
// remember this element as first partially selected element
firstPartialElement = el.domobj;
}
}
} else if (el.selection == 'full') {
// eventually set the new range (if not done before)
if (!newRange.startContainer) {
adjacentTextNode = GENTICS.Utils.Dom.searchAdjacentTextNode(el.domobj.parentNode, GENTICS.Utils.Dom.getIndexInParent(el.domobj) + 1, false, {'blocklevel' : false});
if (adjacentTextNode) {
newRange.startContainer = newRange.endContainer = adjacentTextNode;
newRange.startOffset = newRange.endOffset = 0;
} else {
newRange.startContainer = newRange.endContainer = el.domobj.parentNode;
newRange.startOffset = newRange.endOffset = GENTICS.Utils.Dom.getIndexInParent(el.domobj) + 1;
}
}
// full node selected, so just remove it (will also remove all children)
jQuery(el.domobj).remove();
}
}
},
/**
* split passed rangeObject without or with optional markup
* @param Aloha.Selection.SelectionRange of the current selection
* @param markup object (jQuery) to insert in between the split elements
* @return void
*/
splitRangeObject: function(rangeObject, markup) {
// UAAAA: first check where the markup can be inserted... *grrrrr*, then decide where to split
// object which is split up
var
splitObject = jQuery(rangeObject.splitObject),
selectionTree, insertAfterObject, followUpContainer;
// update the commonAncestor with the splitObject (so that the selectionTree is correct)
rangeObject.update(rangeObject.splitObject); // set the splitObject as new commonAncestorContainer and update the selectionTree
// calculate the selection tree. NOTE: it is necessary to do this before
// getting the followupcontainer, since getting the selection tree might
// possibly merge text nodes, which would lead to differences in the followupcontainer
selectionTree = rangeObject.getSelectionTree();
// object to be inserted after the splitObject
followUpContainer = this.getSplitFollowUpContainer(rangeObject);
// now split up the splitObject into itself AND the followUpContainer
this.splitRangeObjectHelper(selectionTree, rangeObject, followUpContainer); // split the current object into itself and the followUpContainer
// check whether the followupcontainer is still marked for removal
if (followUpContainer.hasClass('preparedForRemoval')) {
// TODO shall we just remove the class or shall we not use the followupcontainer?
followUpContainer.removeClass('preparedForRemoval');
}
// now let's find the place, where the followUp is inserted afterwards. normally that's the splitObject itself, but in
// some cases it might be their parent (e.g. inside a list, a <p> followUp must be inserted outside the list)
insertAfterObject = this.getInsertAfterObject(rangeObject, followUpContainer);
// now insert the followUpContainer
jQuery(followUpContainer).insertAfter(insertAfterObject); // attach the followUpContainer right after the insertAfterObject
// in some cases, we want to remove the "empty" splitObject (e.g. LIs, if enter was hit twice)
if (rangeObject.splitObject.nodeName.toLowerCase() === 'li' && !Aloha.Selection.standardTextLevelSemanticsComparator(rangeObject.splitObject, followUpContainer)) {
jQuery(rangeObject.splitObject).remove();
}
rangeObject.startContainer = null;
// first check whether the followUpContainer starts with a <br/>
// if so, place the cursor right before the <br/>
var followContents = followUpContainer.contents();
if (followContents.length > 0
&& followContents.get(0).nodeType == 1
&& followContents.get(0).nodeName.toLowerCase() === 'br') {
rangeObject.startContainer = followUpContainer.get(0);
}
if (!rangeObject.startContainer) {
// find a possible text node in the followUpContainer and set the selection to it
// if no textnode is available, set the selection to the followup container itself
rangeObject.startContainer = followUpContainer.textNodes(true, true).first().get(0);
}
if (!rangeObject.startContainer) { // if no text node was found, select the parent object of <br class="aloha-ephemera" />
rangeObject.startContainer = followUpContainer.textNodes(false).first().parent().get(0);
}
if (rangeObject.startContainer) {
// the cursor is always at the beginning of the followUp
rangeObject.endContainer = rangeObject.startContainer;
rangeObject.startOffset = 0;
rangeObject.endOffset = 0;
} else {
rangeObject.startContainer = rangeObject.endContainer = followUpContainer.parent().get(0);
rangeObject.startOffset = rangeObject.endOffset = GENTICS.Utils.Dom.getIndexInParent(followUpContainer.get(0));
}
// finally update the range object again
rangeObject.update();
// now set the selection
rangeObject.select();
},
/**
* method to get the object after which the followUpContainer can be inserted during splitup
* this is a helper method, not needed anywhere else
* @param rangeObject Aloha.Selection.SelectionRange of the current selection
* @param followUpContainer optional jQuery object; if provided the rangeObject will be split and the second part will be insert inside of this object
* @return object after which the followUpContainer can be inserted
*/
getInsertAfterObject: function(rangeObject, followUpContainer) {
var passedSplitObject,i,el;
for (i = 0; i < rangeObject.markupEffectiveAtStart.length; i++) {
el = rangeObject.markupEffectiveAtStart[ i ];
// check if we have already passed the splitObject (some other markup might come before)
if (el === rangeObject.splitObject){
passedSplitObject = true;
}
// if not passed splitObject, skip this markup
if (!passedSplitObject) {
continue;
}
// once we are passed, check if the followUpContainer is allowed to be inserted into the currents el's parent
if (Aloha.Selection.canTag1WrapTag2(jQuery(el).parent()[0].nodeName, followUpContainer[0].nodeName)) {
return el;
}
}
return false;
},
/**
* method to get the html code for a fillUpElement. this is needed for empty paragraphs etc., so that they take up their expected height
* @param splitObject split object (dom object)
* @return fillUpElement HTML Code
*/
getFillUpElement: function(splitObject) {
if (jQuery.browser.msie) {
return false;
} else {
return jQuery('<br class="aloha-cleanme"/>');
}
},
/**
* removes textNodes from passed array, which only contain contentWhiteSpace (e.g. a \n between two tags)
* @param domArray array of domObjects
* @return void
*/
removeElementContentWhitespaceObj: function(domArray) {
var correction = 0,
removeLater = [],
i,
el, removeIndex;
for (i = 0; i < domArray.length; i++) {
el = domArray[i];
if (el.isElementContentWhitespace) {
removeLater[removeLater.length] = i;
}
}
for (i = 0; i < removeLater.length; i++) {
removeIndex = removeLater[i];
domArray.splice(removeIndex - correction, 1);
correction++;
}
},
/**
* recursive method to parallelly walk through two dom subtrees, leave elements before startContainer in first subtree and move rest to other
* @param selectionTree tree to iterate over as contained in rangeObject. must be passed separately to allow recursion in the selection tree, but not in the rangeObject
* @param rangeObject Aloha.Selection.SelectionRange of the current selection
* @param followUpContainer optional jQuery object; if provided the rangeObject will be split and the second part will be insert inside of this object
* @param inBetweenMarkup jQuery object to be inserted between the two split parts. will be either a <br> (if no followUpContainer is passed) OR e.g. a table, which must be inserted between the splitobject AND the follow up
* @return void
*/
splitRangeObjectHelper: function(selectionTree, rangeObject, followUpContainer, inBetweenMarkup) {
if (!followUpContainer) {
Aloha.Log.warn(this, 'no followUpContainer, no inBetweenMarkup, nothing to do...');
}
var fillUpElement = this.getFillUpElement(rangeObject.splitObject),
splitObject = jQuery(rangeObject.splitObject),
startMoving = false,
el, i, completeText, jqObj, mirrorLevel, parent, treeLength;
if (selectionTree.length > 0) {
mirrorLevel = followUpContainer.contents();
// if length of mirrorLevel and selectionTree are not equal, the mirrorLevel must be corrected. this happens, when the mirrorLevel contains whitespace textNodes
if (mirrorLevel.length !== selectionTree.length) {
this.removeElementContentWhitespaceObj(mirrorLevel);
}
for (i = 0, treeLength = selectionTree.length; i < treeLength; i++) {
el = selectionTree[i];
// remove all objects in the mirrorLevel, which are BEFORE the cursor
// OR if the cursor is at the last position of the last Textnode (causing an empty followUpContainer to be appended)
if (
(el.selection === 'none' && startMoving === false) ||
(el.domobj && el.domobj.nodeType === 3 && el === selectionTree[ (selectionTree.length-1) ] && el.startOffset === el.domobj.data.length)
) {
// iteration is before cursor, leave this part inside the splitObject, remove from followUpContainer
// however if the object to remove is the last existing textNode within the followUpContainer, insert a BR instead
// otherwise the followUpContainer is invalid and takes up no vertical space
if (followUpContainer.textNodes().length > 1 || (el.domobj.nodeType === 1 && el.children.length === 0)) {
// note: the second part of the if (el.domobj.nodeType === 1 && el.children.length === 0) covers a very special condition,
// where an empty tag is located right before the cursor when pressing enter. In this case the empty tag would not be
// removed correctly otherwise
mirrorLevel.eq(i).remove();
} else if (GENTICS.Utils.Dom.isSplitObject(followUpContainer[0])) {
if (fillUpElement) {
followUpContainer.html(fillUpElement); // for your zoological german knowhow: ephemera = Eintagsfliege
} else {
followUpContainer.empty();
}
} else {
followUpContainer.empty();
followUpContainer.addClass('preparedForRemoval');
}
continue;
} else {
// split objects, which are AT the cursor Position or directly above
if (el.selection !== 'none') { // before cursor, leave this part inside the splitObject
// TODO better check for selection == 'partial' here?
if (el.domobj && el.domobj.nodeType === 3 && el.startOffset !== undefined) {
completeText = el.domobj.data;
if (el.startOffset > 0) {// first check, if there will be some text left in the splitObject
el.domobj.data = completeText.substr(0, el.startOffset);
} else if (selectionTree.length > 1) { // if not, check if the splitObject contains more than one node, because then it can be removed. this happens, when ENTER is pressed inside of a textnode, but not at the borders
jQuery(el.domobj).remove();
} else { // if the "empty" textnode is the last node left in the splitObject, replace it with a ephemera break
// if the parent is a blocklevel element, we insert the fillup element
parent = jQuery(el.domobj).parent();
if (GENTICS.Utils.Dom.isSplitObject(parent[0])) {
if (fillUpElement) {
parent.html(fillUpElement);
} else {
parent.empty();
}
} else {
// if the parent is no blocklevel element and would be empty now, we completely remove it
parent.remove();
}
}
if (completeText.length - el.startOffset > 0) {
// first check if there is text left to put in the followUpContainer's textnode. this happens, when ENTER is pressed inside of a textnode, but not at the borders
mirrorLevel[i].data = completeText.substr(el.startOffset, completeText.length);
} else if (mirrorLevel.length > 1) {
// if not, check if the followUpContainer contains more than one node, because if yes, the "empty" textnode can be removed
mirrorLevel.eq( (i) ).remove();
} else if (GENTICS.Utils.Dom.isBlockLevelElement(followUpContainer[0])) {
// if the "empty" textnode is the last node left in the followUpContainer (which is a blocklevel element), replace it with a ephemera break
if (fillUpElement) {
followUpContainer.html(fillUpElement);
} else {
followUpContainer.empty();
}
} else {
// if the "empty" textnode is the last node left in a non-blocklevel element, mark it for removal
followUpContainer.empty();
followUpContainer.addClass('preparedForRemoval');
}
}
startMoving = true;
if (el.children.length > 0) {
this.splitRangeObjectHelper(el.children, rangeObject, mirrorLevel.eq(i), inBetweenMarkup);
}
} else {
// remove all objects in the origin, which are AFTER the cursor
if (el.selection === 'none' && startMoving === true) {
// iteration is after cursor, remove from splitObject and leave this part inside the followUpContainer
jqObj = jQuery(el.domobj).remove();
}
}
}
}
} else {
Aloha.Log.error(this, 'can not split splitObject due to an empty selection tree');
}
// and finally cleanup: remove all fillUps > 1
splitObject.find('br.aloha-ephemera:gt(0)').remove(); // remove all elements greater than (gt) 0, that also means: leave one
followUpContainer.find('br.aloha-ephemera:gt(0)').remove(); // remove all elements greater than (gt) 0, that also means: leave one
// remove objects prepared for removal
splitObject.find('.preparedForRemoval').remove();
followUpContainer.find('.preparedForRemoval').remove();
// if splitObject / followUp are empty, place a fillUp inside
if (splitObject.contents().length === 0 && GENTICS.Utils.Dom.isSplitObject(splitObject[0]) && fillUpElement) {
splitObject.html(fillUpElement);
}
if (followUpContainer.contents().length === 0 && GENTICS.Utils.Dom.isSplitObject(followUpContainer[0]) && fillUpElement) {
followUpContainer.html(fillUpElement);
}
},
/**
* returns a jQuery object fitting the passed splitObject as follow up object
* examples,
* - when passed a p it will return an empty p (clone of the passed p)
* - when passed an h1, it will return either an h1 (clone of the passed one) or a new p (if the collapsed selection was at the end)
* @param rangeObject Aloha.RangeObject
* @return void
*/
getSplitFollowUpContainer: function(rangeObject) {
var
tagName = rangeObject.splitObject.nodeName.toLowerCase(),
returnObj, inside, lastObj;
switch(tagName) {
case 'h1':
case 'h2':
case 'h3':
case 'h4':
case 'h5':
case 'h6':
// get the last textnode in the splitobject, but don't consider aloha-cleanme elements
lastObj = jQuery(rangeObject.splitObject).textNodes(':not(.aloha-cleanme)').last()[0];
// special case: when enter is hit at the end of a heading, the followUp should be a <p>
if (lastObj && rangeObject.startContainer === lastObj && rangeObject.startOffset === lastObj.length) {
returnObj = jQuery('<p></p>');
inside = jQuery(rangeObject.splitObject).clone().contents();
returnObj.append(inside);
return returnObj;
}
break;
case 'li':
// TODO check whether the li is the last one
// special case: if enter is hit twice inside a list, the next item should be a <p> (and inserted outside the list)
if (rangeObject.startContainer.nodeName.toLowerCase() === 'br' && jQuery(rangeObject.startContainer).hasClass('aloha-ephemera')) {
returnObj = jQuery('<p></p>');
inside = jQuery(rangeObject.splitObject).clone().contents();
returnObj.append(inside);
return returnObj;
}
// when the li is the last one and empty, we also just return a <p>
if (!rangeObject.splitObject.nextSibling && jQuery.trim(jQuery(rangeObject.splitObject).text()).length === 0) {
returnObj = jQuery('<p></p>');
return returnObj;
}
}
return jQuery(rangeObject.splitObject).clone();
},
/**
* Transform the given domobj into an object with the given new nodeName.
* Preserves the content and all attributes. If a range object is given, also the range will be preserved
* @param domobj dom object to transform
* @param nodeName new node name
* @param range range object
* @api
* @return new object as jQuery object
*/
transformDomObject: function (domobj, nodeName, range) {
// first create the new element
var
jqOldObj = jQuery(domobj),
jqNewObj = jQuery('<' + nodeName + '></' + nodeName + '>'),
i;
// TODO what about events? css properties?
// copy attributes
if (jqOldObj[0].attributes) {
for (i = 0; i < jqOldObj[0].attributes.length; i++) {
jqNewObj.attr(jqOldObj[0].attributes[i].nodeName, jqOldObj[0].attributes[i].nodeValue);
}
}
// copy inline CSS
if (jqOldObj[0].style && jqOldObj[0].style.cssText) {
jqNewObj[0].style.cssText = jqOldObj[0].style.cssText;
}
// now move the contents of the old dom object into the new dom object
jqOldObj.contents().appendTo(jqNewObj);
// finally replace the old object with the new one
jqOldObj.replaceWith(jqNewObj);
// preserve the range
if (range) {
if (range.startContainer == domobj) {
range.startContainer = jqNewObj.get(0);
}
if (range.endContainer == domobj) {
range.endContainer = jqNewObj.get(0);
}
}
return jqNewObj;
},
/**
* String representation
* @return "Aloha.Selection"
*/
toString: function() {
return 'Aloha.Markup';
}
});
Aloha.Markup = new Aloha.Markup();
return Aloha.Markup;
});

View File

@ -1,115 +0,0 @@
/*!
* This file is part of Aloha Editor Project http://aloha-editor.org
* Copyright © 2010-2011 Gentics Software GmbH, aloha@gentics.com
* Contributors http://aloha-editor.org/contribution.php
* Licensed unter the terms of http://www.aloha-editor.org/license.html
*//*
* Aloha Editor is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.*
*
* Aloha Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(
['aloha/core', 'util/class', 'aloha/jquery'],
function( Aloha, Class, jQuery ) {
var
// Aloha = window.Aloha,
// Class = window.Class,
GENTICS = window.GENTICS;
/**
* Message Object
* @namespace Aloha
* @class Message
* @constructor
* @param {Object} data object which contains the parts of the message
* title: the title
* text: the message text to be displayed
* type: one of Aloha.Message.Type
* callback: callback function, which will be triggered after the message was confirmed, closed or accepted
*/
Aloha.Message = Class.extend({
_constructor: function (data) {
this.title = data.title;
this.text = data.text;
this.type = data.type;
this.callback = data.callback;
},
/**
* Returns a textual representation of the message
* @return textual representation of the message
* @hide
*/
toString: function () {
return this.type + ': ' + this.message;
}
});
/**
* Message types enum. Contains all allowed types of messages
* @property
*/
Aloha.Message.Type = {
// reserved for messages
// SUCCESS : 'success',
// INFO : 'info',
// WARN : 'warn',
// CRITICAL : 'critical',
CONFIRM : 'confirm', // confirm dialog, like js confirm()
ALERT : 'alert', // alert dialog like js alert()
WAIT : 'wait' // wait dialog with loading bar. has to be hidden via Aloha.hideMessage()
};
/**
* This is the message line
* @hide
*/
Aloha.MessageLine = Class.extend({
messages: [],
/**
* Add a new message to the message line
* @param message message to add
* @return void
* @hide
*/
add: function(message) {
var messageline = '',
messagesLength = this.messages.length,
i;
// dummy implementation to add a message
this.messages[messagesLength] = message;
while(messagesLength > 4) {
this.messages.shift();
--messagesLength;
}
for ( i = 0; i < messagesLength; i++) {
messageline += this.messages[i].toString() + '<br/>';
}
jQuery('#gtx_aloha_messageline').html(messageline);
}
});
/**
* Message Line Object
* @hide
*/
Aloha.MessageLine = new Aloha.MessageLine();
});

View File

@ -1,10 +0,0 @@
define( {
'floatingmenu.tab.format': 'Formatieren',
'floatingmenu.tab.insert': 'Einf\u00fcgen',
'yes': 'Ja',
'no': 'Nein',
'cancel': 'Abbrechen',
'repository.no_item_found': 'Keinen Eintrag gefunden.',
'repository.loading': 'Es wird geladen',
'repository.no_items_found_yet': 'Noch keine Eintr\u00e4ge gefunden...'
} );

View File

@ -1,10 +0,0 @@
define( {
'floatingmenu.tab.format': 'Mise en page',
'floatingmenu.tab.insert': 'Insertion',
'yes': 'Oui',
'no': 'Non',
'cancel': 'Annuel',
'repository.no_item_found': 'Aucun élément trouvé.',
'repository.loading': 'Chargement',
'repository.no_items_found_yet': 'Aucun élément trouvé...'
} );

View File

@ -1,21 +0,0 @@
define( {
'root': {
'plugin.abbr.floatingmenu.tab.abbr': 'Abbreviation',
'floatingmenu.tab.format': 'Format',
'floatingmenu.tab.insert': 'Insert',
'yes': 'Yes',
'no': 'No',
'cancel': 'Cancel',
'repository.no_item_found': 'No item found.',
'repository.loading': 'Loading',
'repository.no_items_found_yet': 'No items found yet...'
},
'de': true,
'fr': true
/* 'eo': true,
'fi': true,
'it': true,
'pl': true,
'ru': true*/
} );

View File

@ -1,106 +0,0 @@
/*!
* This file is part of Aloha Editor Project http://aloha-editor.org
* Copyright <EFBFBD> 2010-2011 Gentics Software GmbH, aloha@gentics.com
* Contributors http://aloha-editor.org/contribution.php
* Licensed unter the terms of http://www.aloha-editor.org/license.html
*//*
* Aloha Editor is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.*
*
* Aloha Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(
['aloha/jquery'],
function(jQuery, undefined) {
var
$ = jQuery;
return {
_eventHandlers: null,
/**
* Attach a handler to an event
*
* @param {String} eventType A string containing the event name to bind to
* @param {Function} handler A function to execute each time the event is triggered
* @param {Object} scope Optional. Set the scope in which handler is executed
*/
bind: function(eventType, handler, scope) {
this._eventHandlers = this._eventHandlers || {};
if (!this._eventHandlers[eventType]) {
this._eventHandlers[eventType] = [];
}
this._eventHandlers[eventType].push({
handler: handler,
scope: (scope ? scope : window)
});
},
/**
* Remove a previously-attached event handler
*
* @param {String} eventType A string containing the event name to unbind
* @param {Function} handler The function that is to be no longer executed. Optional. If not given, unregisters all functions for the given event.
*/
unbind: function(eventType, handler) {
this._eventHandlers = this._eventHandlers || {};
if (!this._eventHandlers[eventType]) {
return;
}
if (!handler) {
// No handler function given, unbind all event handlers for the eventType
this._eventHandlers[eventType] = [];
} else {
this._eventHandlers[eventType] = $.grep(this._eventHandlers[eventType], function(element) {
if (element.handler === handler) {
return false;
}
return true;
});
}
},
/**
* Execute all handlers attached to the given event type.
* All arguments except the eventType are directly passed to the callback function.
*
* @param (String} eventType A string containing the event name for which the event handlers should be invoked.
*/
trigger: function(eventType) {
this._eventHandlers = this._eventHandlers || {};
if (!this._eventHandlers[eventType]) {
return;
}
// preparedArguments contains all arguments except the first one.
var preparedArguments = [];
$.each(arguments, function(i, argument) {
if (i>0) {
preparedArguments.push(argument);
}
});
$.each(this._eventHandlers[eventType], function(index, element) {
element.handler.apply(element.scope, preparedArguments);
});
},
/**
* Clears all event handlers. Call this method when cleaning up.
*/
unbindAll: function() {
this._eventHandlers = null;
}
};
});

View File

@ -1,276 +0,0 @@
/*!
* This file is part of Aloha Editor Project http://aloha-editor.org
* Copyright © 2010-2011 Gentics Software GmbH, aloha@gentics.com
* Contributors http://aloha-editor.org/contribution.php
* Licensed unter the terms of http://www.aloha-editor.org/license.html
*//*
* Aloha Editor is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.*
*
* Aloha Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(
['aloha/core', 'aloha/jquery', 'util/class', 'aloha/pluginmanager', 'aloha/console'],
function(Aloha, jQuery, Class, PluginManager, console ) {
/**
* Abstract Plugin Object
* @namespace Aloha
* @class Plugin
* @constructor
* @param {String} pluginPrefix unique plugin prefix
*/
var Plugin = Class.extend({
name: null,
/**
* contains the plugin's default settings object
* @cfg {Object} default settings for the plugin
*/
defaults: {},
/**
* contains the plugin's settings object
* @cfg {Object} settings the plugins settings stored in an object
*/
settings: {},
/**
* Names of other plugins which must be loaded in order for this plugin to
* function.
* @cfg {Array}
*/
dependencies: [],
_constructor: function( name ) {
/**
* Settings of the plugin
*/
if (typeof name !== "string") {
console.error('Cannot initialise unnamed plugin, skipping');
} else {
this.name = name;
}
},
/**
* @return true if dependencies satisfied, false otherwise
*/
checkDependencies: function() {
var
dependenciesSatisfied = true,
that = this;
jQuery.each(this.dependencies, function() {
if (!Aloha.isPluginLoaded(this)) {
dependenciesSatisfied = false;
console.error('plugin.' + that.name, 'Required plugin "' + this + '" not found.');
}
});
return dependenciesSatisfied;
},
/**
* Init method of the plugin. Called from Aloha Core to initialize this plugin
* @return void
* @hide
*/
init: function() {},
/**
* Get the configuration settings for an editable obj.
* Handles both conf arrays or conf objects
* <ul>
* <li>Array configuration parameters are:
* <pre>
* "list": {
* config : [ 'b', 'h1' ],
* editables : {
* '#title' : [ ],
* 'div' : [ 'b', 'i' ],
* '.article' : [ 'h1' ]
* }
* }
* </pre>
*
* The hash keys of the editables are css selectors. For a
*
* <pre>
* <div class="article">content</div>
* </pre>
*
* the selectors 'div' and '.article' match and the returned configuration is
*
* <pre>
* [ 'b', 'i', 'h1']
* </pre>
*
* The '#title' object would return an empty configuration.
*
* <pre>
* [ ]
* </pre>
*
* All other objects would get the 'config' configuration. If config is not set
* the plugin default configuration is returned.
*
* <pre>
* [ 'b', 'h1']
* </pre></li>
* <li>Object configuration parameters are :
* <pre>
* "image": {
* config : { 'img': { 'max_width': '50px',
* 'max_height': '50px' }},
* editables : {
* '#title': {},
* 'div': {'img': {}},
* '.article': {'img': { 'max_width': '150px',
* 'max_height': '150px' }}
* }
* }
* </pre>
* The '#title' object would return an empty configuration.<br/>
* The 'div' object would return the default configuration.<br/>
* the '.article' would return :
* <pre>
* {'img': { 'max_width': '150px',
* 'max_height': '150px' }}
* </pre>
* </li>
*
* @param {jQuery} obj jQuery object of an Editable Object
* @return {Array} config A Array with configuration entries
*/
getEditableConfig: function (obj) {
var configObj = null,
configSpecified = false,
that = this;
if ( this.settings.editables ) {
// check if the editable's selector matches and if so add its configuration to object configuration
jQuery.each( this.settings.editables, function (selector, selectorConfig) {
if ( obj.is(selector) ) {
configSpecified = true;
if (selectorConfig instanceof Array) {
configObj = [];
configObj = jQuery.merge(configObj, selectorConfig);
} else if (typeof selectorConfig === "object") {
configObj = {};
for (var k in selectorConfig) {
if ( selectorConfig.hasOwnProperty(k) ) {
if (selectorConfig[k] instanceof Array) {
} else if (typeof selectorConfig[k] === "object") {
configObj[k] = {};
configObj[k] = jQuery.extend(true, configObj[k], that.config[k], selectorConfig[k]);
} else {
configObj[k] = selectorConfig[k];
}
}
}
} else {
configObj = selectorConfig;
}
}
});
}
// fall back to default configuration
if ( !configSpecified ) {
if ( typeof this.settings.config === 'undefined' || !this.settings.config ) {
configObj = this.config;
} else {
configObj = this.settings.config;
}
}
return configObj;
},
/**
* Make the given jQuery object (representing an editable) clean for saving
* @param obj jQuery object to make clean
* @return void
*/
makeClean: function ( obj ) {},
/**
* Make a system-wide unique id out of a plugin-wide unique id by prefixing it with the plugin prefix
* @param id plugin-wide unique id
* @return system-wide unique id
* @hide
* @deprecated
*/
getUID: function(id) {
console.deprecated ('plugin', 'getUID() is deprecated. Use plugin.name instead.');
return this.name;
},
/**
* Localize the given key for the plugin.
* @param key key to be localized
* @param replacements array of replacement strings
* @return localized string
* @hide
* @deprecated
*/
i18n: function(key, replacements) {
console.deprecated ('plugin', 'i18n() is deprecated. Use plugin.t() instead.');
return Aloha.i18n(this, key, replacements);
},
/**
* Return string representation of the plugin, which is the prefix
* @return name
* @hide
* @deprecated
*/
toString: function() {
return this.name;
},
/**
* Log a plugin message to the logger
* @param level log level
* @param message log message
* @return void
* @hide
* @deprecated
*/
log: function (level, message) {
console.deprecated ('plugin', 'log() is deprecated. Use Aloha.console instead.');
console.log(level, this, message);
}
});
/**
* Static method used as factory to create plugins.
*
* @param {String} pluginName name of the plugin
* @param {Object} definition definition of the plugin, should have at least an "init" and "destroy" method.
*/
Plugin.create = function(pluginName, definition) {
var pluginInstance = new ( Plugin.extend( definition ) )( pluginName );
pluginInstance.settings = jQuery.extendObjects( true, pluginInstance.defaults, Aloha.settings[pluginName] );
PluginManager.register( pluginInstance );
return pluginInstance;
};
return Plugin;
});

View File

@ -1,146 +0,0 @@
/*!
* This file is part of Aloha Editor Project http://aloha-editor.org
* Copyright © 2010-2011 Gentics Software GmbH, aloha@gentics.com
* Contributors http://aloha-editor.org/contribution.php
* Licensed unter the terms of http://www.aloha-editor.org/license.html
*//*
* Aloha Editor is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.*
*
* Aloha Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Do not add dependencies that require depend on aloha/core
define(
[ 'aloha/jquery', 'util/class' ],
function( jQuery, Class ) {
/**
* The Plugin Manager controls the lifecycle of all Aloha Plugins.
*
* @namespace Aloha
* @class PluginManager
* @singleton
*/
return new (Class.extend({
plugins: {},
/**
* Initialize all registered plugins
* @return void
* @hide
*/
init: function(next, userPlugins) {
var
me = this,
globalSettings = ( Aloha && Aloha.settings ) ? Aloha.settings.plugins||{}: {},
i,
plugin,
pluginName;
// Global to local settings
for ( pluginName in globalSettings ) {
if ( globalSettings.hasOwnProperty( pluginName ) ) {
plugin = this.plugins[pluginName] || false;
if ( plugin ) {
plugin.settings = globalSettings[ pluginName ] || {};
}
}
}
// Default: All loaded plugins are enabled
if ( !userPlugins.length ) {
for ( pluginName in this.plugins ) {
if ( this.plugins.hasOwnProperty( pluginName ) ) {
userPlugins.push( pluginName );
}
}
}
// Enable Plugins specified by User
for ( i=0; i < userPlugins.length; ++i ) {
pluginName = userPlugins[ i ];
plugin = this.plugins[ pluginName ]||false;
if ( plugin ) {
plugin.settings = plugin.settings || {};
if ( typeof plugin.settings.enabled === 'undefined' ) {
plugin.settings.enabled = true;
}
if ( plugin.settings.enabled ) {
if ( plugin.checkDependencies() ) {
plugin.init();
}
}
}
}
next();
},
/**
* Register a plugin
* @param {Plugin} plugin plugin to register
*/
register: function( plugin ) {
if ( !plugin.name ) {
throw new Error( 'Plugin does not have an name.' );
}
if ( this.plugins[ plugin.name ]) {
throw new Error( 'Already registered the plugin "' + plugin.name + '"!' );
}
this.plugins[ plugin.name ] = plugin;
},
/**
* Pass the given jQuery object, which represents an editable to all plugins, so that they can make the content clean (prepare for saving)
* @param obj jQuery object representing an editable
* @return void
* @hide
*/
makeClean: function(obj) {
var i, plugin;
// iterate through all registered plugins
for ( plugin in this.plugins ) {
if ( this.plugins.hasOwnProperty( plugin ) ) {
if (Aloha.Log.isDebugEnabled()) {
Aloha.Log.debug(this, 'Passing contents of HTML Element with id { ' + obj.attr('id') +
' } for cleaning to plugin { ' + plugin + ' }');
}
this.plugins[plugin].makeClean(obj);
}
}
},
/**
* Expose a nice name for the Plugin Manager
* @hide
*/
toString: function() {
return 'pluginmanager';
}
}))();
});

File diff suppressed because it is too large Load Diff

View File

@ -1,59 +0,0 @@
/*!
* This file is part of Aloha Editor
* Author & Copyright (c) 2010 Gentics Software GmbH, aloha@gentics.com
* Licensed unter the terms of http://www.aloha-editor.com/license.html
*/
/**
* Registry base class.
* TODO: document that it also contains Observable.
*
*/
define(
['aloha/jquery', 'aloha/observable'],
function(jQuery, Observable) {
return Class.extend(Observable, {
_entries: null,
_constructor: function() {
this._entries = {};
},
/**
* @event register
* @param entry
* @param id
*/
register: function(id, entry) {
this._entries[id] = entry;
this.trigger('register', entry, id);
},
/**
* @event unregister
* @param odEntry
* @param id
*/
unregister: function(id) {
var oldEntry = this._entries[id];
delete this._entries[id];
this.trigger('unregister', oldEntry, id);
},
get: function(id) {
return this._entries[id];
},
has: function(id) {
return (this._entries[id] ? true : false);
},
getEntries: function() {
// clone the entries so the user does not accidentally modify our _entries object.
return jQuery.extend({}, this._entries);
}
});
});

Some files were not shown because too many files have changed in this diff Show More