1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-08 02:10:24 +00:00

[aloha] upgraded to 0.22.7 and added textcolor plugin

* textcolor: fixed plugin bugs, added translation for zh
* image: fixed default.jpg src bug
* added 'ru' support for seaf edit
* rm aloha-0.22.3 and ununsed files in aloha-0.22.7
This commit is contained in:
llj
2013-01-15 14:48:04 +08:00
parent 680b5e17cc
commit 720ac28c22
295 changed files with 65268 additions and 4430 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -1,88 +0,0 @@
/*
* jsTree browser theme 1.0
* Supported features: dots/no-dots, icons/no-icons, focused, loading
* Supported plugins: ui (hovered, clicked), checkbox, contextmenu, search
*/
.jstree li a {
display: inline-block;
padding: 4px;
border: 1px solid transparent;
}
.jstree-browser li > ins {
cursor: pointer;
background: url(../img/arrow-315-medium.png) no-repeat center center;
}
/*
.jstree-browser ins { background-image:url("xd.png"); background-repeat:no-repeat; background-color:transparent; }
.jstree-browser li { background-position:-90px 0; background-repeat:repeat-y; border-left: 1px dotted #ccc; }
*/
.jstree-browser li {
margin-left: 10px;
padding-left: 5px;
border-left: 1px dotted #ccc;
}
.jstree-browser li.jstree-last { background:transparent; }
.jstree-browser > ul:first-child > li { border-left-width: 0; }
.jstree-browser li > ins {
background: transparent no-repeat center center;
opacity: 0.7;
filter: alpha(opacity=70);
}
.jstree-browser li > ins:hover {
opacity: 1;
filter: alpha(opacity=100);
}
.jstree-browser li.jstree-open > ins {
background-image: url(../img/arrow-315-medium.png);
opacity: 1;
filter: alpha(opacity=100);
}
.jstree-browser li.jstree-closed > ins {
background-image: url(../img/arrow-000-medium.png);
}
.jstree-browser li.jstree-leaf > ins {
background-image: url(../img/control-stop-square-small.png);
}
/*
.jstree-browser .jstree-hovered { background:#f9d53f; border:1px solid #f7b940; }
.jstree-browser .jstree-clicked { background:#88c7ea; border:1px solid #48a3d2; }
*/
.jstree-browser .jstree-hovered {
color: #303539;
}
.jstree-browser .jstree-clicked {
}
.jstree-browser .jstree-hovered.jstree-clicked {
}
/* Folder */
.jstree-browser a .jstree-icon {
background: url(../img/folder-horizontal-open.png) no-repeat center center;
cursor: pointer;
}
.jstree-browser a.jstree-loading .jstree-icon { background:url(../img/throbber.gif) center center no-repeat !important; }
.jstree-browser a.jstree-clicked .jstree-icon {
background-image: url(../img/folder-open.png);
}
/* IE6 BEGIN */
/*
.jstree-browser li,
.jstree-browser ins,
#vakata-dragged.jstree-browser .jstree-invalid,
#vakata-dragged.jstree-browser .jstree-ok,
#jstree-marker.jstree-browser { _background-image:url("d.gif"); }
.jstree-browser .jstree-open ins { _background-position:-72px 0; }
.jstree-browser .jstree-closed ins { _background-position:-54px 0; }
.jstree-browser .jstree-leaf ins { _background-position:-36px 0; }
.jstree-browser a ins.jstree-icon { _background-position:-56px -19px; }
#vakata-contextmenu.jstree-browser-context ins { _display:none; }
#vakata-contextmenu.jstree-browser-context li { _zoom:1; }
.jstree-browser .jstree-undetermined a .jstree-checkbox { _background-position:-20px -19px; }
.jstree-browser .jstree-checked a .jstree-checkbox { _background-position:-38px -19px; }
.jstree-browser .jstree-unchecked a .jstree-checkbox { _background-position:-2px -19px; }
*/
/* IE6 END */

View File

@@ -1,756 +0,0 @@
/*Grid*/
.ui-jqgrid {position: relative; font-size:11px; border: 0;}
.ui-jqgrid .ui-jqgrid-view {position: relative;left:0px; top: 0px; padding: .0em;}
/* caption*/
.ui-jqgrid .ui-jqgrid-titlebar {padding: .3em .2em .2em .3em; position: relative; border-left: 0px none;border-right: 0px none; border-top: 0px none;}
.ui-jqgrid .ui-jqgrid-title { float: left; margin: .1em 0 .2em; }
.ui-jqgrid .ui-jqgrid-titlebar-close { position: absolute;top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height:18px;}.ui-jqgrid .ui-jqgrid-titlebar-close span { display: block; margin: 1px; }
.ui-jqgrid .ui-jqgrid-titlebar-close:hover { padding: 0; }
/* header*/
.ui-jqgrid .ui-jqgrid-hdiv {position: relative; margin: 0em;padding: 0em; overflow-x: hidden; overflow-y: auto; border-left: 0px none; border-top : 0px none; border-right : 0px none;}
.ui-jqgrid .ui-jqgrid-hbox {float: left; padding-right: 20px;}
.ui-jqgrid .ui-jqgrid-htable {table-layout:fixed;margin:0em;}
.ui-jqgrid .ui-jqgrid-htable th {height:22px;padding: 2px 2px 0 2px;}
.ui-jqgrid .ui-jqgrid-htable th div {overflow: hidden; position:relative; height:17px;}
.ui-th-column, .ui-jqgrid .ui-jqgrid-htable th.ui-th-column {overflow: hidden;white-space: nowrap;text-align:center;border-top : 0px none;border-bottom : 0px none;}
.ui-th-ltr, .ui-jqgrid .ui-jqgrid-htable th.ui-th-ltr {border-left : 0px none;}
.ui-th-rtl, .ui-jqgrid .ui-jqgrid-htable th.ui-th-rtl {border-right : 0px none;}
.ui-jqgrid .ui-th-div-ie {white-space: nowrap; zoom :1; height:17px;}
.ui-jqgrid .ui-jqgrid-resize {height:20px;position: relative; cursor :e-resize;display: inline;overflow: hidden;}
.ui-jqgrid .ui-grid-ico-sort {overflow:hidden;position:absolute;display:inline; cursor: pointer;}
.ui-jqgrid .ui-icon-asc {margin-top:-3px; height:12px;}
.ui-jqgrid .ui-icon-desc {margin-top:3px;height:12px;}
.ui-jqgrid .ui-i-asc {margin-top:0px;height:16px;}
.ui-jqgrid .ui-i-desc {margin-top:0px;margin-left:13px;height:16px;}
.ui-jqgrid tr.ui-search-toolbar th { border-top-width: 1px; border-top-color: inherit; border-top-style: ridge }
tr.ui-search-toolbar input {margin: 1px 0px 0px 0px}
tr.ui-search-toolbar select {margin: 1px 0px 0px 0px}
/* body */
.ui-jqgrid .ui-jqgrid-bdiv {position: relative; margin: 0em; padding:0; overflow: auto; text-align:left;}
.ui-jqgrid .ui-jqgrid-btable {table-layout:fixed; margin:0em;}
.ui-jqgrid tr.jqgrow { outline-style: none; background: none; }
.ui-jqgrid tr.jqgrow td {font-weight: normal; overflow: hidden; white-space: pre; height: 22px;padding: 0 2px 0 2px;border-bottom-width: 1px; border-bottom-color: inherit; border-bottom-style: solid;}
.ui-jqgrid tr.jqgfirstrow td {padding: 0 2px 0 2px;border-right-width: 1px; border-right-style: solid;}
.ui-jqgrid tr.jqgroup td {font-weight: normal; overflow: hidden; white-space: pre; height: 22px;padding: 0 2px 0 2px;border-bottom-width: 1px; border-bottom-color: inherit; border-bottom-style: solid;}
.ui-jqgrid tr.jqfoot td {font-weight: bold; overflow: hidden; white-space: pre; height: 22px;padding: 0 2px 0 2px;border-bottom-width: 1px; border-bottom-color: inherit; border-bottom-style: solid;}
.ui-jqgrid tr.ui-row-ltr td {text-align:left;border-right-width: 1px; border-right-color: inherit; border-right-style: solid;}
.ui-jqgrid tr.ui-row-rtl td {text-align:right;border-left-width: 1px; border-left-color: inherit; border-left-style: solid;}
.ui-jqgrid td.jqgrid-rownum { padding: 0 2px 0 2px; margin: 0px; border: 0px none;}
.ui-jqgrid .ui-jqgrid-resize-mark { width:2px; left:0; background-color:#777; cursor: e-resize; cursor: col-resize; position:absolute; top:0; height:100px; overflow:hidden; display:none; border:0 none;}
/* footer */
.ui-jqgrid .ui-jqgrid-sdiv {position: relative; margin: 0em;padding: 0em; overflow: hidden; border-left: 0px none; border-top : 0px none; border-right : 0px none;}
.ui-jqgrid .ui-jqgrid-ftable {table-layout:fixed; margin-bottom:0em;}
.ui-jqgrid tr.footrow td {font-weight: bold; overflow: hidden; white-space:nowrap; height: 21px;padding: 0 2px 0 2px;border-top-width: 1px; border-top-color: inherit; border-top-style: solid;}
.ui-jqgrid tr.footrow-ltr td {text-align:left;border-right-width: 1px; border-right-color: inherit; border-right-style: solid;}
.ui-jqgrid tr.footrow-rtl td {text-align:right;border-left-width: 1px; border-left-color: inherit; border-left-style: solid;}
/* Pager*/
.ui-jqgrid .ui-jqgrid-pager { border-left: 0px none;border-right: 0px none; border-bottom: 0px none; margin: 0px; padding: 0px; position: relative; height: 40px;white-space: nowrap;overflow: hidden;}
.ui-jqgrid .ui-pager-control {position: relative;}
.ui-jqgrid .ui-pg-table {position: relative; padding-bottom:2px; width:auto; margin: 0em;}
.ui-jqgrid .ui-pg-table td {font-weight:normal; vertical-align:middle; padding:1px;}
.ui-jqgrid .ui-pg-button { height:19px;}
.ui-jqgrid .ui-pg-button span { display: block; margin: 1px; float:left;}
.ui-jqgrid .ui-pg-button span.ui-separator { display: none;}
.ui-jqgrid .ui-pg-button:hover { padding: 0px; }
.ui-jqgrid .ui-state-disabled:hover {padding:1px;}
.ui-jqgrid .ui-pg-input { height:13px;font-size:.8em; margin: 0em;}
.ui-jqgrid .ui-pg-selbox {font-size:.8em; line-height:18px; display:block; height:18px; margin: 0em;}
.ui-jqgrid .ui-separator {display: none; height: 18px; border-left: 1px solid #ccc ; border-right: 1px solid #ccc ; margin: 1px; float: right;}
.ui-jqgrid .ui-paging-info {font-weight: normal; height: 19px; margin: 0; line-height: 1em; padding-right: 10px;}
.ui-jqgrid .ui-jqgrid-pager .ui-pg-div {padding:1px 0;float:left;list-style-image:none;list-style-position:outside;list-style-type:none;position:relative;}
.ui-jqgrid .ui-jqgrid-pager .ui-pg-button { cursor:pointer; }
.ui-jqgrid .ui-jqgrid-pager .ui-pg-div span.ui-icon {float:left;margin:0 2px;}
.ui-jqgrid td input, .ui-jqgrid td select .ui-jqgrid td textarea { margin: 0em;}
.ui-jqgrid td textarea {width:auto;height:auto;}
.ui-jqgrid .ui-jqgrid-toppager {border-left: 0px none;border-right: 0px none; border-top: 0px none; margin: 0px; padding: 0px; position: relative; height: 25px;white-space: nowrap;overflow: hidden;}
/*subgrid*/
.ui-jqgrid .ui-jqgrid-btable .ui-sgcollapsed span {display: block;}
.ui-jqgrid .ui-subgrid {margin:0em;padding:0em; width:100%;}
.ui-jqgrid .ui-subgrid table {table-layout: fixed;}
.ui-jqgrid .ui-subgrid tr.ui-subtblcell td {height:18px;border-right-width: 1px; border-right-color: inherit; border-right-style: solid;border-bottom-width: 1px; border-bottom-color: inherit; border-bottom-style: solid;}
.ui-jqgrid .ui-subgrid td.subgrid-data {border-top: 0px none;}
.ui-jqgrid .ui-subgrid td.subgrid-cell {border-width: 0px 0px 1px 0px;}
.ui-jqgrid .ui-th-subgrid {height:20px;}
/* loading */
.ui-jqgrid .loading {position: absolute; top: 45%;left: 45%;width: auto;z-index:101;padding: 6px; margin: 5px;text-align: center;font-weight: bold;display: none;border-width: 2px;}
.ui-jqgrid .jqgrid-overlay {display:none;z-index:100;}
* html .jqgrid-overlay {
width: ~"expression(this.parentNode.offsetWidth+'px')";
height: ~"expression(this.parentNode.offsetHeight+'px')";
}
* .jqgrid-overlay iframe {
position:absolute;
top:0;
left:0;
z-index:-1;
width: ~"expression(this.parentNode.offsetWidth+'px')";
height: ~"expression(this.parentNode.offsetHeight+'px')";
}
/* Tree Grid */
.ui-jqgrid .tree-wrap {position: relative; height: 18px; float: left; overflow: hidden; white-space: nowrap;}
.ui-jqgrid .tree-minus {position: absolute; height: 18px; width: 18px; overflow: hidden;}
.ui-jqgrid .tree-plus {position: absolute; height: 18px; width: 18px; overflow: hidden;}
.ui-jqgrid .tree-leaf {position: absolute; height: 18px; width: 18px; overflow: hidden;}
.ui-jqgrid .treeclick {cursor: pointer;}
/* moda dialog */
.ui-jqgrid .ui-jqgrid-resize-ltr {float: right; margin: -2px -2px -2px 0px;}
.ui-jqgrid .ui-jqgrid-resize-rtl {float: left; margin: -2px 0px -1px -3px;}
/* caption */
.ui-jqgrid .ui-jqgrid-titlebar {
position: relative;
border-radius-topleft: 0;
-moz-border-radius-topleft: 0;
-webkit-border-top-left-radius: 0;
border-radius-topright: 2px;
-moz-border-radius-topright: 2px;
-webkit-border-top-right-radius: 2px;
border: 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),
color-stop(1.00, #4c4f54)
);
background-image: -moz-linear-gradient(
center top,
#6c6f74 0%,
#4c4f54 5%,
#3f4448 10%,
#383d41 45%,
#303539 50%,
#33363b 95%,
#4c4f54 100%
);
filter: progid:DXImageTransform.Microsoft.Gradient(
startColorstr='#383d41',
endColorstr='#303539',
gradientType='0'
);
color: #ddd;
text-shadow: 0 0 4px #23262b;
font-weight: bold;
font-size: 13px;
line-height: 2em;
white-space: nowrap;
}
.ui-jqgrid .ui-jqgrid-title {
float: none;
display: block;
}
.ui-jqgrid .ui-jqgrid-titlebar-close {display: none;}
/* header */
.ui-jqgrid .ui-jqgrid-hdiv {
background: #303539;
}
.ui-jqgrid .ui-jqgrid-htable {
border: 0;
background: #fff;
}
.ui-jqgrid .ui-jqgrid-htable th {
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),
color-stop(1.00, #4c4f54)
);
background-image: -moz-linear-gradient(
center top,
#6c6f74 0%,
#4c4f54 5%,
#3f4448 10%,
#383d41 45%,
#303539 50%,
#33363b 95%,
#4c4f54 100%
);
filter: progid:DXImageTransform.Microsoft.Gradient(
startColorstr='#383d41',
endColorstr='#303539',
gradientType='0'
);
color: #ddd;
text-shadow: 0 0 4px #23262b;
font-weight: bold;
font-size: 13px;
}
.ui-jqgrid .ui-jqgrid-htable th:hover {
background-color: #3f4448;
background-image: -webkit-gradient(
linear,
center top,
center bottom,
color-stop(0.00, #6c6f74),
color-stop(0.05, #4c4f54),
color-stop(0.45, #3f4448),
color-stop(0.50, #383d41),
color-stop(1.00, #3f4448)
);
background-image: -moz-linear-gradient(
center top,
#6c6f74 0%,
#4c4f54 5%,
#3f4448 45%,
#383d41 50%,
#3f4448 100%
);
filter: progid:DXImageTransform.Microsoft.Gradient(
startColorstr='#4c4f54',
endColorstr='#3f4448',
gradientType='0'
);
color: #fff;
text-shadow: 0 0 2px gba(0, 0, 0, .5);
}
.ui-jqgrid .ui-jqgrid-htable th:hover .ui-grid-ico-sort {
opacity: 1;
filter: alpha(opacity=100);
}
.ui-th-ltr, .ui-jqgrid .ui-jqgrid-htable th.ui-th-ltr {
border: 1px solid #33363b;
border-right: 1px solid #3f4448;
}
.ui-jqgrid-resize {
background: #fff;
opacity: 0.10;
filter: alpha(opacity=10);
text-indent: 0;
}
.ui-jqgrid-resize:hover {
opacity: 0.5;
filter: alpha(opacity=50);
}
.ui-jqgrid .s-ico {
display: none;
}
.ui-jqgrid .ui-grid-ico-sort {
display: none;
}
.ui-jqgrid-sortable {
cursor: default;
}
.ui-jqgrid .ui-icon-asc {
background: url(../img/sort-alphabet.png) no-repeat center center;
}
.ui-jqgrid .ui-icon-desc {
background: url(../img/sort-alphabet-descending.png) no-repeat center center;
}
.ui-jqgrid .ui-grid-ico-sort.ui-state-disabled {
display: none;
}
.ui-th-column, .ui-jqgrid .ui-jqgrid-htable th.ui-th-column {
text-align: left;
text-indent: 10px;
line-height: 1.5em;
}
/* body */
.ui-jqgrid .ui-jqgrid-btable {
border: 0;
}
.ui-jqgrid .ui-jqgrid-bdiv {
background: #fff;
}
.ui-jqgrid tr.jqgfirstrow td {
border: 0;
}
.ui-jqgrid tr.jqgrow td{
border: 1px solid #f5f5f5;
border-left: 0;
border-right: 0;
padding: 2px;
color: #636363;
font-size: 12px;
cursor: default;
}
.ui-jqgrid tr.jqgrow:hover td {
color: #303539;
background: #f5f5f5;
}
.ui-jqgrid tr.ui-row-ltr td {
border-width: 1px;
vertical-align: middle;
}
/* Pager */
.ui-jqgrid .ui-pg-table {
border: 0;
}
.ui-jqgrid .ui-pg-table td {
padding: 5px;
border: 0;
color: #ddd;
background-color: #303539;
}
.ui-jqgrid .ui-pg-table td.ui-pg-button {
opacity: 1 !important;
filter: alpha(opacity=100);
}
.ui-jqgrid .ui-jqgrid-pager {
border: 0;
border-top: 1px solid #33363b;
color: #ddd;
text-shadow: 0 0 4px #23262b;
font-weight: bold;
font-size: 13px;
}
.ui-jqgrid .ui-pg-button {
width: 16px;
height: 16px;
opacity: 0.6;
filter: alpha(opacity=60);
}
.ui-jqgrid .ui-pg-button:hover {
padding: 5px;
opacity: 1;
filter: alpha(opacity=100);
}
.ui-jqgrid .ui-pg-button.ui-state-disabled {
cursor: default;
}
.ui-jqgrid .ui-pg-button.ui-state-disabled .ui-icon {
opacity: 0.10;
filter: alpha(opacity=10);
}
.ui-jqgrid .ui-pg-button .ui-icon {
display: inline-block;
background-position: center center;
background-repeat: no-repeat;
width: 16px;
height: 16px;
}
.ui-jqgrid .ui-pg-button .ui-icon-seek-next {
background-image: url(../img/arrow.png);
}
.ui-jqgrid .ui-pg-button .ui-icon-seek-end {
background-image: url(../img/arrow-stop.png);
}
.ui-jqgrid .ui-pg-button .ui-icon-seek-prev {
background-image: url(../img/arrow-180.png);
}
.ui-jqgrid .ui-pg-button .ui-icon-seek-first {
background-image: url(../img/arrow-stop-180.png);
}
.ui-jqgrid .ui-pg-input {
width: 20px;
height: 20px;
font-size: 11px;
margin: 0;
background-color: #fff;
background-image: -webkit-gradient(
linear,
left top,
left bottom,
color-stop(0.00, #bbb),
color-stop(0.10, #ddd),
color-stop(0.30, #eee),
color-stop(1.00, #fff)
);
background-image: -moz-linear-gradient(
center top,
#ccc 0%,
#ddd 10%,
#eee 30%,
#fff 100%
);
filter: progid:DXImageTransform.Microsoft.Gradient(
startColorstr='#dddddd',
endColorstr='#ffffff',
gradientType='0'
);
border-width: 0;
border-radius: 2px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
color: #777;
text-align: center;
}
/* subgrid */
/* loading */
.ui-jqgrid .loading {
position: absolute;
top: 45%;
left: 45%;
width: auto;
z-index:101;
padding: 6px 6px 6px 20px;
margin: 5px;
text-align: center;
display: none;
border-width: 2px;
font-weight: normal;
color: #777;
background: url(../img/throbber.gif) no-repeat left center;
}
.ui-jqgrid .jqgrid-overlay {display:none; z-index:100;}
/**
*
* Modal
*
**********************************************************************/
.repository-browser-modal-overlay {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
height: 100%;
width: 100%;
z-index: 999;
background-image: -webkit-radial-gradient(
rgba(127, 127, 127, 0.5) 0%,
rgba(127, 127, 127, 0.6) 40%,
rgba(0, 0, 0, 0.7) 100%
);
background-image: -moz-radial-gradient(
rgba(127, 127, 127, 0.5),
rgba(127, 127, 127, 0.6) 40%,
rgba(0, 0, 0, 0.7)
);
}
div.repository-browser-modal-window {
position: fixed;
top: 0;
left: 0;
z-index: 9999;
font-family: Arial, sans-serif;
}
.repository-browser-modal-window .ui-widget {
font-family: Arial, sans-serif;
}
/**
*
* ui-layout
*
**********************************************************************/
.ui-layout-resizer {
background-color: #303539;
background-image: -webkit-gradient(
linear,
left center,
right center,
color-stop(0.00, #303539),
color-stop(0.30, #4c4f54),
color-stop(0.70, #6c6f74),
color-stop(1.00, #303539)
);
background-image: -moz-linear-gradient(
left center,
#303539 0%,
#4c4f54 30%,
#6c6f74 70%,
#303539 100%
);
filter: progid:DXImageTransform.Microsoft.Gradient(
startColorstr='#4c4f54',
endColorstr='#303539',
gradientType='0'
);
}
.ui-layout-toggler {
border: 1px solid #355ea0;
background-color: #508ac9;
background-image: -webkit-gradient(
linear,
right center,
left center,
color-stop(0.00, #81add2),
color-stop(0.10, #5693cc),
color-stop(0.45, #5b9acf),
color-stop(0.60, #508ac9),
color-stop(1.00, #456eb0)
);
background-image: -moz-linear-gradient(
right center,
#81add2 0%,
#5693cc 10%,
#5b9acf 45%,
#508ac9 60%,
#456eb0 100%
);
filter: progid:DXImageTransform.Microsoft.Gradient(
startColorstr='#81add2',
endColorstr='#456eb0',
gradientType='0'
);
}
.ui-layout-toggler:hover {
opacity: 0.5;
filter: alpha(opacity=50);
}
.ui-draggable-dragging {
opacity: 0.85;
/* filter: alpha(opacity=85); */
}
.repository-browser-shadow {
background: transparent;
-moz-box-shadow: 0 0 10px rgba(0,0,0,0.2);
-webkit-box-shadow: 0 0 10px rgba(0,0,0,0.2);
box-shadow: 0 0 10px rgba(0,0,0,0.2);
}
.repository-browser-rounded-top {
border-radius-topleft: 2px;
-moz-border-radius-topleft: 2px;
-webkit-border-top-left-radius: 2px;
border-radius-topright: 2px;
-moz-border-radius-topright: 2px;
-webkit-border-top-right-radius: 2px;
}
.repository-browser-grid {
height: 400px;
border: 1px solid #53565b;
border: 1px solid rgba(0,0,0,0.2);
text-align: left;
line-height: 1.5em;
}
.repository-browser-clear {
float: none;
clear: both;
}
/**
* List
*****************************************************************************/
.repository-browser-list a {
color: #777;
text-decoration: none;
}
.repository-browser-list .ui-state-hover a {
color: #fff;
text-decoration: underline;
}
.repository-browser-list-altrow {
background: rgba(0, 0, 0, 0.05);
}
.repository-browser-list-resizable {}
.repository-browser-list-icon {
width: 100%;
height: 16px;
background: transparent no-repeat center center;
}
.repository-browser-icon-page {
background: url(../img/gcn-icons/gcn-icon-page.gif) no-repeat center center;
}
.repository-browser-icon-file {
background: url(../img/gcn-icons/gcn-icon-file.gif) no-repeat center center;
}
.repository-browser-icon-image {
background: url(../img/gcn-icons/gcn-icon-image.gif) no-repeat center center;
}
.repository-browser-grab-handle {
cursor: default;
}
.repository-browser-btns {
position: absolute;
top: 5px;
right: 5px;
}
.repository-browser-btn {
display: inline-block;
float: left;
margin: -1px 5px 0 0;
padding: 0 8px;
border: 1px solid #355ea0;
background-color: #508ac9;
background-image: -webkit-gradient(
linear,
center top,
center bottom,
color-stop(0.00, #81add2),
color-stop(0.10, #5693cc),
color-stop(0.45, #5b9acf),
color-stop(0.60, #508ac9),
color-stop(1.00, #456eb0)
);
background-image: -moz-linear-gradient(
center top,
#81add2 0%,
#5693cc 10%,
#5b9acf 45%,
#508ac9 60%,
#456eb0 100%
);
filter: progid:DXImageTransform.Microsoft.Gradient(
startColorstr='#81add2',
endColorstr='#456eb0',
gradientType='0'
);
border-radius: 2px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
opacity: 0.8;
filter: alpha(opacity=80);
line-height: 22px;
color: #fff;
text-shadow: 0 0 4px #23262b;
}
.repository-browser-btn:hover {
opacity: 0.9;
filter: alpha(opacity=90);
}
.repository-browser-btn.repository-browser-pressed {
opacity: 1;
filter: alpha(opacity=100);
}
.repository-browser-btns input {
float: left;
height: 15px;
padding: 4px 2px;
border: 1px solid #ccc;
background-color: #fff;
background-image: -webkit-gradient(
linear,
left top,
left bottom,
color-stop(0.00, #bbb),
color-stop(0.10, #ddd),
color-stop(0.30, #eee),
color-stop(1.00, #fff)
);
background-image: -moz-linear-gradient(
center top,
#ccc 0%,
#ddd 10%,
#eee 30%,
#fff 100%
);
filter: progid:DXImageTransform.Microsoft.Gradient(
startColorstr='#dddddd',
endColorstr='#ffffff',
gradientType='0'
);
color: #555;
font-size: 13px;
line-height: 1.5em;
}
.repository-browser-search-btn {
border-radius-topleft: 0;
-moz-border-radius-topleft: 0;
-webkit-border-top-left-radius: 0;
border-radius-bottomleft: 0;
-moz-border-radius-bottomleft: 0;
-webkit-border-bottom-left-radius: 0;
cursor: pointer;
}
.repository-browser-search-icon {
width: 16px;
height: 22px;
display: inline-block;
background: url(../img/magnifier-left.png) no-repeat center center;
vertical-align: middle;
}
.repository-browser-close-btn {
margin-right: 0;
}
/**
* Tree
*****************************************************************************/
.repository-browser-tree {
overflow: scroll;
padding-left: 4px;
background: #fff;
font-size: 12px;
}
.repository-browser-tree-header {
overflow: hidden;
position: relative;
border-radius-topleft: 2px;
-moz-border-radius-topleft: 2px;
-webkit-border-top-left-radius: 2px;
height: 18px;
padding: 8px;
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),
color-stop(1.00, #4c4f54)
);
background-image: -moz-linear-gradient(
center top,
#6c6f74 0%,
#4c4f54 5%,
#3f4448 10%,
#383d41 45%,
#303539 50%,
#33363b 95%,
#4c4f54 100%
);
filter: progid:DXImageTransform.Microsoft.Gradient(
startColorstr='#383d41',
endColorstr='#303539',
gradientType='0'
);
color: #ddd;
text-shadow: 0 0 4px #23262b;
font-weight: bold;
font-size: 13px;
line-height: 1.5em;
white-space: nowrap;
}
/**
* List icons
*****************************************************************************/
.repository-browser-icon {
width: 20px;
height: 20px;
margin: 0 auto;
background-repeat: no-repeat;
background-position: center center
}
/**
*
* Customize from here:
*
*****************************************************************************/
.repository-browser-search-field,
.repository-browser-search-btn {
display: none;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 454 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 589 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 449 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 658 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 665 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 590 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 511 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 647 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 736 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 594 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 599 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,32 +0,0 @@
define("RepositoryBrowser",["Class","jquery","PubSub","repository-browser-i18n-"+(window&&window.__DEPS__&&window.__DEPS__.lang||"en"),"jstree","jqgrid","jquery-layout"],function(m,d,n,o){function p(a){a.each(function(){d(this).attr("unselectable","on").css({"-moz-user-select":"none","-webkit-user-select":"none","user-select":"none"}).each(function(){this.onselectstart=function(){return!1}})})}var j=[],k=0,g=(new Date).getTime(),q={repositoryManager:null,repositoryFilter:[],objectTypeFilter:[],renditionFilter:["cmis:none"],
filter:["url"],element:null,isFloating:!1,verticalPadding:100,horizontalPadding:50,maxHeight:1E3,minHeight:400,minWidth:400,maxWidth:1200,treeWidth:300,listWidth:"auto",pageSize:8,adaptPageSize:!1,rowHeight:32,rootPath:"",rootFolderId:"aloha",columns:{icon:{title:"",width:30,sortable:!1,resizable:!1},name:{title:"Name",width:200,sorttype:"text"},url:{title:"URL",width:220,sorttype:"text"},preview:{title:"Preview",width:150,sorttype:"text"}},i18n:{Browsing:"Browsing",Close:"Close","in":"in","Input search text...":"Input search text...",
numerous:"numerous",of:"of","Repository Browser":"Repository Browser",Search:"Search","Searching for":"Searching for",Viewing:"Viewing"}};return m.extend({_cachedRepositoryObjects:{},_searchQuery:null,_orderBy:null,_prefilledValue:null,$_grid:null,$_tree:null,$_list:null,_isOpened:!0,_constructor:function(){this.init.apply(this,arguments)},init:function(a){a=d.extend({},q,a,{i18n:o});if(!a.element||0===a.element.length)a.isFloating=!0,a.element=this._createOverlay();if(a.maxWidth<a.minWidth)a.maxWidth=
a.minWidth;d.extend(this,a);this._prefilledValue=this._i18n("Input search text...");this._cachedRepositoryObjects={};this._pagingCount=this._orderBy=this._searchQuery=null;this._pagingOffset=0;this._pagingBtns={first:null,end:null,next:null,prev:null};this._initializeUI();j.push(this);n.pub("repository-browser.initialized",{data:this})},_i18n:function(a){return this.i18n[a]||a},_initializeUI:function(){this.element.attr("data-repository-browser",++g);this.element.width(this.maxWidth);this.$_grid=
this._createGrid(this.element).resize();this._setInitialHeight();this.$_tree=this._createTree(this.$_grid.find(".ui-layout-west"));this.$_list=this._createList(this.$_grid.find(".ui-layout-center"));var a=this,b=this.treeWidth/5;this.$_grid.layout({enableCursorHotkey:!1,west__size:this.treeWidth-1,west__minSize:this.treeWidth-b,west__maxSize:this.treeWidth+b,center__size:"auto",paneClass:"ui-layout-pane",resizerClass:"ui-layout-resizer",togglerClass:"ui-layout-toggler",onresize:function(b,d){"center"===
b&&a.$_list.setGridWidth(d.width())}}).sizePane("west",this.treeWidth);p(this.$_grid);this._preloadImages();d(function(){d(window).resize(function(){a._onWindowResized()})});this.element.mousedown(function(){d.each(j,function(a){this.element.css("z-index",99999+a)});d(this).css("z-index",99999+j.length+1)});d(".repository-browser-grid").css("width",this.maxWidth);this.close();this._adaptPageSize()},_setInitialHeight:function(){var a=this.maxHeight-d(window).height()+this.verticalPadding;this.$_grid.height(a>
0?Math.max(this.minHeight,this.maxHeight-a):this.maxHeight)},_onWindowResized:function(){var a=this.maxWidth-d(window).width()+this.horizontalPadding,a=a>0?Math.max(this.minWidth,this.maxWidth-a):this.maxWidth;this.element.width(a);this.$_grid.width(a);this._setInitialHeight();a=this.$_grid.find(".repository-browser-tree-header");this.$_tree.height(this.$_grid.height()-a.outerHeight(!0));a=this.$_grid.find(".ui-layout-center");a.find(".ui-jqgrid-bdiv").height(this.$_grid.height()-(a.find(".ui-jqgrid-titlebar").height()+
a.find(".ui-jqgrid-hdiv").height()+a.find(".ui-jqgrid-pager").height()));this._adaptPageSize()&&this._currentFolder&&this._fetchItems(this._currentFolder)},_preloadImages:function(){for(var a=this.rootPath+"img/",b="arrow-000-medium.png,arrow-180.png,arrow-315-medium.png,arrow-stop-180.png,arrow-stop.png,arrow.png,control-stop-square-small.png,folder-horizontal-open.png,folder-open.png,magnifier-left.png,page.png,picture.png,sort-alphabet-descending.png,sort-alphabet.png".split(","),c=b.length;c;)document.createElement("img").src=
a+b[--c]},_processRepoResponse:function(a,b,c){var d=[],f;typeof b==="function"&&(c=b,b=void 0);for(f=0;f<a.length;f++)d.push(this._harvestRepoObject(a[f]));c(d,b)},_harvestRepoObject:function(a){++g;this._cachedRepositoryObjects[g]=d.extend(a,{uid:g,loaded:!1});return this._processRepoObject(this._cachedRepositoryObjects[g])},_processRepoObject:function(a){var b,c,e,f=this;switch(a.baseType){case "folder":b="folder";break;case "document":b="document"}c=a.hasMoreItems||a.baseType==="folder"?"closed":
null;a.hasMoreItems===!1&&(c=null);a.children&&(e=[],d.each(a.children,function(){e.push(f._harvestRepoObject(this));c="open"}));this._currentFolder&&this._currentFolder.id===a.id&&window.setTimeout(function(){f.$_tree.jstree("select_node","li[data-repo-obj='"+a.uid+"']")},0);return{data:{title:a.name,attr:{"data-repo-obj":a.uid},icon:b||""},attr:{rel:a.type,"data-repo-obj":a.uid},state:c,resource:a,children:e}},_fetchRepoRoot:function(a){if(!this._currentFolder)this._currentFolder=this.getSelectedFolder();
this.repositoryManager&&this.getRepoChildren({inFolderId:this.rootFolderId,repositoryFilter:this.repositoryFilter},a)},_getObjectFromCache:function(a){return a&&a.length?this._cachedRepositoryObjects[a.find("a:first").attr("data-repo-obj")]:null},_onTreeNodeSelected:function(a,b){if(!b.args[0].context){var c=this._getObjectFromCache(b.rslt.obj);if(c)this._pagingOffset=0,this._clearSearch(),this._currentFolder=c,this._fetchItems(c);this.folderSelected(c)}},_createTree:function(a){var b=d('<div class="repository-browser-tree">'),
c=d('<div class="repository-browser-tree-header repository-browser-grab-handle">'+this._i18n("Repository Browser")+"</div>");a.append(c,b);b.height(this.$_grid.height()-c.outerHeight(!0));b.bind("loaded.jstree",function(){d(this).find(">ul>li:first").css("padding-top",5);b.jstree("open_node",'li[rel="repository"]')});var e=this;b.bind("select_node.jstree",function(a,b){e._onTreeNodeSelected(a,b)});b.bind("open_node.jstree",function(a,b){e.folderOpened(b.rslt.obj)});b.bind("close_node.jstree",function(a,
b){e.folderClosed(b.rslt.obj)});b.jstree({types:this.types,rootFolderId:this.rootFolderId,plugins:["themes","json_data","ui","types"],core:{animation:250},themes:{url:this.rootPath+"css/jstree.css",dots:!0,icons:!0,theme:"browser"},json_data:{data:function(a,b){e.repositoryManager?(e.jstree_callback=b,e._fetchSubnodes(a,b)):b()},correct_state:!0},ui:{select_limit:1}});return b},_createGrid:function(a){var b=d('<div class="repository-browser-grid\t\t\t\t repository-browser-shadow\t\t\t\t\t\t\t repository-browser-rounded-top">\t\t\t\t\t<div class="ui-layout-west"></div>\t\t\t\t\t<div class="ui-layout-center"></div>\t\t\t\t</div>');
a.append(b);return b},_createList:function(a){var b=d('<table id="repository-browser-list-'+ ++g+'" class="repository-browser-list"></table>'),c=[{name:"id",sorttype:"int",firstsortorder:"asc",hidden:!0}],e=[""];d.each(this.columns,function(a,b){e.push(b.title||"&nbsp;");c.push({name:a,width:b.width,sortable:b.sortable,sorttype:b.sorttype,resizable:b.resizable,fixed:b.fixed})});var f="repository-browser-list-page-"+ ++g;a.append(b,d('<div id="'+f+'">'));b.jqGrid({datatype:"local",width:a.width(),
shrinkToFit:!0,colNames:e,colModel:c,caption:"&nbsp;",altRows:!0,altclass:"repository-browser-list-altrow",resizeclass:"repository-browser-list-resizable",pager:"#"+f,viewrecords:!0,onPaging:function(){},loadError:function(){},ondblClickRow:function(){},gridComplete:function(){},loadComplete:function(){}});a.find(".ui-jqgrid-bdiv").height(this.$_grid.height()-(a.find(".ui-jqgrid-titlebar").height()+a.find(".ui-jqgrid-hdiv").height()+a.find(".ui-jqgrid-pager").height()));var h=this;b.click(function(){h.rowClicked.apply(h,
arguments)});a.find(".ui-pg-button").unbind().find(">span.ui-icon").each(function(){var a=this.className.match(/ui\-icon\-seek\-([a-z]+)/)[1];h._pagingBtns[a]=d(this).parent().addClass("ui-state-disabled").click(function(){d(this).hasClass("ui-state-disabled")||h._doPaging(a)})});a.find(".ui-pg-input").parent().hide();a.find(".ui-separator").parent().css("opacity",0).first().hide();this._createTitlebar(a);var l=b[0].p;a.find(".ui-jqgrid-view tr:first th div").each(function(a){!1!==l.colModel[a].sortable&&
(d(this).css("cursor","pointer"),d(this).unbind().click(function(b){b.stopPropagation();h._sortList(l.colModel[a],this)}))});return b},_clearSearch:function(){this.$_grid.find(".repository-browser-search-field").val(this._prefilledValue).addClass("repository-browser-search-field-empty");this._searchQuery=null},_createTitlebar:function(a){var a=a.find(".ui-jqgrid-titlebar"),b=d('<div class="repository-browser-btns">\t\t\t\t\t<input type="text" class="repository-browser-search-field" />\t\t\t\t\t<span class="repository-browser-btn repository-browser-search-btn">\t\t\t\t\t\t<span class="repository-browser-search-icon"></span>\t\t\t\t\t</span>\t\t\t\t\t<span class="repository-browser-btn repository-browser-close-btn">'+
this._i18n("Close")+'</span>\t\t\t\t\t<div class="repository-browser-clear"></div>\t\t\t\t</div>'),c=this;a.addClass("repository-browser-grab-handle").append(b);a.find(".repository-browser-search-btn").html(this._i18n("Search")).click(function(){c._triggerSearch()});b=a.find(".repository-browser-search-field");this._clearSearch();b.keypress(function(a){13===a.keyCode&&c._triggerSearch()});b.focus(function(){d(this).val()===c._prefilledValue&&d(this).val("").removeClass("repository-browser-search-field-empty")});
b.blur(function(){d(this).val()===""&&c._clearSearch()});a.find(".repository-browser-close-btn").click(function(){c.close()});a.find(".repository-browser-btn").mousedown(function(){d(this).addClass("repository-browser-pressed")}).mouseup(function(){d(this).removeClass("repository-browser-pressed")})},_triggerSearch:function(){var a=this.$_grid.find("input.repository-browser-search-field"),b=a.val();if(d(a).hasClass("aloha-browser-search-field-empty")||""===b)b=null;this._pagingOffset=0;this._searchQuery=
b;this._fetchItems(this._currentFolder)},_sortList:function(a,b){this.$_grid.find("span.ui-grid-ico-sort").addClass("ui-state-disabled");a.sortorder="asc"===a.sortorder?"desc":"asc";d(b).find("span.s-ico").show().find(".ui-icon-"+a.sortorder).removeClass("ui-state-disabled");this._setSortOrder(a.name,a.sortorder);this._fetchItems(this._currentFolder)},_doPaging:function(a){switch(a){case "first":this._pagingOffset=0;break;case "end":this._pagingOffset=this._pagingCount%this.pageSize===0?this._pagingCount-
this.pageSize:this._pagingCount-this._pagingCount%this.pageSize;break;case "next":this._pagingOffset+=this.pageSize;break;case "prev":if(this._pagingOffset-=this.pageSize,this._pagingOffset<0)this._pagingOffset=0}this._fetchItems(this._currentFolder)},_setSortOrder:function(a,b){var c={},d=!1,f=this._orderBy||[],h,g,i;c[a]=b||"asc";for(i=0;i<f.length;++i){h=f[i];for(g in h)if(h.hasOwnProperty(g)&&g===a){f.splice(i,1);f.unshift(c);d=!0;break}if(d)break}d&&f.unshift(c);this._orderBy=f},_listItems:function(a){var b=
this.$_list.clearGridData(),c,e;for(c=0;c<a.length;c++)e=a[c].resource,b.addRowData(e.uid,d.extend({id:e.id},this.renderRowCols(e)))},handleTimeout:function(){},_processItems:function(a,b){this._pagingCount=b&&d.isNumeric(b.numItems)?b.numItems:null;this.$_grid.find(".loading").hide();this.$_list.show();this._listItems(a);var c=this._pagingBtns;this._pagingOffset<=0?c.first.add(c.prev).addClass("ui-state-disabled"):c.first.add(c.prev).removeClass("ui-state-disabled");d.isNumeric(this._pagingCount)?
this._pagingOffset+this.pageSize>=this._pagingCount?c.end.add(c.next).addClass("ui-state-disabled"):c.end.add(c.next).removeClass("ui-state-disabled"):(c.end.addClass("ui-state-disabled"),a.length<=this.pageSize?c.next.addClass("ui-state-disabled"):c.next.removeClass("ui-state-disabled"));var e;0===a.length&&0===this._pagingOffset?e=c=0:(c=this._pagingOffset+1,e=c+a.length-1);this.$_grid.find(".ui-paging-info").html(this._i18n("Viewing")+" "+c+" - "+e+" "+this._i18n("of")+" "+(d.isNumeric(this._pagingCount)?
this._pagingCount:this._i18n("numerous")));b&&b.timeout&&this.handleTimeout()},_createOverlay:function(){0===d(".repository-browser-modal-overlay").length&&d("body").append('<div class="repository-browser-modal-overlay" style="top: -99999px; z-index: 99999;"></div>');var a=this;d(".repository-browser-modal-overlay").click(function(){a.close()});var b=d('<div class="repository-browser-modal-window" style="top: -99999px; z-index: 99999;">');d("body").append(b);return b},_fetchSubnodes:function(a,b){if(-1===
a)this._fetchRepoRoot(b);else{var c;for(c=0;c<a.length;c++){var d=this._getObjectFromCache(a.eq(c));d&&this.fetchChildren(d,b)}}},getRepoChildren:function(a,b){if(this.repositoryManager){var c=this;this.repositoryManager.getChildren(a,function(a){c._processRepoResponse(a,b)})}},queryRepository:function(a,b){if(this.repositoryManager){var c=this;this.repositoryManager.query(a,function(a){c._processRepoResponse(a.results>0?a.items:[],{numItems:a.numItems,hasMoreItems:a.hasMoreItems,timeout:a.timeout},
b)})}},renderRowCols:function(a){var b={};d.each(this.columns,function(c){switch(c){case "icon":b.icon='<div class="repository-browser-icon repository-browser-icon-'+a.type+'"></div>';break;default:b[c]=a[c]||"--"}});return b},onSelect:function(){},fetchChildren:function(a,b){if((!0===a.hasMoreItems||"folder"===a.baseType)&&!1===a.loaded){var c=this;this.getRepoChildren({inFolderId:a.id,repositoryId:a.repositoryId},function(d){c._cachedRepositoryObjects[a.uid].loaded=!0;typeof b==="function"&&b(d)})}},
rowClicked:function(a){a=d(a.target).parent("tr");return a.length?(a=this._cachedRepositoryObjects[a.attr("id")],this.onSelect(a),a):null},getFieldOfHeader:function(a){return a.find("div.ui-jqgrid-sortable").attr("id").replace("jqgh_","")},_fetchItems:function(a){if(a){var b=typeof this._searchQuery==="string";this.$_list.setCaption(typeof this._searchQuery==="string"?this._i18n("Searching for")+' "'+this._searchQuery+'" '+this._i18n("in")+" "+a.name:this._i18n("Browsing")+": "+a.name);this.$_list.hide();
this.$_grid.find(".loading").show();var c=this;this.queryRepository({repositoryId:a.repositoryId,inFolderId:a.id,queryString:this._searchQuery,orderBy:this._orderBy,skipCount:this._pagingOffset,maxItems:this.pageSize,objectTypeFilter:this.objectTypeFilter,renditionFilter:this.renditionFilter,filter:this.filter,recursive:b},function(a,b){c._processItems(a,b)})}},setObjectTypeFilter:function(a){this.objectTypeFilter=typeof a==="string"?[a]:a},getObjectTypeFilter:function(){return this.objectTypeFilter},
show:function(){this.open()},open:function(){if(!this._isOpened){this._isOpened=!0;var a=this.element;this.isFloating?(d(".repository-browser-modal-overlay").stop().css({top:0,left:0}).show(),a.stop().show(),this._onWindowResized(),this.$_grid.resize(),d(window),a.css({left:this.horizontalPadding/2,top:this.verticalPadding/2}).draggable({handle:a.find(".repository-browser-grab-handle")}),this.$_grid.css({marginTop:0,opacity:0}).animate({marginTop:0,opacity:1},1500,"easeOutExpo",function(){d.browser.msie&&
d(this).add(a).css("filter","progid:DXImageTransform.Microsoft.gradient(enabled=false)")})):(a.stop().show().css({opacity:1,filter:"progid:DXImageTransform.Microsoft.gradient(enabled=false)"}),this._onWindowResized(),this.$_grid.resize());++k}},close:function(){if(this._isOpened)this._isOpened=!1,this.element.fadeOut(250,function(){d(this).css("top",0).hide();(0===k||0===--k)&&d(".repository-browser-modal-overlay").hide()})},refresh:function(){this._currentFolder&&this._fetchItems(this._currentFolder)},
folderOpened:function(a){(a=this._getObjectFromCache(a))&&this.repositoryManager&&this.repositoryManager.folderOpened(a)},folderClosed:function(a){(a=this._getObjectFromCache(a))&&this.repositoryManager&&this.repositoryManager.folderClosed(a)},folderSelected:function(a){this.repositoryManager&&this.repositoryManager.folderSelected(a)},getSelectedFolder:function(){if(this.repositoryManager&&typeof this.repositoryManager.getSelectedFolder==="function")return this.repositoryManager.getSelectedFolder()},
_adaptPageSize:function(){var a;return!this.adaptPageSize||!this.$_list||!this.rowHeight?!1:(a=this.$_grid.find(".ui-jqgrid-bdiv").innerHeight()-20)?(a=Math.floor(a/this.rowHeight),a<=0&&(a=1),a!==this.pageSize?(this.pageSize=a,!0):!1):!1}})});define("repository-browser-i18n-de",[],function(){return{Browsing:"Durchsuchen",Close:"Schließen","in":"in","Input search text...":"Suchtext einfügen...",numerous:"zahlreiche",of:"von","Repository Browser":"Repository Browser",Search:"Suchen","Searching for":"Suche nach",Viewing:"Anzeige","button.switch-metaview.tooltip":"Zwischen Metaansicht und normaler Ansicht umschalten"}});define("repository-browser-i18n-en",[],function(){return{Browsing:"Browsing",Close:"Close","in":"in","Input search text...":"Input search text...",numerous:"numerous",of:"of","Repository Browser":"Repository Browser",Search:"Search","Searching for":"Searching for",Viewing:"Viewing","button.switch-metaview.tooltip":"Switch between meta and normal view"}});

View File

@@ -1,166 +0,0 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View File

@@ -1,12 +0,0 @@
Config example
--------------
"align": {
// Allow align left, center and justify only for all elements
// 4 possibilities : left, center, right and justify
config : {
alignment: [ 'left','center','justify']
}
}
This plugin is release under the LGPL license.

View File

@@ -1,38 +0,0 @@
.aloha-character-picker-overlay {
position: absolute;
display: none;
float: left;
padding: 3px;
top: 0;
left: 0;
border: 1px solid #afafaf;
border-collapse: separate;
background-color: #fff;
z-index: 999999;
}
.aloha-character-picker-overlay {
border-collapse:collapse;
}
.aloha-character-picker-overlay td {
width: 1.5em;
height: 1.5em;
border: 1px solid #afafaf;
font-size: 0.8em;
padding: 0.05em;
}
.aloha-character-picker-overlay td.mouseover {
border: 1px solid #fdea83;
background-color: #fefce1;
}
.aloha-character-picker-overlay td.focused {
border: 1px solid #407bcf;
background-color: #b9d6f9;
}
.aloha-icon-characterpicker {
background: url( '../img/icon.png' );
}

View File

@@ -1,66 +0,0 @@
# The AlohaEditor Image Plugin
Image Plugin for enabling basic images manipulations in Aloha Editor
## Features
* Insert image
* Edit url and title
* set align
* Handles [DragnDropFiles Plugin](https://github.com/alohaeditor/Aloha-Plugin-DragAndDropFiles) events for image files dropped in current page.
* css resize with controlbuttons or mousedrag
* reset to natural size (DEV)
* canvas crop (EXPERIMENTAL)
## Example conf
config: {
'img': {
'max_width': '50px',
'max_height': '50px',
//Image manipulation options - ONLY in default config section
'ui': {
'meta': true, // If imageResizeWidth and imageResizeHeight are displayed, then you will want to set this to true, so that the width and height text fields are updated automatically.
'crop':true, // If imageCropButton is displayed, then you have to enable this.
'resizable': true, //resizable ui-drag image
},
/**
* crop callback is triggered after the user clicked accept to accept his crop
* @param image jquery image object reference
* @param props cropping properties
*/
'onCropped':function (image, props) {},
/**
* reset callback is triggered before the internal reset procedure is applied
* if this function returns true, then the reset has been handled by the callback
* which means that no other reset will be applied
* if false is returned the internal reset procedure will be applied
* @param image jquery image object reference
* @return true if a reset has been applied, false otherwise
*/
'onReset': function (image) { return false; }
}
}
To show or hide specific Image plug-in buttons, please configure @Aloha.settings.toolbar@, look at the "Image tab" example in @src/plugins/common/ui/lib/settings.js@.
## TODO
* resize slider
* canvas resize
Copyright (c) 2010-2011 Gentics Software GmbH, aloha@gentics.com
Author : [Nicolas Karageuzian](https://github.com/nka11)
Contributors :
* [Nils Dehl](https://github.com/mrsunshine)
* [Benjamin Athur Lupton](https://github.com/balupton)
* [Christopher Hlubek](https://github.com/chlu)
* [Thomas Lete](https://github.com/bistory)
* [Haymo Meran](https://github.com/draftkraft)
* [Clemens Prerovsky](https://github.com/cprerovsky) (base of crop and resize feature is a borrow from cropnresize plugin)
* [Norbert Pomaroli](https://github.com/npomaroli) (for his patience explaining Selection and Range)
* [Kirk Austin](http://www.kirkaustin.com/) who gave the impulsion to dive into html5 canvas

View File

@@ -1,76 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Aloha, World!</title>
<script src="../../lib/require.js" data-main="../../lib/aloha.js" id="aloha-script-include" data-plugins="common/format,common/highlighteditables,common/list,common/undo,common/paste,common/image"></script>
<link rel="stylesheet" href="../../css/aloha.css" id="aloha-style-include">
<link rel="stylesheet" href="../../demo/common/index.css" type="text/css">
<script type="text/javascript">
if (window.Aloha === undefined || window.Aloha === null)
Aloha = {};
Aloha.settings = {
"plugins": {
"com.gentics.aloha.plugins.Image": {
onCropped : function (image, props) {
// invoke the image cropper crop.php
image
.width(props.w) // set width
.height(props.h) // and height to new values
.attr("src", "crop.php?src=" // and adjust src to the cropped image
+ image.attr('src')
+ "&x=" + props.x
+ "&y=" + props.y
+ "&w=" + props.w
+ "&h=" + props.h
);
jQuery("#info").append("<li>Cropped \"" + image.attr("src") + "\"</li>");
},
onResized : function (image) {
// this is the point where you would add a server-side image-resizer
jQuery("#info").append("<li>Resized \"" + image.attr("src") + "\"</li>");
},
onReset : function (image) {
// handle resetting the image
jQuery("#info").append("<li>Resetted \"" + image.attr("src") + "\" to it's initial state</li>");
},
aspectRatio : false, // if set to false the aspectRatio will not be maintained anymore when resizing
maxHeight : 500, // supply a maximum height for resizing
minHeight : 200, // and a minimum height
maxWidth : 700, // maximum image width for resizing
minWidth : 200, // and minimum width
grid : 100 // snap to an invisible grid when resizing
}
}
};
require.ready(function() {
// Prepare
var $ = window.jQuery,
$body = $('body');
$body.bind('aloha',function(){
$('#title').aloha();
$('#teaser').aloha();
$('#content').aloha();
});
});
</script>
</head>
<body>
<div id="main">
<h1 id="title">Aloha, Images! (Extended Version :)</h1>
<div id="bodyContent">
<div id="teaser" class="shorttext">
<p>This <b>extended example</b> is intended for developers planning to use the the CropNResize plugin found at <a href="https://github.com/alohaeditor/Aloha-Plugin-CropNResize">https://github.com/alohaeditor/Aloha-Plugin-CropNResize</a>. It displays the whole set of configuration options currently available. Well, just take a look at the code.</p>
</div>
<div id="content" class="article">
<p>Click the image to start resizing right away, as a resize handle will appear in it's south-east corner.</p>
<p><img src="cropnresize.jpg" /></p>
</div>
</div>
<ol id="info"></ol>
</div>
</body>
</html>

View File

@@ -1,21 +0,0 @@
<?php
/**
* Simple, very basic image cropper for CropNResize plugin demonstration
* @author Clemens Prerovsky
*/
header('Content-type: image/jpeg');
// load parameters from url
$src = $_GET["src"];
$x = intval($_GET["x"]);
$y = intval($_GET["y"]);
$w = intval($_GET["w"]);
$h = intval($_GET["h"]);
// resize image
$img = imagecreatefromjpeg($src) or die("Error: unknown src");
$cropped = imagecreatetruecolor($w, $h);
imagecopyresampled($cropped, $img, 0, 0, $x, $y, $w, $h, $w, $h);
imagejpeg($cropped);
imagedestroy($cropped);
?>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

View File

@@ -1,117 +0,0 @@
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Aloha, Images!</title>
<script type="text/javascript">
(function(window, undefined) {
function _onCropped(image, props) {
var canvas = document.createElement('canvas'),
context = canvas.getContext("2d"),
img = image.get(0),
finalprops = {},
ratio = {img:{}, disp: {}};
ratio.img.h = img.height;// image natural height
ratio.img.w = img.width;// image natural width
ratio.disp.h = image.height(); // image diplay heigth
ratio.disp.w = image.width(); // image diplay width
ratio.h = (ratio.img.h / ratio.disp.h);
ratio.w = (ratio.img.w / ratio.disp.w);
/*
var sourceX = 150;
var sourceY = 0;
var sourceWidth = 150;
var sourceHeight = 150;
var destWidth = sourceWidth;
var destHeight = sourceHeight;
var destX = canvas.width / 2 - destWidth / 2;
var destY = canvas.height / 2 - destHeight / 2;
context.drawImage(imageObj, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight);
*/
// props are related to displayed size of image.
// apply w/h ratio to props to get fprops which will be related to 'real' image dimensions
finalprops.x = props.x * ratio.w;
finalprops.y = props.y * ratio.h;
finalprops.w = props.w * ratio.w;
finalprops.h = props.h * ratio.h;
context.drawImage(img,
finalprops.x, finalprops.y,
finalprops.w, finalprops.h,
0,0,
// props.x2, props.y2,
props.w, props.h);
$('body').append(canvas);
}
if (window.Aloha === undefined || window.Aloha === null) {
var Aloha = window.Aloha = {};
}
Aloha.settings = {
logLevels: {'error': true, 'warn': true, 'info': true, 'debug': false},
'plugins': {
'image': {
'fixedAspectRatio': false,
'maxWidth': 1024,
'minWidth': 10,
'maxHeight': 786,
'minHeight': 10,
'globalselector': '.global'
}
}
};
})(window);
</script>
<script src="../../../../lib/aloha.js" data-aloha-plugins="common/format, common/highlighteditables, common/image"></script>
<link rel="stylesheet" href="../../../../css/aloha.css" id="aloha-style-include" type="text/css">
<link rel="stylesheet" href="../../../../demo/common/index.css" type="text/css">
</head>
<body>
<div id="main">
<div id="tree-div"></div>
<h1 id="title">Aloha, Images!</h1>
<div id="bodyContent">
<div id="teaser" class="shorttext">
<p>This example will show you how to use the Image plugin found at <a href="https://github.com/alohaeditor/Aloha-Plugin-Image">https://github.com/alohaeditor/Aloha-Plugin-Image</a>.</p>
</div>
<div id="content" class="article">
<p><img src="cropnresize.jpg"></p>
<p>Click the image to start resizing right away, as a resize handle will appear in it's south-east corner.</p>
<p><em>Note:</em> This is a very simple example, that will not allow subsequent cropping actions, or cropping combined with resizing.</p>
</div>
Outside of the editable
<p><img class="global" src="cropnresize.jpg"></p>
</div>
</div>
<script type="text/javascript">
Aloha.ready( function(){
var $ = Aloha.jQuery;
$('#title').aloha();
$('#teaser').aloha();
$('#content').aloha();
});
</script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 635 B

View File

@@ -1,12 +0,0 @@
#content {
margin-left: auto;
margin-right: auto;
position: relative;
}
.ui-wrapper {
margin-left: auto !important;
margin-right: auto !important;
position: relative !important;
}

View File

@@ -1,40 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Aloha, Images!</title>
<script type="text/javascript" src="../../../../lib/vendor/jquery-1.6.1.js"></script>
<script type="text/javascript" src="../vendor/ui/jquery-ui-1.8.10.custom.min.js"></script>
<link href="../vendor/ui/ui-lightness/jquery-ui-1.8.10.cropnresize.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="../../../../demo/common/index.css" type="text/css">
<link rel="stylesheet" href="test.css" type="text/css">
</head>
<body>
<script type="text/javascript">
$(document).ready(function() {
$("#myimg").resizable({
grid: 10,
minHeight: 10,
minWidth: 10,
maxHeight: 800,
maxWidth: 900,
handles: 'ne, se, sw, nw',
stop : function (event, ui) {
console.log("stop");
}
});
});
</script>
<div id="main">
<div id="content">
<img id="myimg" src="../demo/cropnresize.jpg" width="200px" height="135px">
</div>
</div>
</body>
</html>

View File

@@ -1,264 +0,0 @@
/* delicious.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
/**
* Create the Repositories object. Namespace for Repositories
* @hide
*/
if ( !GENTICS.Aloha.Repositories ) GENTICS.Aloha.Repositories = {};
/**
* register the plugin with unique name
*/
GENTICS.Aloha.Repositories.delicious = new GENTICS.Aloha.Repository('delicious');
/**
* If no username is given, the public respoitory is searched:
* @property
* @cfg
*/
GENTICS.Aloha.Repositories.delicious.settings.username = 'draftkraft';
/**
* Defines the value to use for sorting the items. Allowed a values 0-0.75
* We choose a low default weight 0.35
* @property
* @default 0.35
* @cfg
*/
GENTICS.Aloha.Repositories.delicious.settings.weight = 0.35;
/**
* init Delicious repository
*/
GENTICS.Aloha.Repositories.delicious.init = function() {
var that = this;
// check weight
if ( this.settings.weight + 0.15 > 1 ) {
this.settings.weight = 1 - 0.15;
}
// default delicious URL. Returns most popular links.
this.deliciousURL = "http://feeds.delicious.com/v2/json/";
if ( this.settings.username ) {
// if a username is set use public user links
this.deliciousURL += this.settings.username + '/';
// set the repository name
this.repositoryName = 'deliciuos/' + this.settings.username;
// when a user is specified get his tags and store it local
this.tags = [];
jQuery.ajax({ type: "GET",
dataType: "jsonp",
url: 'http://feeds.delicious.com/v2/json/tags/'+that.settings.username,
success: function(data) {
// convert data
for (var tag in data) {
that.tags.push(tag);
}
}
});
} else {
// set the repository name
this.repositoryName = 'deliciuos/' + popular;
this.deliciousURL += 'tag/';
}
};
/**
* Searches a repository for items matching query if objectTypeFilter.
* If none found it returns null.
*/
GENTICS.Aloha.Repositories.delicious.query = function( p, callback) {
var that = this;
if ( p.objectTypeFilter && jQuery.inArray('website', p.objectTypeFilter) == -1) {
// return if no website type is requested
callback.call( this, []);
} else {
// prepare tags
var tags = [];
if ( this.settings.username ) {
// search in user tags
var queryTags = p.queryString ? p.queryString.split(' ') : [];
for (var i = 0; i < queryTags.length; i++) {
var queryTag = queryTags[i].trim();
if ( jQuery.inArray(queryTag, that.tags) == -1 ) {
var newtags = that.tags.filter(function(e, i, a) {
var r = new RegExp(queryTag, 'i');
return ( e.match(r) );
});
if ( newtags.length > 0 ) {
tags.push(newtags[0]);
}
} else {
tags.push(queryTag);
}
}
} else {
// handle each word as tag
tags = p.queryString.split(' ');
}
// search in tree
var folderTags = p.inFolderId ? p.inFolderId.split('+') : [];
jQuery.extend(tags, folderTags);
// if we have a query and no tag matching return
if ( p.queryString && tags.length == 0 ) {
callback.call( that, []);
return;
}
jQuery.ajax({ type: "GET",
dataType: "jsonp",
url: that.deliciousURL + tags.join('+'),
success: function(data) {
var items = [];
// convert data to Aloha objects
for (var i = 0; i < data.length; i++) {
if (typeof data[i] != 'function' ) {
items.push(new GENTICS.Aloha.Repository.Document ({
id: data[i].u,
name: data[i].d,
repositoryId: that.repositoryId,
type: 'website',
url: data[i].u,
weight: that.settings.weight + (15-1)/100
}));
}
}
callback.call( that, items);
}
});
}
};
/**
* Returns all tags for username in a tree style way
*/
GENTICS.Aloha.Repositories.delicious.getChildren = function( p, callback) {
var that = this;
// tags are only available when a username is available
if ( this.settings.username ) {
// return all tags
var items = [];
if ( p.inFolderId == this.repositoryId ) {
for (var i = 0; i < this.tags.length; i++) {
if (typeof this.tags[i] != 'function' ) {
items.push(new GENTICS.Aloha.Repository.Folder ({
id: this.tags[i],
name: this.tags[i],
repositoryId: this.repositoryId,
type: 'tag',
url: 'http://feeds.delicious.com/v2/rss/tags/'+that.settings.username+'/'+this.tags[i]
}));
}
}
callback.call( this, items);
} else {
jQuery.ajax({ type: "GET",
dataType: "jsonp",
url: 'http://feeds.delicious.com/v2/json/tags/'+that.settings.username+'/'+p.inFolderId,
success: function(data) {
var items = [];
// convert data
for (var tag in data) {
// the id is tag[+tag+...+tag]
var id = (p.inFolderId)?p.inFolderId + '+' + tag:tag;
if (typeof data[tag] != 'function' ) {
items.push(new GENTICS.Aloha.Repository.Folder({
id: id,
name: tag,
repositoryId: that.repositoryId,
type: 'tag',
url: 'http://feeds.delicious.com/v2/rss/tags/'+that.settings.username+'/'+id,
hasMoreItems: true
}));
}
}
callback.call( that, items);
}
});
}
} else {
callback.call( this, []);
}
};
/**
* Get the repositoryItem with given id
* @param itemId {String} id of the repository item to fetch
* @param callback {function} callback function
* @return {GENTICS.Aloha.Repository.Object} item with given id
*/
GENTICS.Aloha.Repositories.delicious.getObjectById = function ( itemId, callback ) {
var that = this;
jQuery.ajax({
type: 'GET',
dataType: "jsonp",
url: 'http://feeds.delicious.com/v2/json/urlinfo/' + jQuery.md5(itemId),
success: function (data) {
var items = [];
// convert data to Aloha objects
for (var i = 0; i < data.length; i++) {
if (typeof data[i] != 'function' ) {
items.push(new GENTICS.Aloha.Repository.Document ({
id: itemId,
name: data[i].title,
repositoryId: that.repositoryId,
type: 'website',
url: itemId,
weight: that.settings.weight + (15-1)/100
}));
}
}
callback.call( that, items);
}
});
};

View File

@@ -1,247 +0,0 @@
/* linklist.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
/* Aloha Link List Repository
* --------------------------
* A simple demo repository of links.
*/
define(
[ 'aloha', 'aloha/jquery' ],
function ( Aloha, jQuery ) {
/**
* Internal data as array with following format:
*
* [
* { name: 'Aloha Editor - The HTML5 Editor', url: 'http://aloha-editor.org', type: 'website' },
* { name: 'Aloha Editor - Wiki', url: 'http://github.com/alohaeditor/Aloha-Editor/wiki', type: 'website' },
* { name: 'Aloha Editor - GitHub', url: 'http://github.com/alohaeditor/Aloha-Editor', type: 'website' },
* { name: 'Aloha Logo', url: 'http://www.aloha-editor.com/images/aloha-editor-logo.png', type: 'image' }
* ];
*
* @private
*/
var urls = [
{ name: 'Aloha Editor - The HTML5 Editor', url: 'http://aloha-editor.org', type: 'website' },
{ name: 'Aloha Editor - Wiki', url: 'http://github.com/alohaeditor/Aloha-Editor/wiki', type: 'website' },
{ name: 'Aloha Editor - GitHub', url: 'http://github.com/alohaeditor/Aloha-Editor', type: 'website' },
{ name: 'Aloha Logo', url: 'http://www.aloha-editor.com/images/aloha-editor-logo.png', type: 'image' }
];
new ( Aloha.AbstractRepository.extend( {
_constructor: function () {
this._super( 'linklist' );
},
/**
* @private
* @type {array.<?>} Internal folder structure.
*/
folder: [],
/**
* Initalize LinkList, parse all links, build folder structure and add
* additional properties to the items.
*/
init: function () {
if ( Aloha.settings.repositories &&
Aloha.settings.repositories.linklist &&
Aloha.settings.repositories.linklist.data ) {
urls = urls.concat(Aloha.settings.repositories.linklist.data);
}
// Add ECMA262-5 Array method filter if not supported natively.
// But we will be very conservative and add to this single array
// object so that we do not tamper with the native Array prototype
// object.
if ( !( 'filter' in Array.prototype ) ) {
urls.filter = function ( filter, that /*opt*/ ) {
var other = [],
v,
i = 0,
n = this.length;
for ( ; i < n; i++ ) {
if ( i in this && filter.call( that, v = this[ i ], i, this ) ) {
other.push( v );
}
}
return other;
};
}
var l = urls.length;
// generate folder structure
for ( var i = 0; i < l; ++i ) {
var e = urls[ i ];
e.repositoryId = this.repositoryId;
e.id = e.id ? e.id : e.url;
var u = e.uri = this.parseUri( e.url ),
// add hostname as root folder
path = this.addFolder( '', u.host ),
pathparts = u.path.split( '/' );
for ( var j = 0; j < pathparts.length; j++ ) {
if ( pathparts[ j ] &&
// It's a file because it has an extension.
// Could improve this one :)
pathparts[ j ].lastIndexOf( '.' ) < 0 ) {
path = this.addFolder( path, pathparts[ j ] );
}
}
e.parentId = path;
urls[ i ] = new Aloha.RepositoryDocument( e );
}
this.repositoryName = 'Linklist';
},
/**
* @param {String} path
* @param {String} name
* @return {String}
*/
addFolder: function ( path, name ) {
var type = path ? 'folder' : 'hostname';
var p = path ? path + '/' + name : name;
if ( name && !this.folder[ p ] ) {
this.folder[ p ] = new Aloha.RepositoryFolder( {
id: p,
name: name || p,
parentId: path,
type: 'host',
repositoryId: this.repositoryId
} );
}
return p;
},
/**
* Searches a repository for object items matching query if
* objectTypeFilter. If none is found it returns null.
*
* @param {Object} p
* @param {Function} callback
*/
query: function ( p, callback ) {
// Not supported; filter, orderBy, maxItems, skipcount, renditionFilter
var r = new RegExp( p.queryString, 'i' );
var d = urls.filter( function ( e, i, a ) {
return (
( !p.queryString || e.name.match( r ) || e.url.match( r ) ) &&
( !p.objectTypeFilter || ( !p.objectTypeFilter.length ) || jQuery.inArray( e.type, p.objectTypeFilter ) > -1 ) &&
true //( !p.inFolderId || p.inFolderId == e.parentId )
);
} );
callback.call( this, d );
},
/**
* returns the folder structure as parsed at init
*
* @param {Object} p
* @param {Function} callback
*/
getChildren: function ( p, callback ) {
var d = [], e;
for ( e in this.folder ) {
var l = this.folder[ e ].parentId;
if ( typeof this.folder[ e ] != 'function' && ( // extjs prevention
this.folder[ e ].parentId == p.inFolderId || // all subfolders
( !this.folder[ e ].parentId && p.inFolderId == this.repositoryId ) // the hostname
) ) {
d.push( this.folder[ e ] );
}
}
callback.call( this, d );
},
//parseUri 1.2.2
//(c) Steven Levithan <stevenlevithan.com>
//MIT License
//http://blog.stevenlevithan.com/archives/parseuri
parseUri: function(str) {
var o = {
strictMode: false,
key: [ "source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
q: {
name: "queryKey",
parser: /(?:^|&)([^&=]*)=?([^&]*)/g
},
parser: {
strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
}
},
m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
uri = {},
i = 14;
while (i--) uri[o.key[i]] = m[i] || "";
uri[o.q.name] = {};
uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
if ($1) uri[o.q.name][$1] = $2;
});
return uri;
},
/**
* Get the repositoryItem with given id
* Callback: {GENTICS.Aloha.Repository.Object} item with given id
* @param itemId {String} id of the repository item to fetch
* @param callback {function} callback function
*/
getObjectById: function ( itemId, callback ) {
var i = 0,
l = urls.length,
d = [];
for ( ; i < l; i++ ) {
if ( urls[ i ].id == itemId ) {
d.push( urls[ i ] );
}
}
callback.call( this, d );
}
}))();
});

View File

@@ -1,247 +0,0 @@
/* slowlinklist.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
/* Aloha Link List Repository
* --------------------------
* A simple demo repository of links, which is deliberatly slow, in order to
* simulate lags when querying repositories.
*/
define(
[ 'aloha', 'jquery' ],
function ( Aloha, jQuery ) {
'use strict'
/**
* Internal data as array with following format:
*
* [
* { name: 'Aloha Editor - The HTML5 Editor', url:'http://aloha-editor.com', type:'website' },
* { name: 'Aloha Logo', url:'http://www.aloha-editor.com/images/aloha-editor-logo.png', type:'image' }
* ];
*
* @private
*/
var urlset = [
{ name: 'Aloha Test', url: '#alohatest', type: 'website' },
{ name: 'Test One', url: '#test1', type: 'website' },
{ name: 'Test Two', url: '#test2', type: 'website' },
{ name: 'Test Three', url: '#test3', type: 'website' },
{ name: 'Test Four', url: '#test4', type: 'image' }
];
new ( Aloha.AbstractRepository.extend( {
_constructor: function () {
this._super( 'slowlinklist' );
},
/**
* Internal folder structure
* @hide
*/
folder: [],
/**
* initalize LinkList, parse all links, build folder structure and add
* additional properties to the items
*/
init: function () {
// Add ECMA262-5 Array method filter if not supported natively.
// But we will be very conservative and add to this single array
// object so that we do not tamper with the native Array prototype
// object
if ( !( 'filter' in Array.prototype ) ) {
urlset.filter = function ( filter, that /*opt*/ ) {
var other = [],
v,
i = 0,
n = this.length;
for ( ; i < n; i++ ) {
if ( i in this && filter.call( that, v = this[ i ], i, this ) ) {
other.push( v );
}
}
return other;
};
}
var l = urlset.length;
// generate folder structure
for ( var i = 0; i < l; ++i ) {
var e = urlset[ i ];
e.repositoryId = this.repositoryId;
e.id = e.id ? e.id : e.url;
var u = e.uri = this.parseUri( e.url ),
// add hostname as root folder
path = this.addFolder( '', u.host ),
pathparts = u.path.split( '/' );
for ( var j = 0; j < pathparts.length; j++ ) {
if ( pathparts[ j ] &&
// It's a file because it has an extension.
// Could improve this one :)
pathparts[ j ].lastIndexOf( '.' ) < 0 ) {
path = this.addFolder( path, pathparts[ j ] );
}
}
e.parentId = path;
urlset[ i ] = new Aloha.RepositoryDocument( e );
}
this.repositoryName = 'Linklist';
},
/**
* @param {String} path
* @param {String} name
* @return {String}
*/
addFolder: function ( path, name ) {
var type = path ? 'folder' : 'hostname',
p = path ? path + '/' + name : name;
if ( name && !this.folder[ p ] ) {
this.folder[ p ] = new Aloha.RepositoryFolder( {
id: p,
name: name || p,
parentId: path,
type: 'host',
repositoryId: this.repositoryId
} );
}
return p;
},
/**
* Searches a repository for object items matching query if
* objectTypeFilter. If none is found it returns null.
*
* @param {Object} p
* @param {Function} callback
*/
query: function ( p, callback ) {
// Not supported; filter, orderBy, maxItems, skipcount, renditionFilter
var r = new RegExp( p.queryString, 'i' );
var d = urlset.filter( function ( e, i, a ) {
return (
( !p.queryString || e.name.match( r ) || e.url.match( r ) ) &&
( !p.objectTypeFilter || ( !p.objectTypeFilter.length ) || jQuery.inArray( e.type, p.objectTypeFilter ) > -1 ) &&
true //( !p.inFolderId || p.inFolderId == e.parentId )
);
} );
window.setTimeout( function () {
callback.call( this, d );
}, 2000 );
},
/**
* returns the folder structure as parsed at init
*
* @param {Object} p
* @param {Function} callback
*/
getChildren: function ( p, callback ) {
var d = [],
e;
for ( e in this.folder ) {
var l = this.folder[ e ].parentId;
if ( typeof this.folder[ e ] != 'function' && ( // extjs prevention
this.folder[ e ].parentId == p.inFolderId || // all subfolders
( !this.folder[ e ].parentId && p.inFolderId == this.repositoryId ) // the hostname
) ) {
d.push( this.folder[ e ] );
}
}
window.setTimeout( function () {
callback.call( this, d );
}, 2000 );
},
//parseUri 1.2.2
//(c) Steven Levithan <stevenlevithan.com>
//MIT License
//http://blog.stevenlevithan.com/archives/parseuri
parseUri: function(str) {
var o = {
strictMode: false,
key: [ "source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
q: {
name: "queryKey",
parser: /(?:^|&)([^&=]*)=?([^&]*)/g
},
parser: {
strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
}
},
m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
uri = {},
i = 14;
while (i--) uri[o.key[i]] = m[i] || "";
uri[o.q.name] = {};
uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
if ($1) uri[o.q.name][$1] = $2;
});
return uri;
},
/**
* Get the repositoryItem with given id
* Callback: {GENTICS.Aloha.Repository.Object} item with given id
* @param itemId {String} id of the repository item to fetch
* @param callback {function} callback function
*/
getObjectById: function ( itemId, callback ) {
var i = 0,
l = urlset.length,
d = [];
for ( ; i < l; i++ ) {
if ( urlset[ i ].id == itemId ) {
d.push( urlset[ i ] );
}
}
callback.call( this, d );
}
} ) )();
} );

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

View File

@@ -20,4 +20,5 @@
@import "../plugins/extra/ribbon/css/ribbon.css";
@import "../plugins/extra/headerids/css/headerids.css";
@import "../plugins/extra/metaview/css/metaview.css";
@import "../plugins/extra/textcolor/css/textcolor.css";

File diff suppressed because one or more lines are too long

View File

Before

Width:  |  Height:  |  Size: 770 B

After

Width:  |  Height:  |  Size: 770 B

View File

Before

Width:  |  Height:  |  Size: 790 B

After

Width:  |  Height:  |  Size: 790 B

View File

Before

Width:  |  Height:  |  Size: 719 B

After

Width:  |  Height:  |  Size: 719 B

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
media/aloha-0.22.7/img/base.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 509 KiB

After

Width:  |  Height:  |  Size: 509 KiB

View File

Before

Width:  |  Height:  |  Size: 330 B

After

Width:  |  Height:  |  Size: 330 B

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 112 B

After

Width:  |  Height:  |  Size: 112 B

View File

Before

Width:  |  Height:  |  Size: 123 B

After

Width:  |  Height:  |  Size: 123 B

View File

Before

Width:  |  Height:  |  Size: 929 B

After

Width:  |  Height:  |  Size: 929 B

View File

Before

Width:  |  Height:  |  Size: 211 B

After

Width:  |  Height:  |  Size: 211 B

View File

Before

Width:  |  Height:  |  Size: 211 B

After

Width:  |  Height:  |  Size: 211 B

View File

Before

Width:  |  Height:  |  Size: 564 B

After

Width:  |  Height:  |  Size: 564 B

View File

Before

Width:  |  Height:  |  Size: 193 B

After

Width:  |  Height:  |  Size: 193 B

View File

Before

Width:  |  Height:  |  Size: 353 B

After

Width:  |  Height:  |  Size: 353 B

View File

Before

Width:  |  Height:  |  Size: 351 B

After

Width:  |  Height:  |  Size: 351 B

View File

@@ -0,0 +1,12 @@
// To be included in the compiled aloha-full.js (which includes
// requirejs and jQuery) immediately after jQuery. This will prevent
// Aloha's jQuery from polluting the global namespace.
// TODO: requirejs shouldn't leak either
// NB: this is only for aloha-full.js to preserve behaviour with the way
// older builds of aloha were done. It is now always preferred to use
// aloha-bare.js (which doesn't include either requirejs or jQuery) and
// let the implementer worry exactly how to set up jQuery and requirejs
// to suit his needs.
Aloha = window.Aloha || {};
Aloha.settings = Aloha.settings || {};
Aloha.settings.jQuery = Aloha.settings.jQuery || jQuery.noConflict(true);

View File

@@ -0,0 +1,591 @@
/* aloha.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
(function (global) {
'use strict';
/**
* Initialization facilities.
*/
var Initialization = {
/**
* A list of all stages that are passed into the Initialization.start()
* function. Unless failure happens, every single one of these phases
* will be passed.
*
* @type {Array.<object>}
*/
phases: [],
/**
* Completed phases.
*
* This array grows as the initialization process progresses through
* the initialization phases. Each phases which is completed is pushed
* to the bottom of the list.
*
* @type {Array.<object>}
*/
completed: [],
/**
* Starts the initialization phases.
*
* @param {object.<object>} phases Initialization phases.
* @param {function} callback Callback function to be invoked when
* initialization is completed.
*/
start: function (phases, callback) {
Initialization.phases = Initialization.phases.concat(phases);
Initialization.proceed(0, phases, callback);
},
/**
* Proceeds to next initialization phase.
*
* @param {number} index The current initialization phase, as an index
* into `phases'.
* @param {Array.<object>} phases
* @param {function=} callback Callback function to invoke at the end
* of the initialization phases.
*/
proceed: function (index, phases, callback) {
if (index < phases.length) {
var phase = phases[index];
var next = function () {
Initialization.proceed(++index, phases, callback);
};
var event = function () {
Initialization.completed.push(phase);
if (phase.event) {
Aloha.trigger(phase.event);
}
};
if (phase.fn) {
phase.fn(event, next);
} else {
event();
next();
}
} else if (callback) {
callback();
}
},
/**
* Retreives an phase object whose `event' property string matches the
* given event name.
*
* @param {string} event The event name.
* @return {object} A phase object or null.
*/
getPhaseByEvent: function (event) {
var i;
for (i = 0; i < Initialization.phases.length; i++) {
if (event === Initialization.phases[i].event) {
return Initialization.phases[i];
}
}
return null;
},
/**
* Given and the name of an event, returns a corresponding readiness
* state concerning what should be done with that event at the current
* stage in the initialization phase.
*
* @param {string} event Name of event.
* @return {string} One of either "immediate", "deferred", or "noraml".
*/
getReadiness: function (event) {
var i;
for (i = 0; i < Initialization.completed.length; i++) {
if (event === Initialization.completed[i].event) {
return 'immediate';
}
}
return Initialization.getPhaseByEvent(event) ? 'deferred'
: 'normal';
}
};
/**
* Gets the configuration for loading Aloha.
*
* If Aloha.settings.baseUrl is not specified, it will be taken from
* the first script element that has a data-aloha-plugins attribute,
* or, if there is no such script element, the first script element
* of which the src attribute matches /\/aloha.js$/.
*
* If Aloha.settings.plugins.load is not specified, it will be taken
* from the data-aloha-plugins attribute from the first script
* element carrying this attribute.
*
* @return
* A map with two properties:
* baseUrl - the path to aloha.js (this file).
* plugins - an array of plugins to load.
*/
function getLoadConfig() {
var scripts,
script,
plugins = Aloha.settings.plugins && Aloha.settings.plugins.load,
baseUrl = Aloha.settings.baseUrl,
pluginsAttr,
regexAlohaJs = /\/aloha.js(\?\S*)?$/,
regexStripFilename = /\/[^\/]*\.js$/,
i;
if (!plugins || !baseUrl) {
scripts = document.getElementsByTagName('script');
for (i = 0; i < scripts.length; i++) {
script = scripts[i];
pluginsAttr = script.getAttribute('data-aloha-plugins');
if (null != pluginsAttr) {
if (!plugins) {
plugins = pluginsAttr;
}
if (!baseUrl) {
baseUrl = script.src.replace(regexStripFilename, '');
}
break;
}
if (!baseUrl && regexAlohaJs.test(script.src)) {
baseUrl = script.src.replace(regexAlohaJs, '');
}
}
}
if (typeof plugins === 'string' && plugins !== '') {
plugins = plugins.replace(/\s+/g, '').split(',');
}
return {
baseUrl: baseUrl,
plugins: plugins || []
};
}
function isDeferInit() {
var scripts = document.getElementsByTagName('script');
for (var i = 0; i < scripts.length; i++) {
var attr = scripts[i].getAttribute('data-aloha-defer-init');
if ("true" === attr) {
return true;
}
}
return false;
}
/**
* Extends the given map with plugin specific requirejs path configuration.
*
* plugin-name: bundle-path/plugin-name/lib
* plugin-name/nls: bundle-path/plugin-name/nls
* plugin-name/css: bundle-path/plugin-name/css
* plugin-name/vendor: bundle-path/plugin-name/vendor
* plugin-name/res: bundle-path/plugin-name/res
*/
function mergePluginPaths(paths, bundlePath, pluginName) {
var resourceFolders = ['nls', 'css', 'vendor', 'res'],
resourceFolder,
i;
paths[pluginName] = bundlePath + '/' + pluginName + '/lib';
for (i = 0; i < resourceFolders.length; i++) {
var resourceFolder = resourceFolders[i];
paths[pluginName + '/' + resourceFolder]
= bundlePath + '/' + pluginName + '/' + resourceFolder;
}
}
/**
* Gets the configuration for loading the given plugins.
*
* The bundle-path for each given plugin is determined in the following manner:
* Aloha.settings.basePath + (Aloha.settings.bundles[bundleName] || "../plugins/bundle-name")
*
* @param plugins
* An array of plugins to get the configuration for in the
* form "bundle-name/plugin-name"
* @return
* A map with the following properties:
* paths - requirejs path configuration for each plugin (mergePluginPaths())
* entryPoints - an array of requirejs entry points ("link/link-plugin")
* baseUrlByName - ("link" => "bundle-path/link")
* names - an array of plugin names (the same as the given
* array with the bundle-name stripped)
*/
function getPluginLoadConfig(plugins) {
var paths = {},
entryPoints = [],
names = [],
baseUrlByName = {},
map = {},
parts,
bundleName,
pluginName,
basePath = Aloha.settings.basePath || '',
bundlePath,
bundles = Aloha.settings.bundles || {},
i;
for (i = 0; i < plugins.length; i++) {
parts = plugins[i].split('/');
bundleName = parts[0];
pluginName = parts[1];
if (bundles[bundleName]) {
bundlePath = basePath + bundles[bundleName];
} else {
bundlePath = basePath + '../plugins/' + bundleName;
}
mergePluginPaths(paths, bundlePath, pluginName);
baseUrlByName[pluginName] = bundlePath + '/' + pluginName;
entryPoints.push(pluginName + '/' + pluginName + '-plugin');
map[pluginName] = {'jquery': 'aloha/jquery'};
}
return {
paths: paths,
entryPoints: entryPoints,
baseUrlByName: baseUrlByName,
names: names,
map: map
};
}
/**
* Merges properites of all given arguments into a new one.
* Duplicate properties will be "seived" out.
* Works in a similar way to jQuery.extend.
* Necessary because we must not assume that jquery was already
* loaded.
*/
function mergeObjects () {
var clone = {};
var objects = Array.prototype.slice.call(arguments);
var name;
var i;
var obj;
for (i = 0; i < objects.length; i++) {
obj = objects[i];
for (name in obj) {
if (obj.hasOwnProperty(name)) {
clone[name] = objects[i][name];
}
}
}
return clone;
}
function createDefine(name, module) {
define(name, function () {
return module;
});
}
function load() {
Aloha.features = {};
Aloha.defaults = {};
Aloha.settings = Aloha.settings || {};
Aloha.initialize = Initialization.start;
var loadConfig = getLoadConfig();
var pluginConfig = getPluginLoadConfig(loadConfig.plugins);
Aloha.settings.baseUrl = loadConfig.baseUrl;
Aloha.settings.loadedPlugins = pluginConfig.names;
Aloha.settings._pluginBaseUrlByName = pluginConfig.baseUrlByName;
var coreMap = {
'aloha': {'jquery': 'aloha/jquery'},
'aloha/jquery': {'jquery': 'jquery'}, // avoid a circular dependency
'jqueryui': {'jquery': 'aloha/jquery'},
'vendor': {'jquery': 'aloha/jquery'},
'util': {'jquery': 'aloha/jquery'},
'RepositoryBrowser': {'jquery': 'aloha/jquery'},
'jstree': {'jquery': 'aloha/jquery'},
'jqgrid': {'jquery': 'aloha/jquery'},
'jqgrid-locale-en': {'jquery': 'aloha/jquery'},
'jqgrid-locale-de': {'jquery': 'aloha/jquery'},
'jquery-layout': {'jquery': 'aloha/jquery'}
};
/**
* Map the 'jquery' module to the 'aloha/jquery' module. This
* enforces Aloha modules to always use aloha/jquery instead of
* jquery. One could also just write
* define(['aloha/jquery']... to require Aloha's jquery, but
* this is problematic in vendor files that don't know anything
* about Aloha. Each key in the map is either the module name,
* or the firs part of the module name. For example, the mapping
* under the key 'aloha' will take effect for all modules with
* names like aloha/xxx. When a new 'paths' entry is added
* (browserPaths or other), an entry should also be added the
* moduleMap to rename the jquery dependency.
* See also define('aloha/jquery', ... below.
*/
var moduleMap = mergeObjects(coreMap, pluginConfig.map)
var defaultConfig = {
context: 'aloha',
locale: Aloha.settings.locale || 'en',
baseUrl: Aloha.settings.baseUrl,
map: moduleMap
};
var DependencyManagement = global.__DEPS__ || (global.__DEPS__ = {});
DependencyManagement.lang = defaultConfig.locale;
var defaultPaths = {
jquery: 'vendor/jquery-1.7.2',
jqueryui: 'vendor/jquery-ui-1.9m6'
};
var browserPaths = {
PubSub: 'vendor/pubsub/js/pubsub-unminified',
'Class': 'vendor/class',
RepositoryBrowser: 'vendor/repository-browser/js/repository-browser-unminified',
jstree: 'vendor/jquery.jstree', // Mutates jquery
jqgrid: 'vendor/jquery.jqgrid', // Mutates jquery
'jquery-layout': 'vendor/jquery.layout', // Mutates jquery
'jqgrid-locale-en': 'vendor/grid.locale.en', // Mutates jqgrid
'jqgrid-locale-de': 'vendor/grid.locale.de', // Mutates jqgrid
'repository-browser-i18n-de': 'vendor/repository-browser/js/repository-browser-unminified',
'repository-browser-i18n-en': 'vendor/repository-browser/js/repository-browser-unminified'
};
var requireConfig = mergeObjects(
defaultConfig,
Aloha.settings.requireConfig
);
requireConfig.paths = mergeObjects(
defaultPaths,
browserPaths,
pluginConfig.paths,
requireConfig.paths
);
// Create define() wrappers that will provide the initialized objects
// that the user passes into Aloha via require() calls.
var predefinedModules = Aloha.settings.predefinedModules || {};
if (Aloha.settings.jQuery) {
predefinedModules.jquery = Aloha.settings.jQuery;
}
var moduleName;
for (moduleName in predefinedModules) if (predefinedModules.hasOwnProperty(moduleName)) {
createDefine(moduleName, predefinedModules[moduleName]);
delete requireConfig.paths[moduleName];
}
// Configure require and expose the Aloha.require.
var alohaRequire = require.config(requireConfig);
Aloha.require = function (callback) {
// Pass the Aloha object to the given callback.
if (1 === arguments.length && typeof callback === 'function') {
return alohaRequire(['aloha'], callback);
}
return alohaRequire.apply(this, arguments);
};
/**
*
* @param {string} event Name of event
* @param {function} fn Event handler
*/
Aloha.bind = function (event, fn) {
Aloha.require(['aloha/jquery'], function ($) {
// Because we will only need to load jQuery once
Aloha.bind = function (event, fn) {
switch(Initialization.getReadiness(event)) {
case 'deferred':
var phase = Initialization.getPhaseByEvent(event);
if (!phase.deferred) {
phase.deferred = $.Deferred();
}
phase.deferred.done(fn);
break;
case 'immediate':
fn();
break;
case 'normal':
$(Aloha, 'body').bind(event, fn);
break;
default:
throw 'Unknown readiness';
}
return this;
};
Aloha.bind(event, fn);
});
return this;
};
Aloha.trigger = function (type, data) {
Aloha.require(['aloha/jquery'], function ($) {
Aloha.trigger = function (type, data) {
var phase = Initialization.getPhaseByEvent(type);
if (phase) {
if (phase.deferred) {
$(phase.deferred.resolve);
phase.deferred = null;
}
}
$(Aloha, 'body').trigger(type, data);
return this;
};
Aloha.trigger(type, data);
});
return this;
};
Aloha.unbind = function (typeOrEvent) {
Aloha.require(['aloha/jquery'], function ($) {
Aloha.unbind = function (typeOrEvent) {
$(Aloha, 'body').unbind(typeOrEvent);
};
Aloha.unbind(typeOrEvent);
});
};
Aloha.ready = function (fn) {
this.bind('aloha-ready', fn);
return this;
};
/**
* This makes sure that all Aloha modules will receive the same jQuery.
*
* This is a workaround for when a user includes his own
* jQuery _after_ aloha.js has been loaded.
*
* If multiple 'jquery's are included in the page, each version
* will make its own call to define(), and depending on when an
* Aloha module is loaded, it may receive a different
* 'jquery'. However, 'aloha/jquery' will not be redefined and
* will therefore point always to only one particular version.
*
* !!Important!! to be certain that 'aloha/jquery' points to
* the jQuery intended for Aloha, it can't be loaded
* dynamically, because if a user loads his own jQuery after
* aloha.js, then there is no way to tell whether it is the
* user's jQuery or Aloha's jQuery that has finished
* loading. Instead, jQuery must be loaded before aloha.js and
* passed in to us.
*/
var jQueryThatWasPassedToUs = Aloha.settings.jQuery;
define('aloha/jquery', ['jquery'], function ($) {
// We prefer Aloha.settings.jQuery, since a dynamically loaded
// jQuery may have been redefined by a user's jQuery.
return jQueryThatWasPassedToUs || $;
});
// Initialize this early so that the user doesn't have to use
// Aloha.ready().
Aloha.jQuery = jQueryThatWasPassedToUs;
define('aloha', [
'aloha/jquery',
'util/json2',
'aloha/rangy-core',
'util/class',
'util/lang',
'util/range',
'util/dom',
'aloha/core',
'aloha/editable',
'aloha/console',
'aloha/markup',
'aloha/plugin',
'aloha/selection',
'aloha/command',
'aloha/jquery.aloha',
'aloha/sidebar',
'util/position',
'aloha/repositorymanager',
'aloha/repository',
'aloha/repositoryobjects',
'aloha/contenthandlermanager'
], function($) {
Aloha.features.jquery = true;
// Set it again in case jQuery was loaded asynchronously.
Aloha.jQuery = $;
// Some core files provide default settings in Aloha.defaults.
Aloha.settings = $.extendObjects(true, {}, Aloha.defaults,
Aloha.settings);
return Aloha;
});
// TODO aloha should not make the require call itself. Instead, user
// code should require and initialize aloha.
require(requireConfig, ['aloha', 'aloha/jquery'], function (Aloha, $) {
require(requireConfig, pluginConfig.entryPoints, function () {
$(function () {
// Rangy must be initialized only after the body is
// available since it accesses the body element during
// initialization.
window.rangy.init();
// The same for Aloha, but probably only because it depends
// on rangy.
Aloha.init();
});
});
});
} // end load()
global.Aloha = global.Aloha || {};
if (global.Aloha.deferInit || isDeferInit()) {
global.Aloha.deferInit = load;
} else {
// Unless init is deferred above, aloha mus be loaded
// immediately in the development version, but later in the
// compiled version. The reason loading must be delayed in the
// compiled version is that the "include" directive in the r.js
// build profile, which lists the plugins that will be compiled
// into aloha.js, will include the plugins *after* this
// file. Since the require() call that loads the plugins is in
// this file, it will not see any of the plugin's defines that
// come after this file. The call to Aloha._load is only made in
// compiled mode in closure-end.frag. The call to load() below
// is only made in development mode because the excludeStart and
// excludeEnd r.js pragmas will exclude everything inbetween in
// the compiled version.
// TODO ideally the bootstrap file should not make the require
// call at all. Instead, user code should require and
// initialize aloha.
Aloha._load = load;
//>>excludeStart("alohaLoadInEndClosure", pragmas.alohaLoadInEndClosure);
load();
//>>excludeEnd("alohaLoadInEndClosure");
}
}(window));

View File

@@ -0,0 +1,151 @@
/* block-jump.js is part of the Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
/**
* Implements some logic related to moving the cursor keys across blocks.
*
* In the following example
*
* "some text<span class="aloha-block ..." contenteditable="false" ...>...</span>[]some text"
*
* when one moves the cursor indicated by "[]" to the left, the entire
* non-contenteditable block is skipped. The same for moving the cursor
* right across the block.
*
* TODO: actually, the block shouldn't be skipped, it should be
* selected/highlighted first.
* TODO: this file currently doesn't contain all the code to implement
* block jumping. Some of it is currently implemented in markup.js.
*/
define([
'aloha/core',
'jquery'
], function (
Aloha,
$
) {
'use strict';
var zeroWidthNode = null;
/**
* Replaces the text in given text with the given text.
*
* @param node
* A text node attached to the DOM.
* @param text
* A string that is to replace the text of the given text node.
*/
function replaceMergeTextNode(node, text) {
node.deleteData(0, node.length);
if ('' !== text) {
if (node.nextSibling && 3 === node.nextSibling.nodeType) {
node.nextSibling.insertData(0, text);
} else if (node.previousSibling && 3 === node.previousSibling.nodeType) {
node.previousSibling.insertData(node.previousSibling.length, text);
} else {
node.insertData(0, text);
}
}
// We don't remove the node immediately to avoid intefering with a
// caller's range object that may have a start or end containers
// equal to this node. Removing it in a timeout may still interfere
// with the selection, but that was not a problem during testing.
setTimeout(function () {
if (0 === node.length) {
$(node).remove();
}
}, 0);
}
/**
* Removes a previously inserted zero width text node.
* See insertZeroWidthTextNodeFix().
*/
function removeZeroWidthTextNodeFix() {
if (!zeroWidthNode) {
return;
}
// We want to only replace a single zero-width character to avoid
// interfering with the other zero-width whitespace hack that makes
// empty lines visible in IE7.
var text = zeroWidthNode.nodeValue.replace(/\u200b/, '');
if (text === zeroWidthNode.nodeValue) {
console.warn('Expected to remove the zero width text node fix, but couldn\'t find it');
}
replaceMergeTextNode(zeroWidthNode, text);
zeroWidthNode = null;
}
/**
* Inserts a zero width text node before or after a block.
*
* There is a problem where some browsers can't select the boundary
* between some contenteditable content and non-contenteditable
* content. For example, if in the example at the top of the file
* the selection were one step to the right "...</span>s[]ome..."
* and the left cursor key were pressed, then the selection would
* just disappear or be stuck between the span and the text node.
*
* To work around this problem a zero width text node is inserted
* before or after a block.
*
* The inserted zero width text node will be removed automatically
* when it isn't necessary any more (on selection change or on
* editable.getContents()).
*
* TODO: In retrospect, a better alternative may be to simply wrap
* every inlin-block with an editable span.
* @param block
* The DOM element for a block before or after which the zero
* width text node will be inserted.
* @param isGoingLeft
* True if the zero width text node is to be inserted after
* the block element, or false if the zero width text node is
* to be inserted before the block element.
* @return
* The text node that was inserted.
*/
function insertZeroWidthTextNodeFix(block, isGoingLeft) {
removeZeroWidthTextNodeFix();
zeroWidthNode = document.createTextNode("\u200b");
if (isGoingLeft) {
$(block).after(zeroWidthNode);
} else {
$(block).before(zeroWidthNode);
}
Aloha.bind('aloha-selection-changed', function (event) {
removeZeroWidthTextNodeFix();
Aloha.unbind(event);
});
return zeroWidthNode;
}
return {
removeZeroWidthTextNodeFix: removeZeroWidthTextNodeFix,
insertZeroWidthTextNodeFix: insertZeroWidthTextNodeFix
};
});

View File

@@ -0,0 +1,283 @@
/* command.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
define([
'aloha/core',
'aloha/registry',
'aloha/engine',
'util/dom',
'aloha/contenthandlermanager'
], function (
Aloha,
Registry,
Engine,
Dom,
ContentHandlerManager
) {
"use strict";
// 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) {
var evtObj = {
commandId: commandId,
preventDefault: false
};
Aloha.trigger('aloha-command-will-execute', evtObj);
if (evtObj.preventDefault === true) {
return;
}
// 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.toLowerCase() === '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,
command: 'insertHtml'
});
}
Engine.execCommand(commandId, showUi, value, range);
if (Aloha.getSelection().getRangeCount()) {
// Read range after engine modification
range = Aloha.getSelection().getRangeAt(0);
// FIX: doCleanup should work with W3C range
var startnode = range.commonAncestorContainer;
if (startnode.parentNode) {
startnode = startnode.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) {
if (Engine.commands.hasOwnProperty(command)) {
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

@@ -0,0 +1,347 @@
/* console.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
define([
'aloha/core',
'util/class',
'jquery'
], function (
Aloha,
Class,
jQuery
) {
"use strict";
/**
* 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()
});
var console = window.console;
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
// @todo remove old entries when aloha-log-full event is triggered
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.
Aloha.Log = Aloha.Console = AlohaConsole;
return AlohaConsole;
});

View File

@@ -0,0 +1,101 @@
/* contenthandlermanager.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
define([
'aloha/registry',
'util/class',
'aloha/console'
], function (
Registry,
Class,
console
) {
'use strict';
/**
* Create an contentHandler from the given definition. Acts as a factory
* method for contentHandler.
*
* @param {ContentHandlerManager} definition
*/
var ContentHandlerManager = 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();
},
/**
* Manipulates the given contents of an editable by invoking content
* handlers over the contents.
*
* @param {string} content The contents of an editable which will be
* handled.
* @param {object} options Used to filter limit which content handlers
* should be used.
* @param {Aloha.Editable} The editable whose content is being handled.
* @return {string} The handled content.
*/
handleContent: function (content, options, editable) {
var manager = this;
// Because if no options is specified to indicate which content
// handler to use, then all that are available are used.
var handlers = options ? options.contenthandler : manager.getIds();
if (!handlers) {
return content;
}
var i;
var handler;
for (i = 0; i < handlers.length; i++) {
handler = manager.get(handlers[i]);
if (handler) {
content = handler.handleContent(content, options,
editable || Aloha.activeEditable);
}
// FIME: Is it ever valid for content to be null? This breaks
// the handleContent(string):string contract.
if (null === content) {
break;
}
}
return content;
}
});
return new ContentHandlerManager();
});

View File

@@ -0,0 +1,108 @@
/* copypaste.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
/**
* @overview:
* Various utility functions that are useful when working with selections, and
* ranges for copy/paste functionality.
*/
define('aloha/copypaste', [
'jquery',
'aloha/core'
], function (
$,
Aloha
) {
'use strict';
/**
* Retrieve the editable host in which the given range is contained.
*
* @param {WrappedRange} range
* @return {jQuery.<HTMLElement>|null} The editable host element, null if
* non can be determinded from the given
* range.
*/
function getEditableAt(range) {
if (!range || !range.commonAncestorContainer) {
return null;
}
var $container = $(range.commonAncestorContainer);
return $container.length ? Aloha.getEditableHost($container) : null;
}
/**
* Retrieves the current range.
*
* @return {WrappedRange|null} Range at current selection or null of non
* exists.
*/
function getRange() {
var selection = Aloha.getSelection();
return selection.getRangeCount() ? selection.getRangeAt(0) : null;
}
/**
* Set the selection to the given range
*
* @param {object} range An object that must container the following
* essential range properties: ~ startContainer
* ~ endContainer
* ~ startOffset
* ~ endOffset
*/
function setSelectionAt(range) {
var newRange = Aloha.createRange();
var selection = Aloha.getSelection();
newRange.setStart(range.startContainer, range.startOffset);
newRange.setEnd(range.endContainer, range.endOffset);
selection.removeAllRanges();
selection.addRange(newRange);
}
/**
* Creates a selection that encompasses the contents of the given element.
*
* @param {HTMLElement} element Editable DOM element.
*/
function selectAllOf(element) {
setSelectionAt({
startContainer: element,
endContainer: element,
startOffset: 0,
endOffset: element.childNodes ? element.childNodes.length
: element.length
});
$(element).focus();
}
return {
getEditableAt: getEditableAt,
getRange: getRange,
selectAllOf: selectAllOf,
setSelectionAt: setSelectionAt
};
});

View File

@@ -0,0 +1,615 @@
/*core.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
define([
'jquery',
'aloha/pluginmanager'
], function (
$,
PluginManager
) {
'use strict';
var Aloha = window.Aloha;
/**
* Checks whether the current user agent is supported.
*
* @return {boolean} True if Aloha supports the current browser.
*/
function isBrowserSupported() {
var browser = $.browser;
var version = browser.version;
return !(
// Chrome/Safari 4
(browser.webkit && parseFloat(version) < 532.5) ||
// FF 3.5
(browser.mozilla && parseFloat(version) < 1.9) ||
// IE 7
(browser.msie && version < 7) ||
// Right now Opera needs some work
(browser.opera && version < 11)
);
}
/**
* Checks whether the given jQuery event originates from an Aloha dialog
* element.
*
* This is used to facilitate a hackish way of preventing blurring
* editables when interacting with Aloha UI modals.
*
* @param {jQuery<Event>} $event
* @return {boolean} True if $event is initiated from within an Aloha
* dialog element.
*/
function originatesFromDialog($event) {
var $target = $($event.target);
return $target.is('.aloha-dialog') ||
0 < $target.closest('.aloha-dialog').length;
}
/**
* Registers events on the documents to cause editables to be blurred when
* clicking outside of editables.
*
* Hack: Except when the click originates from a modal dialog.
*/
function registerEvents() {
$('html').mousedown(function ($event) {
if (Aloha.activeEditable && !Aloha.eventHandled
&& !originatesFromDialog($event)) {
Aloha.deactivateEditable();
}
}).mouseup(function () {
Aloha.eventHandled = false;
});
}
/**
* Initialize Aloha.
*
* @param {function} next Function to call after initialization.
*/
function initAloha(event, next) {
if (!isBrowserSupported()) {
var console = window.console;
if (console) {
var fn = console.error ? 'error' : console.log ? 'log' : null;
if (fn) {
console[fn]('This browser is not supported');
}
}
return;
}
// Because different css is to be applied based on what the user-agent
// supports. For example: outlines do not render in IE7.
if ($.browser.webkit) {
$('html').addClass('aloha-webkit');
} else if ($.browser.opera) {
$('html').addClass('aloha-opera');
} else if ($.browser.msie) {
$('html').addClass('aloha-ie' + parseInt($.browser.version, 10));
} else if ($.browser.mozilla) {
$('html').addClass('aloha-mozilla');
}
if (navigator.appVersion.indexOf('Win') !== -1) {
Aloha.OSName = 'Win';
} else if (navigator.appVersion.indexOf('Mac') !== -1) {
Aloha.OSName = 'Mac';
} else if (navigator.appVersion.indexOf('X11') !== -1) {
Aloha.OSName = 'Unix';
} else if (navigator.appVersion.indexOf('Linux') !== -1) {
Aloha.OSName = 'Linux';
}
registerEvents();
Aloha.settings.base = Aloha.getAlohaUrl();
Aloha.Log.init();
// Initialize error handler for general javascript errors.
if (Aloha.settings.errorhandling) {
window.onerror = function (msg, url, line) {
Aloha.Log.error(Aloha, 'Error message: ' + msg + '\nURL: ' +
url + '\nLine Number: ' + line);
return true;
};
}
event();
next();
}
/**
* Initialize managers
*/
function initRepositoryManager(event, next) {
Aloha.RepositoryManager.init();
event();
next();
}
/**
* Initialize Aloha plugins.
*
* @param {function} onPluginsInitialized Callback that will be invoked
* after all plugins have been
* initialized. Whereas plugins are
* loaded synchronously, plugins may
* initialize asynchronously.
*/
function initPluginManager(event, next) {
// Because if there are no loadedPlugins specified, then the default is
// to initialized all available plugins.
if (0 === Aloha.loadedPlugins.length) {
var plugins = PluginManager.plugins;
var plugin;
for (plugin in plugins) {
if (plugins.hasOwnProperty(plugin)) {
Aloha.loadedPlugins.push(plugin);
}
}
}
var fired = false;
PluginManager.init(function () {
if (!fired) {
event();
fired = true;
}
next();
}, Aloha.loadedPlugins);
if (!fired) {
event();
fired = true;
}
}
/**
* Begin initialize editables.
*/
function initEditables(event, next) {
var i;
for (i = 0; i < Aloha.editables.length; i++) {
if (!Aloha.editables[i].ready) {
Aloha.editables[i].init();
}
}
event();
next();
}
/**
* Initialization phases.
*
* These stages denote the initialization states which Aloha will go
* through from loading to ready.
*
* Each phase object contains the following properties:
* fn : The process that is to be invoked during this phase.
* Will take two functions: event() and next().
* event : The event name, which if provided, will be fired after the
* phase has been started (optional).
* deferred : A $.Deferred() object to hold event handlers until that
* initialization phase has been done (optional).
*
* @type {Array.<phase>}
*/
var phases = [
// Phase 0: Waiting for initialization to begin. This is the state at
// load-time.
{
fn: null,
event: null,
deferred: null
},
// Phase 1: DOM is ready; performing compatibility checks, registering
// basic events, and initializing logging.
{
fn: initAloha,
event: null,
deferred: null
},
// Phase 2: Initial checks have passed; Initializing repository manger.
{
fn: initRepositoryManager,
event: null,
deferred: null
},
// Phase 3: Repository manager is ready for use; commence
// initialization of configured or default plugins.
{
fn: initPluginManager,
event: 'aloha-plugins-loaded',
deferred: null
},
// Phase 4: Plugins have all begun their initialization process, but it
// is not necessary that they have completed. Start
// initializing editable, along with their scaffolding UI.
// Editables will not be fully initialized however, until
// plugins have finished initialization.
{
fn: initEditables,
event: null,
deferred: null
},
// Phase 5: The "ready" state. Notify the system that Aloha is fully
// loaded, and ready for use.
{
fn: null,
event: 'aloha-ready',
deferred: null
}
];
/**
* Base Aloha Object
* @namespace Aloha
* @class Aloha The Aloha base object, which contains all the core functionality
* @singleton
*/
$.extend(true, Aloha, {
/**
* The Aloha Editor Version we are using
* It should be set by us and updated for the particular branch
* @property
*/
version: '${version}',
/**
* 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',
/**
* A list of loaded plugin names, available after the STAGES.PLUGINS
* initialization phase.
*
* @type {Array.<string>}
* @internal
*/
loadedPlugins: [],
/**
* Maps names of plugins (link) to the base URL (../plugins/common/link).
*/
_pluginBaseUrlByName: {},
/**
* Start the initialization process.
*/
init: function () {
Aloha.initialize(phases);
},
/**
* 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.
*
* @param {string} plugin Name of plugin
* @return {boolean} True if plugin with given name is load.
*/
isPluginLoaded: function (name) {
var loaded = false;
$.each(this.loadedPlugins, function (i, plugin) {
if (name === plugin.toString()) {
loaded = true;
return false;
}
});
return loaded;
},
/**
* Activates editable and deactivates all other Editables.
*
* @param {Editable} editable the Editable to be activated
*/
activateEditable: function (editable) {
// Because editables may be removed on blur, Aloha.editables.length
// is not cached.
var editables = Aloha.editables;
var i;
for (i = 0; i < editables.length; i++) {
if (editables[i] !== editable && editables[i].isActive) {
editables[i].blur();
}
}
Aloha.activeEditable = editable;
},
/**
* Returns the current Editable
* @return {Editable} returns the active Editable
*/
getActiveEditable: function () {
return Aloha.activeEditable;
},
/**
* Deactivates the active Editable.
*
* TODO: Would be better named "deactivateActiveEditable".
*/
deactivateEditable: function () {
if (Aloha.activeEditable) {
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|null} An editable, or null if none if found
* for the given id.
*/
getEditableById: function (id) {
// Because if the element is a textarea, then it's necessary to
// route to the editable div.
var $editable = $('#' + id);
if ($editable.length
&& 'textarea' === $editable[0].nodeName.toLowerCase()) {
id = id + '-aloha';
}
var i;
for (i = 0; i < Aloha.editables.length; i++) {
if (Aloha.editables[i].getId() === id) {
return Aloha.editables[i];
}
}
return null;
},
/**
* Checks whether an object is a registered Aloha Editable.
* @param {jQuery} obj the jQuery object to be checked.
* @return {boolean}
*/
isEditable: function (obj) {
var i, editablesLength;
for (i = 0, editablesLength = Aloha.editables.length; i < editablesLength; i++) {
if (Aloha.editables[i].originalObj.get(0) === obj) {
return true;
}
}
return false;
},
/**
* Gets the nearest editable parent of the DOM element contained in the
* given jQuery object.
*
* @param {jQuery} $element jQuery unit set containing DOM element.
* @return {Aloha.Editable} Editable, or null if none found.
*/
getEditableHost: (function () {
var getEditableOf = function (editable) {
var i;
for (i = 0; i < Aloha.editables.length; i++) {
if (Aloha.editables[i].originalObj[0] === editable) {
return Aloha.editables[i];
}
}
return null;
};
return function ($element) {
if (!$element || 0 === $element.length) {
return null;
}
var editable = getEditableOf($element[0]);
if (!editable) {
$element.parents().each(function (__unused__, node) {
editable = getEditableOf(node);
if (editable) {
return false;
}
});
}
return editable;
};
}()),
/**
* Logs a message to the console.
*
* @param {string} level Level of the log
* ("error", "warn" or "info", "debug").
* @param {object} component Component that calls the log.
* @param {string} message Log message.
* @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.
* @hide
*/
registerEditable: function (editable) {
Aloha.editables.push(editable);
},
/**
* Unregister the given editable. It will be deactivated and removed
* from editables.
*
* @param {Editable} editable The editable to unregister.
* @hide
*/
unregisterEditable: function (editable) {
var index = $.inArray(editable, Aloha.editables);
if (index !== -1) {
Aloha.editables.splice(index, 1);
}
},
/**
* Check whether at least one editable was modified.
*
* @return {boolean} True when at least one editable was modified,
* false otherwise.
*/
isModified: function () {
var i;
for (i = 0; i < Aloha.editables.length; i++) {
if (Aloha.editables[i].isModified
&& Aloha.editables[i].isModified()) {
return true;
}
}
return false;
},
/**
* Determines the Aloha Url.
*
* @return {String} Aloha's baseUrl setting or "" if not set.
*/
getAlohaUrl: function (suffix) {
return Aloha.settings.baseUrl || '';
},
/**
* Gets the plugin's url.
*
* @param {string} name The name with which the plugin was registered
* with.
* @return {string} The fully qualified url of this plugin.
*/
getPluginUrl: function (name) {
if (name) {
return null;
}
var url = Aloha.settings._pluginBaseUrlByName[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;
},
/**
* Disable object resizing by executing command 'enableObjectResizing',
* if the browser supports this.
*/
disableObjectResizing: function () {
try {
// This will disable browsers image resizing facilities in
// order 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 (e2) {
Aloha.Log.error(e2, 'Could not disable enableObjectResizing');
// this is just for others, who will not support disabling enableObjectResizing
}
},
/**
* Human-readable string representation of this.
*
* @hide
*/
toString: function () {
return 'Aloha';
}
});
return Aloha;
});

View File

@@ -0,0 +1,326 @@
/**
* ecma5schims.js - Shim for ECMA5 compatibility
* (http://en.wikipedia.org/wiki/Shim_%28computing%29)
*
* A shim library that implements common functions that are missing on some
* environments in order to complete ECMA5 compatibility across all major
* browsers.
*
* TODO: This code needs to be refactored so as to conform to Aloha coding
* standards. It is also severly lacking in documentation. Please take
* note of: https://github.com/alohaeditor/Aloha-Editor/wiki/Commit-Checklist .
*/
define([], function () {
'use strict';
var $_;
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);
}
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);
}
return obj.replace(/^\s+/, '').replace(/\s+$/, '');
},
// Array methods
// i optional
indexOf: function (find, i) {
var obj = this.obj || this;
var native_method = Array.prototype.indexOf;
if (native_method) {
return native_method.call(obj, find, i);
}
if (i === undefined) {
i = 0;
}
if (i < 0) {
i += obj.length;
}
if (i < 0) {
i = 0;
}
var n;
for (n = obj.length; i < n; i++) {
if (undefined !== obj[i] && obj[i] === find) {
return i;
}
}
return -1;
},
// that optional
forEach: function (action, that) {
var obj = this.obj || this;
var native_method = Array.prototype.forEach;
if (native_method) {
return native_method.call(obj, action, that);
}
var i, n;
for (i = 0, n = obj.length; i < n; i++) {
if (undefined !== obj[i]) {
action.call(that, obj[i], i, obj);
}
}
},
// that optional
// chain optional
map: function (mapper, that, chain) {
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 = [];
var i, n;
for (i = 0, n = obj.length; i < n; i++) {
if (undefined !== obj[i]) {
other[i] = mapper.call(that, obj[i], i, obj);
}
}
result = other;
}
return returnWrapper ? $_(result) : result;
},
// that optional
// chain optional
filter: function (filterFunc, that, chain) {
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,
i,
n;
for (i = 0, n = obj.length; i < n; i++) {
if (undefined !== obj[i] && filterFunc.call(that, v = obj[i], i, obj)) {
other.push(v);
}
}
result = other;
}
return returnWrapper ? $_(result) : result;
},
// that optional
every: function (tester, that) {
var obj = this.obj || this;
var native_method = Array.prototype.every;
if (native_method) {
return native_method.call(obj, tester, that);
}
var i, n;
for (i = 0, n = obj.length; i < n; i++) {
if (undefined !== obj[i] && !tester.call(that, obj[i], i, obj)) {
return false;
}
}
return true;
},
// that optional
some: function (tester, that) {
var obj = this.obj || this;
var native_method = Array.prototype.some;
if (native_method) {
return native_method.call(obj, tester, that);
}
var i, n;
for (i = 0, n = obj.length; i < n; i++) {
if (undefined !== obj[i] && 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);
}
return !!obj.getAttribute(attr);
}
};
$_ = function (obj) {
var Wrapper = function () {};
Wrapper.prototype = shims;
var wrapper_instance = new Wrapper();
wrapper_instance.obj = obj;
return wrapper_instance;
};
var shim;
for (shim in shims) {
if (shims.hasOwnProperty(shim)) {
$_[shim] = shims[shim];
}
}
// Node constants
// http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-1841493061
if (typeof window.Node != 'undefined') {
$_.Node = window.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
};
}
//node.ownerDocument gives the document object, which isn't the right info for a disconnect
function getRootParent(node) {
var parent = null;
if (node) {
do {
parent = node;
} while (null != (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 (null != node.sourceIndex) {
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);
}
// 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 (document.documentElement.compareDocumentPosition) {
return node1.compareDocumentPosition(node2);
}
if (!document.documentElement.contains) {
throw 'neither compareDocumentPosition nor contains is 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 (null != node1.sourceIndex && null != node2.sourceIndex) {
return comparePosition(node1, node2);
}
//document will definitely contain the other node
if (node1 == document) {
return 20;
}
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;
};
$_.getComputedStyle = function (node, style) {
if (window.getComputedStyle) {
return window.getComputedStyle(node, style);
}
if (node.currentStyle) {
return node.currentStyle;
}
return null;
};
return $_;
});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,456 @@
/* ephemera.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
/**
* Provides functions to mark the contents of editables as ephemeral. An
* editable's ephemeral content will be pruned before it is being
* returned by editable.getContents().
*
* It is planned to replace most instances of makeClean() with this
* implementation for improved performance and more importantly, in
* order to have a centralized place that has the control over all
* ephemeral content, which can be leveraged by plugins to provide more
* advanced functionality.
*
* Some examples that would be possible:
* * a HTML source code text box, an interactive tree structure, or
* other kind of DOM visualization, next to the editable, that
* contains just the content of the editable (without ephemeral data)
* and which is updated efficiently in real time after each keystroke.
*
* * change detection algorithms that are able to intelligently ignore
* ephemeral data and which would not trigger unless non-ephemeral
* data is added to the editable.
*
* * When a plugin provides very general functionality over all nodes of
* the DOM, somtimes the plugin may not know what is and what isn't
* supposed to be real content. The functionality provided here makes
* it possible for the plugin to exaclty distinguish real content from
* ephemeral content.
*
* TODO: currently only simple transformations are suppored, like
* marking classes, attributes and elements as ephemeral and removing
* them during the pruning process.
* In the future, support for the block-plugin and custom pruning
* functions should be added. This may be done by letting implementations
* completely control the pruning of a DOM element through a
* function that takes the content+ephemeral-data and returns only
* content - similar to make clean, but for single elements to reduce
* overhead.
*/
define([
'jquery',
'aloha/core',
'aloha/console',
'util/strings',
'util/trees',
'util/arrays',
'util/maps',
'util/dom2',
'util/functions',
'util/misc',
'PubSub'
], function (
$,
Aloha,
console,
Strings,
Trees,
Arrays,
Maps,
Dom,
Functions,
Misc,
PubSub
) {
'use strict';
var ephemeraMap = {
classMap: {
'aloha-cleanme': true,
'aloha-ui-wrapper': true,
'aloha-ui-filler': true,
'aloha-ui-attr': true
},
attrMap: {
'hidefocus': true,
'hideFocus': true,
'tabindex': true,
'tabIndex': true,
'TABLE.contenteditable': true,
'TABLE.contentEditable': true
},
attrRxs: [/^(?:nodeIndex|sizcache|sizset|jquery)[\w\d]*$/i],
pruneFns: []
};
var commonClsSubstr = 'aloha-';
/**
* Checks whether the given classes contain the substring common to
* all ephemeral classes. If the check fails, an warning will be
* logged and the substring will be set to the empty string which
* voids the performance improvement the common substring would
* otherwise have gained.
*/
function checkCommonSubstr(clss) {
var i, len;
for (i = 0, len = clss.length; i < len; i++) {
if (-1 === clss[i].indexOf(commonClsSubstr)) {
console.warn('Class "' + clss[i] + '" was set to be ephemeral,' + 'which hurts peformance.' + ' Add the common substring "' + commonClsSubstr + '" to the class to fix this problem.');
commonClsSubstr = '';
}
}
}
/**
* Registers ephemeral classes.
*
* An ephemeral class is a non-content class that will be pruned
* from the from the result of editable.getContents().
*
* The given classes should contain the string 'aloha-' to get the
* benefit of a performance optimization.
*
* Returns a map that contains all classes that were ever registered
* with this function.
*
* Multiple classes may be specified. If none are specified, just
* returns the current ephemeral classes map without modifying it.
*
* Also see ephemera().
*/
function classes() {
var clss = Array.prototype.slice.call(arguments);
Maps.fillKeys(ephemeraMap.classMap, clss, true);
checkCommonSubstr(clss);
PubSub.pub('aloha.ephemera.classes', {
ephemera: ephemeraMap,
newClasses: clss
});
}
/**
* Registers ephemeral attributes by attribute name.
*
* Similar to classes() except applies to entire attributes instead
* of individual classes in the class attribute.
*/
function attributes() {
var attrs = Array.prototype.slice.call(arguments);
Maps.fillKeys(ephemeraMap.attrMap, attrs, true);
PubSub.pub('aloha.ephemera.attributes', {
ephemera: ephemeraMap,
newAttributes: attrs
});
}
/**
* Merges a map containing values to identify ephemeral content into
* a global registry.
*
* The given map may have the following entries
* classMap - a map from class name to the value true
* attrMap - a map from attribute name to the value true; attribute
* names may be optionally prefixed with "ELEMENT.",
* where ELEMENT is the name of an element in uppercase,
* to prune only from specific elements. An element name prefix
* should always be specified if it is known, and if
* multiple are known, multiple entries with separate
* element prefixes should be made instead of a single
* entry without - preserve information for refactoring.
* attrRxs - an array of regexes in object form (/[a-z].../ and not "[a-z]...")
* pruneFns - an array of functions that will be called at each pruning step.
*
* Returns the global registry, which has the same structure as above.
*
* When a DOM tree is pruned with prune(elem) without an emap
* argument, the global registry maintained with classes()
* attributes() and ephemera() is used as a default map. If an emap
* argument is specified, the global registry will be ignored and
* the emap argument will be used instead.
*
* When a DOM tree is pruned with prune()
* * classes specified by classMap will be removed
* * attributes specified by attrMap or attrRxs will be removed
* * functions specified by pruneFns will be called as the DOM tree
* is descended into (pre-order), with each node (element, text,
* etc.) as a single argument. The function is free to modify the
* element and return it, or return a new element which will
* replace the given element in the pruned tree. If null or
* undefined is returned, the element will be removed from the
* tree. As per contract of Maps.walkDomInplace, it is allowed to
* insert/remove children in the parent node as long as the given
* node is not removed.
*
* Also see classes() and attributes().
*
* Note that removal of attributes doesn't always work on IE7 (in
* rare special cases). The dom-to-xhtml plugin can reliably remove
* ephemeral attributes during the serialization step.
*/
function ephemera(emap) {
if (emap) {
if (emap.classMap) {
$.extend(ephemeraMap.classMap, emap.classMap);
}
if (emap.attrMap) {
$.extend(ephemeraMap.attrMap, emap.attrMap);
}
if (emap.attrRxs) {
ephemeraMap.attrRxs = ephemeraMap.attrRxs.concat(emap.attrRxs);
}
if (emap.pruneFns) {
ephemeraMap.pruneFns = ephemeraMap.pruneFns.concat(emap.pruneFns);
}
PubSub.pub('aloha.ephemera', {
ephemera: ephemeraMap,
newEphemera: emap
});
}
return ephemeraMap;
}
/**
* Marks an element as ephemeral.
*
* The element will be completely removed when the prune function is
* called on it.
*/
function markElement(elem) {
$(elem).addClass('aloha-cleanme');
}
/**
* Marks the attribute of an element as ephemeral.
*
* The attribute will be removed from the element when the prune
* function is called on it.
*
* Multiple attributes can be passed at the same time be separating
* them with a space.
*/
function markAttribute(elem, attr) {
elem = $(elem);
var data = elem.attr('data-aloha-ui-attr');
data = (null == data || '' === data ? attr : data + ' ' + attr);
elem.attr('data-aloha-ui-attr', data);
elem.addClass('aloha-ui-attr');
}
/**
* Marks an element as a ephemeral, excluding subnodes.
*
* The element will be removed when the prune function is called on
* it, but any children of the wrapper element will remain in its
* place.
*
* A wrapper is an element that wraps a single non-ephemeral
* element. A filler is an element that is wrapped by a single
* non-ephemeral element. This distinction is not important for the
* prune function, which behave the same for both wrappers and
* fillers, but it makes it easier to build more advanced content
* inspection algorithms (also see note at the header of ephemeral.js).
*
* NB: a wrapper element must not wrap a filler element. Wrappers
* and fillers are ephermeral. A wrapper must always wrap a
* single _non-ephemeral_ element, and a filler must always fill
* a single _non-ephemeral_ element.
*/
function markWrapper(elem) {
$(elem).addClass('aloha-ui-wrapper');
}
/**
* Marks an element as ephemeral, excluding subnodes.
*
* See wrapper()
*/
function markFiller(elem) {
$(elem).addClass('aloha-ui-filler');
}
/**
* Prunes attributes marked as ephemeral with Ephemera.attributes()
* from the given element.
*/
function pruneMarkedAttrs(elem) {
var $elem = $(elem);
var data = $elem.attr('data-aloha-ui-attr');
var i;
var attrs;
$elem.removeAttr('data-aloha-ui-attr');
if (typeof data === 'string') {
attrs = Strings.words(data);
for (i = 0; i < attrs.length; i++) {
$elem.removeAttr(attrs[i]);
}
}
}
/**
* Determines whether the given attribute of the given element is
* ephemeral according to the given emap.
* See Ephemera.ephemera() for an explanation of attrMap and attrRxs.
*/
function isAttrEphemeral(elem, attrName, attrMap, attrRxs) {
return attrMap[attrName] || Misc.anyRx(attrRxs, attrName) || attrMap[elem.nodeName + '.' + attrName];
}
/**
* Prunes attributes specified with either emap.attrMap or emap.attrRxs.
* See ephemera().
*/
function pruneEmapAttrs(elem, emap) {
var $elem = null,
attrs = Dom.attrNames(elem),
name,
i,
len;
for (i = 0, len = attrs.length; i < len; i++) {
name = attrs[i];
if (isAttrEphemeral(elem, name, emap.attrMap, emap.attrRxs)) {
$elem = $elem || $(elem);
$elem.removeAttr(name);
}
}
}
/**
* Prunes an element of attributes and classes or removes the
* element by returning false.
*
* Elements attributes and classes can either be marked as
* ephemeral, in which case the element itself will contain the
* prune-info, or they can be specified as ephemeral with the given
* emap.
*
* See ephemera() for an explanation of the emap argument.
*/
function pruneElem(elem, emap) {
var className = elem.className;
if (className && -1 !== className.indexOf(commonClsSubstr)) {
var classes = Strings.words(className);
// Ephemera.markElement()
if (-1 !== Arrays.indexOf(classes, 'aloha-cleanme')) {
$.removeData(elem); // avoids memory leak
return false; // removes the element
}
// Ephemera.markWrapper() and Ephemera.markFiller()
if (-1 !== Arrays.indexOf(classes, 'aloha-ui-wrapper') || -1 !== Arrays.indexOf(classes, 'aloha-ui-filler')) {
Dom.moveNextAll(elem.parentNode, elem.firstChild, elem.nextSibling);
$.removeData(elem);
return false;
}
// Ephemera.markAttribute()
if (-1 !== Arrays.indexOf(classes, 'aloha-ui-attr')) {
pruneMarkedAttrs(elem);
}
// Ephemera.classes() and Ehpemera.ephemera({ classMap: {} })
var persistentClasses = Arrays.filter(classes, function (cls) {
return !emap.classMap[cls];
});
if (persistentClasses.length !== classes.length) {
if (0 === persistentClasses.length) {
// Removing the attributes is dangerous. Aloha has a
// jquery patch in place to fix some issue.
$(elem).removeAttr('class');
} else {
elem.className = persistentClasses.join(' ');
}
}
}
// Ephemera.attributes() and Ephemera.ephemera({ attrMap: {}, attrRxs: {} })
pruneEmapAttrs(elem, emap);
return true;
}
/**
* Called for each node during the pruning of a DOM tree.
*/
function pruneStep(emap, step, node) {
if (1 === node.nodeType) {
if (!pruneElem(node, emap)) {
return [];
}
node = Trees.walkDomInplace(node, step);
}
// Ephemera.ephemera({ pruneFns: [] })
node = Arrays.reduce(emap.pruneFns, node, Arrays.applyNotNull);
if (!node) {
return [];
}
return [node];
}
/**
* Prunes the given element of all ephemeral data.
*
* Elements marked with Ephemera.markElement() will be removed.
* Attributes marked with Ephemera.markAttribute() will be removed.
* Elements marked with Ephemera.markWrapper() or
* Ephemera.markFiller() will be replaced with their children.
*
* See ephemera() for an explanation of the emap argument.
*
* All properties of emap, if specified, are required, but may be
* empty.
*
* The element is modified in-place and returned.
*/
function prune(elem, emap) {
emap = emap || ephemeraMap;
function pruneStepClosure(node) {
return pruneStep(emap, pruneStepClosure, node);
}
return pruneStepClosure(elem)[0];
}
if (Aloha.settings.ephemera) {
ephemera(Aloha.settings.ephemera);
}
return {
ephemera: ephemera,
classes: classes,
attributes: attributes,
markElement: markElement,
markAttribute: markAttribute,
markWrapper: markWrapper,
markFiller: markFiller,
prune: prune,
isAttrEphemeral: isAttrEphemeral
};
});

View File

@@ -0,0 +1,29 @@
/* ierange-m2.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
define(['vendor/ierange-m2'], function () {
'use strict';
});

View File

@@ -0,0 +1,525 @@
/* jquery.aloha.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
/**
* IMPORTANT!
* Don't add any more custom jquery extensions here.
* Instead use the define(...) mechanism to define a module and to
* import it where you need it.
*/
define([
'aloha/core',
'aloha/selection',
'jquery',
'aloha/console'
], function (
Aloha,
Selection,
jQuery,
console
) {
'use strict';
var 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.warn('The jquery object did not contain any valid elements.'); // die silent
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;
}
return $el[0].isContentEditable;
}
if (b === '') {
$el.removeAttr(ce);
} else {
if (b && b !== 'false') {
b = 'true';
} else {
b = 'false';
}
$el.attr(ce, b);
}
return $el;
};
/**
* jQuery Aloha Plugin.
*
* Makes the elements in a jQuery selection set Aloha editables.
*
* @return jQuery container of holding DOM elements that have been
* aloha()fied.
* @api
*/
jQuery.fn.aloha = function () {
var $elements = this;
Aloha.bind('aloha-plugins-loaded', function () {
$elements.each(function (_, elem) {
if (!Aloha.isEditable(elem)) {
new Aloha.Editable(jQuery(elem)).init();
}
});
});
return $elements;
};
/**
* 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;
}
try {
// Gecko-based browsers, Safari, Opera.
return (new XMLSerializer()).serializeToString(el);
} catch (e) {
try {
// Internet Explorer.
return el.xml;
} catch (e2) {}
}
};
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) {
var i, childLength;
if ((el.nodeType === 3 && jQuery.trim(el.data) && !includeEmptyTextNodes) || (el.nodeType === 3 && includeEmptyTextNodes) || (el.nodeName == "BR" && !excludeBreaks)) {
ret.push(el);
} else {
for (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 (arg1, arg2) {
var options, name, src, copy, copyIsArray, clone,
start = 1,
target = arg1 || {},
length = arguments.length,
deep = false,
i;
// Handle a deep copy situation
if (typeof target === "boolean") {
deep = target;
target = arg2 || {};
// skip the boolean and the target
start = 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 === start) {
target = this;
--start;
}
for (i = start; i < length; i++) {
// Only deal with non-null/undefined values
if ((options = arguments[i]) != null) {
// Extend the base object
for (name in options) {
if (options.hasOwnProperty(name)) {
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) || true === (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 Hotkeys Plugin
* Copyright 2010, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Based upon the plugin by Tzury Bar Yochay:
* http://github.com/tzuryby/hotkeys
*
* Original idea by:
* Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/
*/
jQuery.hotkeys = {
version: "0.8",
specialKeys: {
8: "backspace",
9: "tab",
13: "return",
16: "shift",
17: "ctrl",
18: "alt",
19: "pause",
20: "capslock",
27: "esc",
32: "space",
33: "pageup",
34: "pagedown",
35: "end",
36: "home",
37: "left",
38: "up",
39: "right",
40: "down",
45: "insert",
46: "del",
96: "0",
97: "1",
98: "2",
99: "3",
100: "4",
101: "5",
102: "6",
103: "7",
104: "8",
105: "9",
106: "*",
107: "+",
109: "-",
110: ".",
111: "/",
112: "f1",
113: "f2",
114: "f3",
115: "f4",
116: "f5",
117: "f6",
118: "f7",
119: "f8",
120: "f9",
121: "f10",
122: "f11",
123: "f12",
144: "numlock",
145: "scroll",
191: "/",
224: "meta"
},
shiftNums: {
"`": "~",
"1": "!",
"2": "@",
"3": "#",
"4": "$",
"5": "%",
"6": "^",
"7": "&",
"8": "*",
"9": "(",
"0": ")",
"-": "_",
"=": "+",
";": ": ",
"'": "\"",
",": "<",
".": ">",
"/": "?",
"\\": "|"
}
};
function applyKeyHandler(handler, context, args, event) {
// Don't fire in text-accepting inputs that we didn't directly bind to
if (context !== event.target && (/textarea|input|select/i.test(event.target.nodeName) || event.target.type === "text")) {
return;
}
return handler.apply(context, args);
}
function keyHandler(handleObj) {
var origHandler, keys, handle, i;
// Only care when a possible input has been specified
if (typeof handleObj.data !== "string") {
return;
}
origHandler = handleObj.handler;
keys = handleObj.data.toLowerCase().split(" ");
handle = {};
for (i = 0; i < keys.length; i++) {
handle[keys[i]] = true;
}
handleObj.handler = function (event) {
// The original comment that was added with this condition says:
// "Don't fire in contentEditable true elements"
// But this is incorrect.
// What this condition does is it skips hotkey events for
// any target unless it is directly bound.
// The condition event.target.contentEditable !== true will
// always be true, because contentEditable is a string
// attribute that is never strictly equal true.
//if (this !== event.target && event.target.contentEditable !== true) {
//return;
//}
// Below is what this condition really does. Ideally, I'd
// like to remove this condition since it was not there in
// the original implementation by John Resig and it could
// interfere with other plugins, but when I removed it, I
// was unable to input any space characters into an
// editable.
// TODO figure out a way to safely remove this
if (this !== event.target) {
return;
}
// Keypress represents characters, not special keys
var special = event.type !== "keypress" && jQuery.hotkeys.specialKeys[event.which],
modif = "",
character;
// check combinations (alt|ctrl|shift+anything)
if (event.altKey && special !== "alt") {
modif += "alt+";
}
if (event.ctrlKey && special !== "ctrl") {
modif += "ctrl+";
}
// TODO: Need to make sure this works consistently across platforms
if (event.metaKey && !event.ctrlKey && special !== "meta") {
modif += "meta+";
}
if (event.shiftKey && special !== "shift") {
modif += "shift+";
}
if (special) {
if (handle[modif + special]) {
return applyKeyHandler(origHandler, this, arguments, event);
}
} else {
character = String.fromCharCode(event.which).toLowerCase();
if (handle[modif + character]) {
return applyKeyHandler(origHandler, this, arguments, event);
}
if (handle[modif + jQuery.hotkeys.shiftNums[character]]) {
return applyKeyHandler(origHandler, this, arguments, event);
}
// "$" can be triggered as "Shift+4" or "Shift+$" or just "$"
if (modif === "shift+") {
if (handle[jQuery.hotkeys.shiftNums[character]]) {
return applyKeyHandler(origHandler, this, arguments, event);
}
}
}
};
}
jQuery.each(['keydown', 'keyup', 'keypress'], function () {
jQuery.event.special[this] = {
add: keyHandler
};
});
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
define({
"plugin.abbr.floatingmenu.tab.abbr": "Abreviació",
"floatingmenu.tab.format": "Format",
"floatingmenu.tab.insert": "Insereix",
"yes": "Sí",
"no": "No",
"cancel": "Cancel·la",
"repository.no_item_found": "No s\'ha trobat cap element.",
"repository.loading": "S\'està carregant",
"repository.no_items_found_yet": "Encara no s\'ha trobat cap element..."
});

View File

@@ -0,0 +1,11 @@
define({
"plugin.abbr.floatingmenu.tab.abbr": "Abkürzung",
"floatingmenu.tab.format": "Formatieren",
"floatingmenu.tab.insert": "Einfügen",
"yes": "Ja",
"no": "Nein",
"cancel": "Abbrechen",
"repository.no_item_found": "Keinen Eintrag gefunden.",
"repository.loading": "Es wird geladen ...",
"repository.no_items_found_yet": "Suche nach Einträgen ..."
});

View File

@@ -0,0 +1,20 @@
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..."
},
"ca": true,
"de": true,
"mk": true,
"pt-br": true,
"ru": true,
"uk": true,
"zh-hans": true
});

View File

@@ -0,0 +1,11 @@
define({
"plugin.abbr.floatingmenu.tab.abbr": "Кратенка",
"floatingmenu.tab.format": "Изглед",
"floatingmenu.tab.insert": "Вметни",
"yes": "Да",
"no": "Не",
"cancel": "Откажи",
"repository.no_item_found": "Не е најдено.",
"repository.loading": "Се вчитува",
"repository.no_items_found_yet": "Сеуште ништо не е најдено..."
});

View File

@@ -0,0 +1,11 @@
define({
"plugin.abbr.floatingmenu.tab.abbr": "Abreviação",
"floatingmenu.tab.format": "Formatar",
"floatingmenu.tab.insert": "Inserir",
"yes": "Sim",
"no": "Não",
"cancel": "Cancelar",
"repository.no_item_found": "Nenhum item encontrado.",
"repository.loading": "Carregando",
"repository.no_items_found_yet": "Nenhum item encontrado ainda..."
});

View File

@@ -0,0 +1,11 @@
define({
"plugin.abbr.floatingmenu.tab.abbr": "Аббревиатура",
"floatingmenu.tab.format": "Форматирование",
"floatingmenu.tab.insert": "Вставить",
"yes": "Да",
"no": "Нет",
"cancel": "Отмена",
"repository.no_item_found": "Объект не найден",
"repository.loading": "Загрузка",
"repository.no_items_found_yet": "Пока что ничего не найдено..."
});

View File

@@ -0,0 +1,11 @@
define({
"plugin.abbr.floatingmenu.tab.abbr": "Абревіатура",
"floatingmenu.tab.format": "Форматування",
"floatingmenu.tab.insert": "Вставити",
"yes": "Так",
"no": "Ні",
"cancel": "Відмінити",
"repository.no_item_found": "Нічого не знайдено",
"repository.loading": "Завантаження",
"repository.no_items_found_yet": "Поки що нічого не знайдено..."
});

View File

@@ -0,0 +1,114 @@
/* observable.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
define([
'jquery'
], function (
jQuery,
undefined
) {
"use strict";
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 || 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

@@ -0,0 +1,281 @@
/* plugin.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
define([
'aloha/core',
'jquery',
'util/class',
'aloha/pluginmanager',
'aloha/console'
], function (
Aloha,
jQuery,
Class,
PluginManager,
console
) {
"use strict";
/**
* 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 plugin = this;
var satisfied = true;
jQuery.each(plugin.dependencies, function (i, dependency) {
if (!Aloha.isPluginLoaded(dependency.toString())) {
satisfied = false;
console.error('plugin.' + plugin.name,
'Required plugin "' + dependency + '" not found.');
return false;
}
});
return satisfied;
},
/**
* 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) {
var k;
if (obj.is(selector)) {
configSpecified = true;
if (selectorConfig instanceof Array) {
configObj = [];
configObj = jQuery.merge(configObj, selectorConfig);
} else if (typeof selectorConfig === "object") {
configObj = {};
configObj['aloha-editable-selector'] = selector;
for (k in selectorConfig) {
if (selectorConfig.hasOwnProperty(k)) {
if (selectorConfig[k] instanceof Array) {
//configObj[k] = [];
//configObj[k] = jQuery.extend(true, configObj[k], that.config[k], selectorConfig[k]);
configObj[k] = selectorConfig[k];
} 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;
},
/**
* 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

@@ -0,0 +1,195 @@
/* pluginmanager.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
// Do not add dependencies that require depend on aloha/core
define([
'jquery',
'util/class'
], function (
$,
Class
) {
'use strict';
var Aloha = window.Aloha;
/**
* For each plugin setting, assigns it into its corresponding plugin.
*
* @param {Array.<Plugin>} plugins
* @param {object<string, object>} settings
*/
function mapSettingsIntoPlugins(plugins, settings) {
var plugin;
for (plugin in settings) {
if (settings.hasOwnProperty(plugin) && plugins[plugin]) {
plugins[plugin].settings = settings[plugin] || {};
}
}
}
/**
* Retrieves a set of plugins or the given `names' list, from among those
* specified in `plugins'.
*
* @param {object<string, object>} plugins
* @param {Array.<string>} names List of plugins names.
* @return {Array.<Plugins>} List of available plugins.
*/
function getPlugins(plugins, names) {
var available = [];
var plugin;
var i;
for (i = 0; i < names.length; i++) {
plugin = plugins[names[i]];
if (plugin) {
available.push(plugin);
}
}
return available;
}
/**
* Initializes the plugins in the given list.
*
* @param {Array.<Plugins>} plugins Plugins to initialize.
* @param {function} callback Function to invoke once all plugins have been
* successfully initialized.
*/
function initializePlugins(plugins, callback) {
var numToEnable = plugins.length;
var onInit = function () {
if (0 === --numToEnable && callback) {
callback();
}
};
var i;
var ret;
var plugin;
for (i = 0; i < plugins.length; i++) {
plugin = plugins[i];
plugin.settings = plugin.settings || {};
if (typeof plugin.settings.enabled === 'undefined') {
plugin.settings.enabled = true;
}
if (plugin.settings.enabled && plugin.checkDependencies()) {
ret = plugin.init();
if (ret && typeof ret.done === 'function') {
ret.done(onInit);
} else {
onInit();
}
}
}
}
/**
* The Plugin Manager controls the lifecycle of all Aloha Plugins.
*
* @namespace Aloha
* @class PluginManager
* @singleton
*/
return new (Class.extend({
plugins: {},
/**
* Initialize all registered plugins.
*
* @param {function} next Callback to invoke after plugins have
* succefully initialized.
* @param {Array.<string>} enabled A list of plugin names which are to
* be enable.
*/
init: function (next, enabled) {
var manager = this;
var plugins = manager.plugins;
mapSettingsIntoPlugins(plugins,
Aloha && Aloha.settings && Aloha.settings.plugins);
// Because all plugins are enabled by default if specific plugins
// are not specified.
var plugin;
if (!plugins || 0 === enabled.length) {
enabled = [];
for (plugin in plugins) {
if (plugins.hasOwnProperty(plugin)) {
enabled.push(plugin);
}
}
}
initializePlugins(getPlugins(plugins, enabled), 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';
}
}))();
});

View File

@@ -0,0 +1,30 @@
/* rangy-core.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
define('aloha/rangy-core', ['jquery', 'vendor/rangy-core'], function (jQuery) {
'use strict';
return window.rangy;
});

View File

@@ -0,0 +1,137 @@
/* registry.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
/*global define:true */
/**
* Registry base class.
* TODO: document that it also contains Observable.
*
*/
define([
'jquery',
'aloha/observable',
'util/class'
], function (
jQuery,
Observable,
Class
) {
"use strict";
return Class.extend(Observable, {
/**
* Object containing the registered entries by key.
*/
_entries: null,
/**
* Array containing the registered ids in order
* of registry
*/
_ids: null,
_constructor: function () {
this._entries = {};
this._ids = [];
},
/**
* Register an entry with an id
*
* @event register
* @param id id of the registered entry
* @param entry registered entry
*/
register: function (id, entry) {
// TODO check whether an entry with the id is already registered
this._entries[id] = entry;
this._ids.push(id);
this.trigger('register', entry, id);
},
/**
* Unregister the entry with given id
*
* @event unregister
* @param id id of the registered entry
*/
unregister: function (id) {
// TODO check whether an entry was registered
var i, oldEntry = this._entries[id];
delete this._entries[id];
for (i in this._ids) {
if (this._ids.hasOwnProperty(i) && this._ids[i] === id) {
this._ids.splice(i, 1);
break;
}
}
this.trigger('unregister', oldEntry, id);
},
/**
* Get the entry registered with the given id
*
* @param id id of the registered entry
* @return registered entry
*/
get: function (id) {
return this._entries[id];
},
/**
* Check whether an entry was registered with given id
*
* @param id id to check
* @return true if an entry was registered, false if not
*/
has: function (id) {
return (this._entries[id] ? true : false);
},
/**
* Get an object mapping the ids (properties) to the registered entries
* Note, that iterating over the properties of the returned object
* will return the entries in an unspecified order
*
* @return object containing the registered entries
*/
getEntries: function () {
// clone the entries so the user does not accidentally modify our _entries object.
return jQuery.extend({}, this._entries);
},
/**
* Get the ids of the registered objects as array.
* The array will contain the ids in order of registry
*
* @return array if registered ids
*/
getIds: function () {
return jQuery.extend([], this._ids);
}
});
});

View File

@@ -0,0 +1,255 @@
/* repository.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
define([
'aloha/core',
'util/class',
'aloha/repositorymanager'
], function (
Aloha,
Class,
RepositoryManager
) {
"use strict";
// var
// $ = jQuery,
// GENTICS = window.GENTICS,
// Aloha = window.Aloha,
// Class = window.Class;
/**
* Abstract Repository Class. Implement that class for your own repository.
* @namespace Aloha.Repository
* @class Repository
* @constructor
* @param {String} repositoryId unique repository identifier
* @param {String} repositoryName (optional) is the displyed name for this Repository instance
*/
var AbstractRepository = Class.extend({
_constructor: function (repositoryId, repositoryName) {
/**
* @property repositoryId is the unique Id for this Repository instance
*/
this.repositoryId = repositoryId;
/**
* contains the repository's settings object
* @property settings {Object} the repository's settings stored in an object
*/
this.settings = {};
/**
* @property repositoryName is the name for this Repository instance
*/
this.repositoryName = repositoryName || repositoryId;
RepositoryManager.register(this);
},
/**
* Init method of the repository. Called from Aloha Core to initialize this repository
* @return void
* @hide
*/
init: function () {},
/**
* Searches a repository for object items matching queryString if none found returns null.
* The returned object items must be an array of Aloha.Repository.Object
*
<pre><code>
// simple delicious implementation
Aloha.Repositories.myRepository.query = function (params, callback) {
// make local var of this to use in ajax function
var that = this;
// handle each word as tag
var tags = p.queryString.split(' ');
// if we have a query and no tag matching return
if ( p.queryString && tags.length == 0 ) {
callback.call( that, []);
return;
}
// no handling of objectTypeFilter, filter, inFolderId, etc...
// in real implementation you should handle all parameters
jQuery.ajax({ type: "GET",
dataType: "jsonp",
url: 'http://feeds.delicious.com/v2/json/' + tags.join('+'),
success: function(data) {
var items = [];
// convert data to Aloha objects
for (var i = 0; i < data.length; i++) {
if (typeof data[i] != 'function' ) {
items.push(new Aloha.Repository.Document ({
id: data[i].u,
name: data[i].d,
repositoryId: that.repositoryId,
type: 'website',
url: data[i].u
}));
}
}
callback.call( that, items);
}
});
};
</code></pre>
*
* @param {object} params object with properties
* <div class="mdetail-params"><ul>
* <li><code> queryString</code> : String <div class="sub-desc">The query string for full text search</div></li>
* <li><code> objectTypeFilter</code> : array (optional) <div class="sub-desc">Object types that will be returned.</div></li>
* <li><code> filter</code> : array (optional) <div class="sub-desc">Attributes that will be returned.</div></li>
* <li><code> inFolderId</code> : boolean (optional) <div class="sub-desc">This is indicates whether or not a candidate object is a child-object of the folder object identified by the given inFolderId (objectId).</div></li>
* <li><code> inTreeId</code> : boolean (optional) <div class="sub-desc">This indicates whether or not a candidate object is a descendant-object of the folder object identified by the given inTreeId (objectId).</div></li>
* <li><code> orderBy</code> : array (optional) <div class="sub-desc">ex. [{lastModificationDate:DESC, name:ASC}]</div></li>
* <li><code> maxItems</code> : Integer (optional) <div class="sub-desc">number items to return as result</div></li>
* <li><code> skipCount</code> : Integer (optional) <div class="sub-desc">This is tricky in a merged multi repository scenario</div></li>
* <li><code> renditionFilter</code> : array (optional) <div class="sub-desc">Instead of termlist an array of kind or mimetype is expected. If null or array.length == 0 all renditions are returned. See http://docs.oasis-open.org/cmis/CMIS/v1.0/cd04/cmis-spec-v1.0.html#_Ref237323310 for renditionFilter</div></li>
* </ul></div>
* @param {function} callback this method must be called with all result items</div></li>
*/
query: null,
/*
query: function( params, callback ) {
if (typeof callback === 'function') {
callback([]);
}
},
*/
/**
* Returns all children of a given motherId.
*
* @param {object} params object with properties
* <div class="mdetail-params"><ul>
* <li><code> objectTypeFilter</code> : array (optional) <div class="sub-desc">Object types that will be returned.</div></li>
* <li><code> filter</code> : array (optional) <div class="sub-desc">Attributes that will be returned.</div></li>
* <li><code> inFolderId</code> : boolean (optional) <div class="sub-desc">This indicates whether or not a candidate object is a child-object of the folder object identified by the given inFolderId (objectId).</div></li>
* <li><code> orderBy</code> : array (optional) <div class="sub-desc">ex. [{lastModificationDate:DESC, name:ASC}]</div></li>
* <li><code> maxItems</code> : Integer (optional) <div class="sub-desc">number items to return as result</div></li>
* <li><code> skipCount</code> : Integer (optional) <div class="sub-desc">This is tricky in a merged multi repository scenario</div></li>
* <li><code> renditionFilter</code> : array (optional) <div class="sub-desc">Instead of termlist an array of kind or mimetype is expected. If null or array.length == 0 all renditions are returned. See http://docs.oasis-open.org/cmis/CMIS/v1.0/cd04/cmis-spec-v1.0.html#_Ref237323310 for renditionFilter</div></li>
* </ul></div>
* @param {function} callback this method must be called with all result items
*/
getChildren: null,
/*
getChildren: function( params, callback ) {
if (typeof callback === 'function') {
callback([]);
}
},
*/
/**
* Make the given jQuery object (representing an object marked as object of this type)
* clean. All attributes needed for handling should be removed.
*
<pre><code>
Aloha.Repositories.myRepository.makeClean = function (obj) {
obj.removeAttr('data-myRepository-name');
};
</code></pre>
* @param {jQuery} obj jQuery object to make clean
* @return void
*/
makeClean: function (obj) {},
/**
* This method will be called when a user chooses an item from a repository and wants
* to insert this item in his content.
* Mark or modify an object as needed by that repository for handling, processing or identification.
* Objects can be any DOM object as A, SPAN, ABBR, etc. or
* special objects such as aloha-aloha_block elements.
* (see http://dev.w3.org/html5/spec/elements.html#embedding-custom-non-visible-data)
*
<pre><code>
Aloha.Repositories.myRepository.markObject = function (obj, resourceItem) {
obj.attr('data-myRepository-name').text(resourceItem.name);
};
</code></pre>
*
*
* @param obj jQuery target object to which the repositoryItem will be applied
* @param repositoryItem The selected item. A class constructed from Document or Folder.
* @return void
*/
markObject: function (obj, repositoryItem) {},
/**
* Set a template for rendering objects of this repository
* @param {String} template
* @return void
* @method
*/
setTemplate: function (template) {
if (template) {
this.template = template;
} else {
this.template = null;
}
},
/**
* Checks whether the repository has a template
* @return {boolean} true when the repository has a template, false if not
* @method
*/
hasTemplate: function () {
return this.template ? true : false;
},
/**
* Get the parsed template
* @return {Object} parsed template
* @method
*/
getTemplate: function () {
return this.template;
},
/**
* Get the repositoryItem with given id
* @param itemId {String} id of the repository item to fetch
* @param callback {function} callback function
* @return {Aloha.Repository.Object} item with given id
*/
getObjectById: function (itemId, callback) {
return true;
}
});
// expose the AbstractRepository
Aloha.AbstractRepository = AbstractRepository;
return AbstractRepository;
});

View File

@@ -0,0 +1,742 @@
/* repositorymanager.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
define([
'jquery',
'util/class',
'aloha/core',
'aloha/console',
'aloha/repositoryobjects' // Provides Aloha.RepositoryFolder
], function (
$,
Class,
Aloha,
Console,
__unused__
) {
'use strict';
/**
* Given an input set, returns a new set which is a range of the input set
* that maps to the given predicate.
*
* Prefers native Array.prototype.filter() where available (after JavaScript
* 1.6).
*
* @param {Array} domain
* @param {function:boolean} predicate
* @return {Array} Sub set of domain
*/
var filter = (function (native) {
return (native
? function (domain, predicate) {
return domain.filter(predicate);
}
: function (domain, predicate) {
var codomain = [];
var i;
for (i = 0; i < domain.length; i++) {
if (predicate(domain[i])) {
codomain.push(domain[i]);
}
}
return codomain;
}
);
}('filter' in Array.prototype));
/**
* Bundles results, and meta information in preparation for the JSON Reader.
*
* Used with query().
*
* @param {Array.<Document|Folder>} items Results, collected from all
* repositories.
* @param {object<string, number>} meta Optional object containing metainfo.
* @return {object} Result object.
*/
function bundle(items, meta) {
var result = {
items: items,
results: items.length
};
if (meta) {
result.numItems = meta.numItems;
result.hasMoreItems = meta.hasMoreItems;
result.timeout = meta.timeout;
}
return result;
}
/**
* Passes all the results we have collected to the client through the
* callback it specified.
*
* TODO: Implement sorting based on repository specification sort
* items by weight.
* items.sort(function (a, b) {
* return (b.weight || 0) - (a.weight || 0);
* });
*
* @param {function} callback Callback specified by client when invoking
* the query method.
* @param {Array.<Document|Folder>|object<string, number>} results
*/
function report(callback, results) {
callback(results);
}
/**
* Predicates; used to filter lists of repositories based on whether they
* implement a method or not.
*
* @type {object<string, function(Repository):boolean}
*/
var repositoryFilters = {
query: function (repository) {
return typeof repository.query === 'function';
},
getChildren: function (repository) {
return typeof repository.getChildren === 'function';
},
getSelectedFolder: function (repository) {
return typeof repository.getSelectedFolder === 'function';
}
};
/**
* Repository Manager.
*
* @namespace Aloha
* @class RepositoryManager
* @singleton
*/
var RepositoryManager = Class.extend({
repositories: [],
settings: (Aloha.settings && Aloha.settings.repositories) || {},
initialized: false,
/**
* Initializes all registered repositories.
*
* ???
* |
* v
*
* Warning: testing has shown that repositories are maybe not loaded yet
* (found that case in IE7), so don't rely on that in this init
* function.
*
* ^
* |
* !!!
*/
init: function () {
var manager = this;
if (typeof manager.settings.timeout === 'undefined') {
manager.settings.timeout = 5000;
}
var i;
for (i = 0; i < manager.repositories.length; i++) {
manager.initRepository(manager.repositories[i]);
}
manager.initialized = true;
},
/**
* Registers a Repository.
*
* If the repositorie is registered after the Repository Manager is
* initialized it will be automatically initialized.
*
* @param {Repository} repository Repository to register.
*/
register: function (repository) {
var manager = this;
if (!manager.getRepository(repository.repositoryId)) {
manager.repositories.push(repository);
if (manager.initialized) {
manager.initRepository(repository);
}
} else {
Console.warn(manager, 'A repository with name "'
+ repository.repositoryId
+ '" already registerd. Ignoring this.');
}
},
/**
* Initializes a repository.
*
* @param {Repository} repository Repository to initialize.
*/
initRepository: function (repository) {
var manager = this;
if (!repository.settings) {
repository.settings = {};
}
if (manager.settings[repository.repositoryId]) {
$.extend(repository.settings,
manager.settings[repository.repositoryId]);
}
repository.init();
},
/**
* Returns the repository identified by repositoryId.
*
* @param {String} id Id of repository to retrieve.
* @return {Repository|null} Repository or null if none with the given
* id is found.
*/
getRepository: function (id) {
var manager = this;
var i;
for (i = 0; i < manager.repositories.length; i++) {
if (manager.repositories[i].repositoryId === id) {
return manager.repositories[i];
}
}
return null;
},
/**
* Searches all repositories for repositoryObjects matching query and
* repositoryObjectType.
*
* <pre><code>
* // Example:
* var params = {
* queryString: 'hello',
* objectTypeFilter: ['website'],
* filter: null,
* inFolderId: null,
* orderBy: null,
* maxItems: null,
* skipCount: null,
* renditionFilter: null,
* repositoryId: null
* };
* Aloha.RepositoryManager.query(params, function (items) {
* Console.log(items);
* });
* </code></pre>
*
* @param {object<string, mixed>} params
*
* queryString: String The query string for full text
* search.
* objectTypeFilter: Array (optional) Object types to be retrieved.
* filter: Array (optional) Attributes that will be
* included.
* inFolderId: boolean (optional) Whether or not a candidate
* object is a child-object of the
* folder object identified by the
* given inFolderId (objectId).
* inTreeId: boolean (optional) This indicates whether or
* not a candidate object is a
* descendant-object of the folder
* object identified by the given
* inTreeId (objectId).
* orderBy: Array (optional) example: [{
* lastModificationDate: 'DESC',
* name: 'ASC'
* }]
* maxItems: number (optional) Number of items to include in
* result set.
* skipCount: number (optional) This is tricky in a merged
* multi repository scenario.
* renditionFilter: Array (optional) Instead of termlist, an
* array of kind or mimetype is
* expected. If null or an empty
* set, then all renditions are
* returned. See
* http://docs.oasis-open.org/cmis/CMIS/v1.0/cd04/cmis-spec-v1.0.html#_Ref237323310
* for renditionFilter.
*
* @param {function(Document|Folder)} callback Function to be invoked
* after the repository
* manager has finished
* querying all
* repositories.
*/
query: function (params, callback) {
var manager = this;
var i;
// The merged results, collected from repository responses.
var results = [];
// The merged metainfo, collected from repository responses.
var allmetainfo = {
numItems: 0,
hasMoreItems: false
};
// A counting semaphore (working in reverse, ie: 0 means free).
var numOpenQueries;
// Unless the calling client specifies otherwise, the manager will
// wait a maximum of 5 seconds for all repositories to be queried
// and respond. 5 seconds is deemed to be the reasonable time to
// wait when querying the repository manager in the context of
// something like autocomplete.
var timeout = (params.timeout && parseInt(params.timeout, 10))
|| manager.settings.timeout;
// When this timer times-out, whatever has been collected in
// `results' will be returned to the calling client and all further
// processing aborted.
var timer = window.setTimeout(function () {
// Store in metainfo that a timeout occurred.
allmetainfo = allmetainfo || {};
allmetainfo.timeout = true;
if (numOpenQueries > 0) {
Console.warn(manager, numOpenQueries
+ ' repositories did not return before the '
+ 'configured timeout of ' + timeout + 'ms.');
numOpenQueries = 0;
}
clearTimeout(timer);
report(callback, bundle(results, allmetainfo));
}, timeout);
/**
* Invoked by each repository when it wants to present its results
* to the manager.
*
* Collects the results from each repository, and decrements the
* numOpenQueries semaphore to indicate that there is one less
* repository for which the manager is waiting for a reponse.
*
* If a repository invokes this callback after all openCallbacks
* have been closed (ie: numOpenQueries == 0), then the repository
* was too late ("missed the ship"), and will be ignored.
*
* If numOpenQueries decrements to 0 during this call, it means that
* the the manager is ready to report the results back to the client
* through the report() method.
*
* @param {Array.<Document|Folder>} items Results returned by the
* repository.
* @param {object<string, number>} metainfo Optional Metainfo
* returned by some
* repositories.
*/
var process = function (items, metainfo) {
var repository = this;
if (0 === numOpenQueries) {
return;
}
if (items && items.length) {
// Because some negligent repository implementations do not
// set repositoryId properly.
if (!items[0].repositoryId) {
var id = repository.repositoryId;
var i;
for (i = 0; i < items.length; i++) {
items[i].repositoryId = id;
}
}
$.merge(results, items);
}
if (metainfo && allmetainfo) {
allmetainfo.numItems =
($.isNumeric(metainfo.numItems) &&
$.isNumeric(allmetainfo.numItems))
? allmetainfo.numItems + metainfo.numItems
: undefined;
allmetainfo.hasMoreItems =
(typeof metainfo.hasMoreItems === 'boolean' &&
typeof allmetainfo.hasMoreItems === 'boolean')
? allmetainfo.hasMoreItems || metainfo.hasMoreItems
: undefined;
if (metainfo.timeout) {
allmetainfo.timeout = true;
}
} else {
// Because if even one repository does not return metainfo,
// so we have no aggregated metainfo at all.
allmetainfo = undefined;
}
Console.debug(manager, 'The repository '
+ repository.repositoryId + 'returned with '
+ items.length + ' results.');
// TODO: how to return the metainfo here?
if (0 === --numOpenQueries) {
clearTimeout(timer);
report(callback, bundle(results, allmetainfo));
}
};
var repositories = params.repositoryId
? [manager.getRepository(params.repositoryId)]
: manager.repositories;
var queue = filter(repositories, repositoryFilters.query);
// If none of the repositories implemented the query method, then
// don't wait for the timeout, simply report to the client.
if (0 === queue.length) {
clearTimeout(timer);
report(callback, bundle(results, allmetainfo));
return;
}
var makeProcess = function (repository) {
return function () {
process.apply(repository, arguments);
};
};
numOpenQueries = queue.length;
for (i = 0; i < queue.length; i++) {
queue[i].query(params, makeProcess(queue[i]));
}
},
/**
* Retrieves children items.
*
* @param {object<string,mixed>} params Object with properties.
*
* objectTypeFilter: Array (optional) Object types to be retrieved.
* filter: Array (optional) Attributes to be retrieved.
* inFolderId: boolean (optional) This indicates whether or not
* a candidate object is a
* child-object of the folder
* object identified by the given
* inFolderId (objectId).
* orderBy: Array (optional) example: [{
* lastModificationDate: 'DESC',
* name: 'ASC'
* }]
* maxItems: number (optional) number Items to return as a result.
* skipCount: number (optional) This is tricky in a merged
* multi repository scenario.
* renditionFilter: Array (optional) Instead of termlist an Array
* of kind or mimetype is
* expected. If null or
* Array.length == 0 all
* renditions are returned. See
* http://docs.oasis-open.org/cmis/CMIS/v1.0/cd04/cmis-spec-v1.0.html#_Ref237323310
* for renditionFilter.
*
* @param {function(Document|Folder)} callback Function to be invoked
* after the repository
* manager has finished
* querying all
* repositories.
*/
getChildren: function (params, callback) {
var manager = this;
var i;
// The marged results, collected from repository responses.
var results = [];
// A counting semaphore (working in reverse, ie: 0 means free).
var numOpenQueries = 0;
var timeout = (params.timeout && parseInt(params.timeout, 10))
|| manager.settings.timeout;
var timer = window.setTimeout(function () {
if (numOpenQueries > 0) {
Console.warn(manager, numOpenQueries
+ ' repositories did not respond before the '
+ 'configured timeout of ' + timeout + 'ms.');
numOpenQueries = 0;
}
clearTimeout(timer);
report(callback, results);
}, timeout);
var process = function (items) {
if (0 === numOpenQueries) {
return;
}
if (items) {
$.merge(results, items);
}
if (0 === --numOpenQueries) {
clearTimeout(timer);
report(callback, results);
}
};
var repositories = params.repositoryId
? [manager.getRepository(params.repositoryId)]
: manager.repositories;
if (params.repositoryFilter && params.repositoryFilter.length) {
repositories = filter(repositories, function (repository) {
return -1 < $.inArray(repository.repositoryId,
params.repositoryFilter);
});
}
// If the inFolderId is the default id of 'aloha', then return all
// registered repositories as the result set.
if ('aloha' === params.inFolderId) {
var hasRepoFilter = params.repositoryFilter
&& 0 < params.repositoryFilter.length;
for (i = 0; i < repositories.length; i++) {
results.push(new Aloha.RepositoryFolder({
id: repositories[i].repositoryId,
name: repositories[i].repositoryName,
repositoryId: repositories[i].repositoryId,
type: 'repository',
hasMoreItems: true
}));
}
clearTimeout(timer);
report(callback, results);
return;
}
var queue = filter(repositories, repositoryFilters.getChildren);
if (0 === queue.length) {
clearTimeout(timer);
report(callback, results);
return;
}
numOpenQueries = queue.length;
for (i = 0; i < queue.length; i++) {
queue[i].getChildren(params, process);
}
},
/**
* @fixme: Not tested, but the code for this function does not seem to
* compute repository.makeClean will be undefined
*
* @todo: Rewrite this function header comment so that is clearer
*
* Pass an object, which represents an marked repository to corresponding
* repository, so that it can make the content clean (prepare for saving)
*
* @param {jQuery} obj - representing an editable
* @return void
*/
makeClean: function (obj) {
// iterate through all registered repositories
var that = this,
repository = {},
i = 0,
j = that.repositories.length;
// find all repository tags
obj.find('[data-gentics-aloha-repository=' + this.prefix + ']').each(function () {
while (i < j) {
repository.makeClean(obj);
i += 1;
}
Console.debug(that, 'Passing contents of HTML Element with id { ' + this.attr('id') + ' } for cleaning to repository { ' + repository.repositoryId + ' }');
repository.makeClean(this);
});
},
/**
* Marks an object as repository of this type and with this item.id.
* Objects can be any DOM objects as A, SPAN, ABBR, etc. or
* special objects such as aloha-aloha_block elements.
*
* Marks the target obj with two private attributes:
* (see http://dev.w3.org/html5/spec/elements.html#embedding-custom-non-visible-data)
* - data-gentics-aloha-repository: stores the repositoryId
* - data-gentics-aloha-object-id: stores the object.id
*
* @param {HTMLElement} obj DOM object to mark.
* @param {Aloha.Repository.Object} item Item which is applied to obj,
* if set to null, the
* "data-GENTICS-..." attributes
* are removed.
*/
markObject: function (obj, item) {
if (!obj) {
return;
}
var manager = this;
if (item) {
var repository = manager.getRepository(item.repositoryId);
if (repository) {
$(obj).attr({
'data-gentics-aloha-repository': item.repositoryId,
'data-gentics-aloha-object-id': item.id
});
repository.markObject(obj, item);
} else {
Console.error(manager, 'Trying to apply a repository "'
+ item.name
+ '" to an object, but item has no repositoryId.');
}
} else {
$(obj).removeAttr('data-gentics-aloha-repository')
.removeAttr('data-gentics-aloha-object-id');
}
},
/**
* Get the object for which the given DOM object is marked from the
* repository.
*
* Will initialize the item cache (per repository) if not already done.
*
* @param {HTMLElement} element DOM object which probably is marked.
* @param {function} callback
*/
getObject: function (element, callback) {
var manager = this;
var $element = $(element);
var itemId = $element.attr('data-gentics-aloha-object-id');
var repositoryId = $element.attr('data-gentics-aloha-repository');
var repository = manager.getRepository(repositoryId);
if (repository && itemId) {
if (!manager.itemCache) {
manager.itemCache = [];
}
var cache = manager.itemCache[repositoryId];
if (!cache) {
cache = manager.itemCache[repositoryId] = [];
}
if (cache[itemId]) {
callback([cache[itemId]]);
} else {
repository.getObjectById(itemId, function (items) {
cache[itemId] = items[0];
callback(items);
});
}
}
},
/**
* Mark a folder as opened.
*
* Called by a repository client (eg: repository browser) when a folder
* is opened.
*
* @param {object|Folder} folder Object with property repositoryId.
*/
folderOpened: function (folder) {
var repository = this.getRepository(folder.repositoryId);
if (typeof repository.folderOpened === 'function') {
repository.folderOpened(folder);
}
},
/**
* Mark a folder as closed.
*
* Called by a repository client (eg: repository browser) when a folder
* is closed.
*
* @param {object|Folder} folder Object with property repositoryId.
*/
folderClosed: function (folder) {
var repository = this.getRepository(folder.repositoryId);
if (typeof repository.folderClosed === 'function') {
repository.folderClosed(folder);
}
},
/**
* Mark a folder as selected.
*
* Called by a repository client (eg: repository browser) when a folder
* is selected.
*
* @param {object|Folder} folder Object with property repositoryId.
*/
folderSelected: function (folder) {
var repository = this.getRepository(folder.repositoryId);
if (typeof repository.folderSelected === 'function') {
repository.folderSelected(folder);
}
},
/**
* Retrieve the selected folder.
*
* @return {Folder} Selected folder or null if it cannot be found.
*/
getSelectedFolder: function () {
var repositories = filter(this.repositories,
repositoryFilters.getSelectedFolder);
var i;
var selected;
for (i = 0; i < repositories.length; i++) {
selected = repositories[i].getSelectedFolder();
if (selected) {
return selected;
}
}
return null;
},
/**
* Human readable representation of repository manager.
*
* @return {string}
*/
toString: function () {
return 'repositorymanager';
}
});
Aloha.RepositoryManager = new RepositoryManager();
return Aloha.RepositoryManager;
});

View File

@@ -0,0 +1,162 @@
/* repositoryobjects.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
define([
'aloha/core',
'util/class'
], function (
Aloha,
Class
) {
"use strict";
var GENTICS = window.GENTICS;
Aloha.RepositoryObject = function () {};
/**
* @namespace Aloha.Repository
* @class Document
* @constructor
*
* Abstract Document suitable for most Objects.<br /><br />
*
* Example:
*
<pre><code>
var item = new Aloha.Repository.Document({
id: 1,
repositoryId: 'myrepository',
name: 'Aloha Editor - The HTML5 Editor',
type: 'website',
url:'http://aloha-editor.com',
});
</code></pre>
*
* @param {Object} properties An object with the data.
* <div class="mdetail-params"><ul>
* <li><code>id</code> : String <div class="sub-desc">Unique identifier</div></li>
* <li><code>repositoryId</code> : String <div class="sub-desc">Unique repository identifier</div></li>
* <li><code>name</code> : String <div class="sub-desc">Name of the object. This name is used to display</div></li>
* <li><code>type</code> : String <div class="sub-desc">The specific object type</div></li>
* <li><code>partentId</code> : String (optional) <div class="sub-desc"></div></li>
* <li><code>mimetype</code> : String (optional) <div class="sub-desc">MIME type of the Content Stream</div></li>
* <li><code>filename</code> : String (optional) <div class="sub-desc">File name of the Content Stream</div></li>
* <li><code>length</code> : String (optional) <div class="sub-desc">Length of the content stream (in bytes)</div></li>
* <li><code>url</code> : String (optional) <div class="sub-desc">URL of the content stream</div></li>
* <li><code>renditions</code> : Array (optional) <div class="sub-desc">Array of different renditions of this object</div></li>
* <li><code>localName</code> : String (optional) <div class="sub-desc">Name of the object. This name is used internally</div></li>
* <li><code>createdBy</code> : String (optional) <div class="sub-desc">User who created the object</div></li>
* <li><code>creationDate</code> : Date (optional) <div class="sub-desc">DateTime when the object was created</div></li>
* <li><code>lastModifiedBy</code> : String (optional) <div class="sub-desc">User who last modified the object</div></li>
* <li><code>lastModificationDate</code> : Date (optional) <div class="sub-desc">DateTime when the object was last modified</div></li>
* </ul></div>
*
*/
Aloha.RepositoryDocument = Class.extend({
_constructor: function (properties) {
var p = properties;
this.type = 'document';
// Basic error checking for MUST attributes
if (!p.id || !p.name || !p.repositoryId) {
// Aloha.Log.error(this, "No valid Aloha Object. Missing MUST property");
return;
}
GENTICS.Utils.applyProperties(this, properties);
this.baseType = 'document';
}
// /**
// * Not implemented method to generate this JS API doc correctly.
// */
// ,empty = function() }
});
/**
* @namespace Aloha.Repository
* @class Folder
* @constructor
* Abstract Folder suitable for most strucural Objects.<br /><br />
*
* Example:
*
<pre><code>
var item = new Aloha.Repository.Folder({
id: 2,
repositoryId: 'myrepository',
name: 'images',
type: 'directory',
parentId:'/www'
});
</code></pre>
* @param {Object} properties An object with the data.
* <div class="mdetail-params"><ul>
* <li><code>id</code> : String <div class="sub-desc">Unique identifier</div></li>
* <li><code>repositoryId</code> : String <div class="sub-desc">Unique repository identifier</div></li>
* <li><code>name</code> : String <div class="sub-desc">Name of the object. This name is used to display</div></li>
* <li><code>type</code> : String <div class="sub-desc">The specific object type</div></li>
* <li><code>partentId</code> : String (optional) <div class="sub-desc"></div></li>
* <li><code>localName</code> : String (optional) <div class="sub-desc">Name of the object. This name is used internally</div></li>
* <li><code>createdBy</code> : String (optional) <div class="sub-desc">User who created the object</div></li>
* <li><code>creationDate</code> : Date (optional) <div class="sub-desc">DateTime when the object was created</div></li>
* <li><code>lastModifiedBy</code> : String (optional) <div class="sub-desc">User who last modified the object</div></li>
* <li><code>lastModificationDate</code> : Date (optional) <div class="sub-desc">DateTime when the object was last modified</div></li>
* </ul></div>
*
*/
Aloha.RepositoryFolder = Class.extend({
_constructor: function (properties) {
var p = properties;
this.type = 'folder';
// Basic error checking for MUST attributes
if (!p.id || !p.name || !p.repositoryId) {
// Aloha.Log.error(this, "No valid Aloha Object. Missing MUST property");
return;
}
GENTICS.Utils.applyProperties(this, properties);
this.baseType = 'folder';
}
// /**
// * Not implemented method to generate this JS API doc correctly.
// */
// ,empty = function() {};
});
});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,455 @@
/** MIT License (c) copyright B Cavalier & J Hann */
/**
* curl css! plugin
*
* Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php
*
*/
(function (global) {
"use strict";
/*
* AMD css! plugin
* This plugin will load and wait for css files. This could be handy when
* loading css files as part of a layer or as a way to apply a run-time theme.
* Most browsers do not support the load event handler of the link element.
* Therefore, we have to use other means to detect when a css file loads.
* (The HTML5 spec states that the LINK element should have a load event, but
* not even Chrome 8 or FF4b7 have it, yet.
* http://www.w3.org/TR/html5/semantics.html#the-link-element)
*
* This plugin tries to use the load event and a universal work-around when
* it is invoked the first time. If the load event works, it is used on
* every successive load. Therefore, browsers that support the load event will
* just work (i.e. no need for hacks!). FYI, Feature-detecting the load
* event is tricky since most browsers have a non-functional onload property.
*
* The universal work-around watches a stylesheet until its rules are
* available (not null or undefined). There are nuances, of course, between
* the various browsers. The isLinkReady function accounts for these.
*
* Note: it appears that all browsers load @import'ed stylesheets before
* fully processing the rest of the importing stylesheet. Therefore, we
* don't need to find and wait for any @import rules explicitly.
*
* Note #2: for Opera compatibility, stylesheets must have at least one rule.
* AFAIK, there's no way to tell the difference between an empty sheet and
* one that isn't finished loading in Opera (XD or same-domain).
*
* Options:
* !nowait - does not wait for the stylesheet to be parsed, just loads it
*
* Global configuration options:
*
* cssDeferLoad: Boolean. You can also instruct this plugin to not wait
* for css resources. They'll get loaded asap, but other code won't wait
* for them. This is just like using the !nowait option on every css file.
*
* cssWatchPeriod: if direct load-detection techniques fail, this option
* determines the msec to wait between brute-force checks for rules. The
* default is 50 msec.
*
* You may specify an alternate file extension:
* require('css!myproj/component.less') // --> myproj/component.less
* require('css!myproj/component.scss') // --> myproj/component.scss
*
* When using alternative file extensions, be sure to serve the files from
* the server with the correct mime type (text/css) or some browsers won't
* parse them, causing an error in the plugin.
*
* usage:
* require(['css!myproj/comp']); // load and wait for myproj/comp.css
* define(['css!some/folder/file'], {}); // wait for some/folder/file.css
* require(['css!myWidget!nowait']);
*
* Tested in:
* Firefox 1.5, 2.0, 3.0, 3.5, 3.6, and 4.0b6
* Safari 3.0.4, 3.2.1, 5.0
* Chrome 7 (8+ is partly b0rked)
* Opera 9.52, 10.63, and Opera 11.00
* IE 6, 7, and 8
* Netscape 7.2 (WTF? SRSLY!)
* Does not work in Safari 2.x :(
* In Chrome 8+, there's no way to wait for cross-domain (XD) stylesheets.
* See comments in the code below.
* TODO: figure out how to be forward-compatible when browsers support HTML5's
* load handler without breaking IE and Opera
*/
var
// compressibility shortcuts
onreadystatechange = 'onreadystatechange',
onload = 'onload',
createElement = 'createElement',
// failed is true if RequireJS threw an exception
failed = false,
undef,
insertedSheets = {},
features = {
// true if the onload event handler works
// "event-link-onload" : false
},
// this actually tests for absolute urls and root-relative urls
// they're both non-relative
nonRelUrlRe = /^\/|^[^:]*:\/\//,
// Note: this will fail if there are parentheses in the url
findUrlRx = /url\s*\(['"]?([^'"\)]*)['"]?\)/g,
// doc will be undefined during a build
doc = global.document,
// find the head element and set it to it's standard property if nec.
head,
// collection of modules that have been written to the built file
built = {};
if (doc) {
head = doc.head || (doc.head = doc.getElementsByTagName('head')[0]);
}
function has (feature) {
return features[feature];
}
/***** load-detection functions *****/
function loadHandler (params, cb) {
// We're using 'readystatechange' because IE and Opera happily support both
var link = params.link;
link[onreadystatechange] = link[onload] = function () {
if (!link.readyState || link.readyState == 'complete') {
features["event-link-onload"] = true;
cleanup(params);
cb();
}
};
}
function nameWithExt (name, defaultExt) {
return name.lastIndexOf('.') <= name.lastIndexOf('/') ?
name + '.' + defaultExt : name;
}
function parseSuffixes (name) {
// creates a dual-structure: both an array and a hashmap
// suffixes[0] is the actual name
var parts = name.split('!'),
suf, i = 1, pair;
while ((suf = parts[i++])) { // double-parens to avoid jslint griping
pair = suf.split('=', 2);
parts[pair[0]] = pair.length == 2 ? pair[1] : true;
}
return parts;
}
var collectorSheet;
function createLink (doc, optHref) {
// detect if we need to avoid 31-sheet limit in IE (how to detect this for realz?)
if (document.createStyleSheet) {
if (!collectorSheet) {
collectorSheet = document.createStyleSheet();
}
if (document.styleSheets.length >= 30) {
moveLinksToCollector();
}
}
var link = doc[createElement]('link');
link.rel = "stylesheet";
link.type = "text/css";
link.setAttribute('_curl_movable', true);
if (optHref) {
link.href = optHref;
}
return link;
}
var testEl;
function styleIsApplied () {
// Chrome 8 hax0rs!
// This is an ugly hack needed by Chrome 8+ which no longer waits for rules
// to be applied to the document before exposing them to javascript.
// Unfortunately, this routine will never fire for XD stylesheets since
// Chrome will also throw an exception if attempting to access the rules
// of an XD stylesheet. Therefore, there's no way to detect the load
// event of XD stylesheets until Google fixes this, preferably with a
// functional load event! As a work-around, use domReady() before
// rendering widgets / components that need the css to be ready.
if (!testEl) {
testEl = doc[createElement]('div');
testEl.id = '_cssx_load_test';
head.appendChild(testEl);
}
return doc.defaultView.getComputedStyle(testEl, null).marginTop == '-5px';
}
function isLinkReady (link) {
// This routine is a bit fragile: browser vendors seem oblivious to
// the need to know precisely when stylesheets load. Therefore, we need
// to continually test beta browsers until they all support the LINK load
// event like IE and Opera.
var sheet, rules, ready = false;
try {
// webkit's and IE's sheet is null until the sheet is loaded
sheet = link.sheet || link.styleSheet;
// mozilla's sheet throws an exception if trying to access xd rules
rules = sheet.cssRules || sheet.rules;
// webkit's xd sheet returns rules == null
// opera's sheet always returns rules, but length is zero until loaded
// friggin IE doesn't count @import rules as rules, but IE should
// never hit this routine anyways.
ready = rules ?
rules.length > 0 : // || (sheet.imports && sheet.imports.length > 0) :
rules !== undef;
// thanks, Chrome 8+, for this lovely hack. TODO: find a better way
if (ready && {}.toString.call(window.chrome) == '[object Chrome]') {
// fwiw, we'll never get this far if this is an XD stylesheet
sheet.insertRule('#_cssx_load_test{margin-top:-5px;}', 0);
ready = styleIsApplied();
sheet.deleteRule(0);
}
}
catch (ex) {
// 1000 means FF loaded an xd stylesheet
// other browsers just throw a security error here (IE uses the phrase 'Access is denied')
ready = (ex.code == 1000) || (ex.message.match(/security|denied/i));
}
return ready;
}
function ssWatcher (params, cb) {
// watches a stylesheet for loading signs.
if (isLinkReady(params.link)) {
cleanup(params);
cb();
}
else if (!failed) {
setTimeout(function () { ssWatcher(params, cb); }, params.wait);
}
}
function loadDetector (params, cb) {
// It would be nice to use onload everywhere, but the onload handler
// only works in IE and Opera.
// Detecting it cross-browser is completely impossible, too, since
// THE BROWSERS ARE LIARS! DON'T TELL ME YOU HAVE AN ONLOAD PROPERTY
// IF IT DOESN'T DO ANYTHING!
var loaded;
function cbOnce () {
if (!loaded) {
loaded = true;
cb();
}
}
loadHandler(params, cbOnce);
if (!has("event-link-onload")) {
ssWatcher(params, cbOnce);
}
}
function cleanup (params) {
var link = params.link;
link[onreadystatechange] = link[onload] = null;
}
function moveLinksToCollector () {
// IE 6-8 fails when over 31 sheets, so we collect them.
// Note: this hack relies on proper cache headers.
var link, links, collector, pos = 0;
collector = collectorSheet;
collectorSheet = null; // so a new one will be created
links = document.getElementsByTagName('link');
while ((link = links[pos])) {
if (link.getAttribute('_curl_movable')) {
// move to the collectorSheet (note: bad cache directive will cause a re-download)
collector.addImport(link.href);
// remove from document
link.parentNode && link.parentNode.removeChild(link);
}
else {
// skip this sheet
pos++;
}
}
}
/***** style element functions *****/
var currentStyle;
function translateUrls (cssText, baseUrl) {
return cssText.replace(findUrlRx, function (all, url) {
return 'url("' + translateUrl(url, baseUrl) + '")';
});
}
function translateUrl (url, parentPath) {
// if this is a relative url
if (!nonRelUrlRe.test(url)) {
// append path onto it
url = parentPath + url;
}
return url;
}
function createStyle (cssText) {
clearTimeout(createStyle.debouncer);
if (createStyle.accum) {
createStyle.accum.push(cssText);
}
else {
createStyle.accum = [cssText];
currentStyle = doc.createStyleSheet ? doc.createStyleSheet() :
head.appendChild(doc.createElement('style'));
}
createStyle.debouncer = setTimeout(function () {
// Note: IE 6-8 won't accept the W3C method for inserting css text
var style, allCssText;
style = currentStyle;
currentStyle = undef;
allCssText = createStyle.accum.join('\n');
createStyle.accum = undef;
// for safari which chokes on @charset "UTF-8";
allCssText = allCssText.replace(/.+charset[^;]+;/g, '');
// TODO: hoist all @imports to the top of the file to follow w3c spec
'cssText' in style ? style.cssText = allCssText :
style.appendChild(doc.createTextNode(allCssText));
}, 0);
return currentStyle;
}
function createSheetProxy (sheet) {
return {
cssRules: function () {
return sheet.cssRules || sheet.rules;
},
insertRule: sheet.insertRule || function (text, index) {
var parts = text.split(/\{|\}/g);
sheet.addRule(parts[0], parts[1], index);
return index;
},
deleteRule: sheet.deleteRule || function (index) {
sheet.removeRule(index);
return index;
},
sheet: function () {
return sheet;
}
};
}
/***** finally! the actual plugin *****/
define(/*=='css',==*/ {
'normalize': function (resourceId, normalize) {
var resources, normalized;
if (!resourceId) return resourceId;
resources = resourceId.split(",");
normalized = [];
for (var i = 0, len = resources.length; i < len; i++) {
normalized.push(normalize(resources[i]));
}
return normalized.join(',');
},
'load': function (resourceId, require, callback, config) {
var resources = (resourceId || '').split(","),
loadingCount = resources.length;
// all detector functions must ensure that this function only gets
// called once per stylesheet!
function loaded () {
// load/error handler may have executed before stylesheet is
// fully parsed / processed in Opera, so use setTimeout.
// Opera will process before the it next enters the event loop
// (so 0 msec is enough time).
if(--loadingCount == 0){
// TODO: move this setTimeout to loadHandler
setTimeout(function () { callback(createSheetProxy(link.sheet || link.styleSheet)); }, 0);
}
}
if (!resourceId) {
// return the run-time API
callback({
'translateUrls': function (cssText, baseId) {
var baseUrl;
baseUrl = require['toUrl'](baseId);
baseUrl = baseUrl.substr(0, baseUrl.lastIndexOf('/') + 1);
return translateUrls(cssText, baseUrl);
},
'injectStyle': function (cssText) {
return createStyle(cssText);
},
'proxySheet': function (sheet) {
// for W3C, `sheet` is a reference to a <style> node so we need to
// return the sheet property.
if (sheet.sheet /* instanceof CSSStyleSheet */) sheet = sheet.sheet;
return createSheetProxy(sheet);
}
});
}
else {
// `after` will become truthy once the loop executes a second time
for (var i = resources.length - 1, after; i >= 0; i--, after = true) {
resourceId = resources[i];
var
// TODO: this is a bit weird: find a better way to extract name?
opts = parseSuffixes(resourceId),
name = opts.shift(),
url = require['toUrl'](nameWithExt(name, 'css')),
link = createLink(doc),
nowait = 'nowait' in opts ? opts['nowait'] != 'false' : !!config['cssDeferLoad'],
params = {
link: link,
url: url,
wait: config['cssWatchPeriod'] || 50
};
if (nowait) {
callback(createSheetProxy(link.sheet || link.styleSheet));
}
else {
// hook up load detector(s)
loadDetector(params, loaded);
}
// go!
link.href = url;
if (after) {
head.insertBefore(link, insertedSheets[after].previousSibling);
}
else {
head.appendChild(link);
}
insertedSheets[url] = link;
}
}
},
'plugin-builder': './builder/css'
});
})(this);

View File

@@ -0,0 +1,192 @@
/**
* @license RequireJS i18n 2.0.1 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/requirejs/i18n for details
*/
/*jslint regexp: true */
/*global require: false, navigator: false, define: false */
/**
* This plugin handles i18n! prefixed modules. It does the following:
*
* 1) A regular module can have a dependency on an i18n bundle, but the regular
* module does not want to specify what locale to load. So it just specifies
* the top-level bundle, like "i18n!nls/colors".
*
* This plugin will load the i18n bundle at nls/colors, see that it is a root/master
* bundle since it does not have a locale in its name. It will then try to find
* the best match locale available in that master bundle, then request all the
* locale pieces for that best match locale. For instance, if the locale is "en-us",
* then the plugin will ask for the "en-us", "en" and "root" bundles to be loaded
* (but only if they are specified on the master bundle).
*
* Once all the bundles for the locale pieces load, then it mixes in all those
* locale pieces into each other, then finally sets the context.defined value
* for the nls/colors bundle to be that mixed in locale.
*
* 2) A regular module specifies a specific locale to load. For instance,
* i18n!nls/fr-fr/colors. In this case, the plugin needs to load the master bundle
* first, at nls/colors, then figure out what the best match locale is for fr-fr,
* since maybe only fr or just root is defined for that locale. Once that best
* fit is found, all of its locale pieces need to have their bundles loaded.
*
* Once all the bundles for the locale pieces load, then it mixes in all those
* locale pieces into each other, then finally sets the context.defined value
* for the nls/fr-fr/colors bundle to be that mixed in locale.
*/
(function () {
'use strict';
//regexp for reconstructing the master bundle name from parts of the regexp match
//nlsRegExp.exec("foo/bar/baz/nls/en-ca/foo") gives:
//["foo/bar/baz/nls/en-ca/foo", "foo/bar/baz/nls/", "/", "/", "en-ca", "foo"]
//nlsRegExp.exec("foo/bar/baz/nls/foo") gives:
//["foo/bar/baz/nls/foo", "foo/bar/baz/nls/", "/", "/", "foo", ""]
//so, if match[5] is blank, it means this is the top bundle definition.
var nlsRegExp = /(^.*(^|\/)nls(\/|$))([^\/]*)\/?([^\/]*)/;
//Helper function to avoid repeating code. Lots of arguments in the
//desire to stay functional and support RequireJS contexts without having
//to know about the RequireJS contexts.
function addPart(locale, master, needed, toLoad, prefix, suffix) {
if (master[locale]) {
needed.push(locale);
if (master[locale] === true || master[locale] === 1) {
toLoad.push(prefix + locale + '/' + suffix);
}
}
}
function addIfExists(req, locale, toLoad, prefix, suffix) {
var fullName = prefix + locale + '/' + suffix;
if (require._fileExists(req.toUrl(fullName))) {
toLoad.push(fullName);
}
}
/**
* Simple function to mix in properties from source into target,
* but only if target does not already have a property of the same name.
* This is not robust in IE for transferring methods that match
* Object.prototype names, but the uses of mixin here seem unlikely to
* trigger a problem related to that.
*/
function mixin(target, source, force) {
var prop;
for (prop in source) {
if (source.hasOwnProperty(prop) && (!target.hasOwnProperty(prop) || force)) {
target[prop] = source[prop];
} else if (typeof source[prop] === 'object') {
mixin(target[prop], source[prop], force);
}
}
}
define(['module'], function (module) {
var masterConfig = module.config();
return {
version: '2.0.1',
/**
* Called when a dependency needs to be loaded.
*/
load: function (name, req, onLoad, config) {
config = config || {};
if (config.locale) {
masterConfig.locale = config.locale;
}
var masterName,
match = nlsRegExp.exec(name),
prefix = match[1],
locale = match[4],
suffix = match[5],
parts = locale.split("-"),
toLoad = [],
value = {},
i, part, current = "";
//If match[5] is blank, it means this is the top bundle definition,
//so it does not have to be handled. Locale-specific requests
//will have a match[4] value but no match[5]
if (match[5]) {
//locale-specific bundle
prefix = match[1];
masterName = prefix + suffix;
} else {
//Top-level bundle.
masterName = name;
suffix = match[4];
locale = masterConfig.locale;
if (!locale) {
locale = masterConfig.locale =
typeof navigator === "undefined" ? "root" :
(navigator.language ||
navigator.userLanguage || "root").toLowerCase();
}
parts = locale.split("-");
}
if (config.isBuild) {
//Check for existence of all locale possible files and
//require them if exist.
toLoad.push(masterName);
addIfExists(req, "root", toLoad, prefix, suffix);
for (i = 0; i < parts.length; i++) {
part = parts[i];
current += (current ? "-" : "") + part;
addIfExists(req, current, toLoad, prefix, suffix);
}
req(toLoad, function () {
onLoad();
});
} else {
//First, fetch the master bundle, it knows what locales are available.
req([masterName], function (master) {
//Figure out the best fit
var needed = [],
part;
//Always allow for root, then do the rest of the locale parts.
addPart("root", master, needed, toLoad, prefix, suffix);
for (i = 0; i < parts.length; i++) {
part = parts[i];
current += (current ? "-" : "") + part;
addPart(current, master, needed, toLoad, prefix, suffix);
}
//Load all the parts missing.
req(toLoad, function () {
var i, partBundle, part;
for (i = needed.length - 1; i > -1 && needed[i]; i--) {
part = needed[i];
partBundle = master[part];
if (partBundle === true || partBundle === 1) {
partBundle = req(prefix + part + '/' + suffix);
}
mixin(value, partBundle);
}
// MODIFICATION FROM ALOHA START: add a t() function
value.t = function( key, defaultValue ) {
if ( this[key] ) {
return this[key];
} else if ( defaultValue ) {
return defaultValue;
} else {
return key;
}
}
// END OF ALOHA MODIFICATION
//All done, notify the loader.
onLoad(value);
});
});
}
}
};
});
}());

View File

@@ -18,7 +18,7 @@
defaultPort = hasLocation && (location.port || undefined),
buildMap = [];
define([],function () {
define(function () {
var text, get, fs;
if (typeof window !== "undefined" && window.navigator && window.document) {

View File

@@ -0,0 +1,208 @@
/* arrays.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
define([], function () {
'use strict';
/**
* Implements unique() using the browser's sort().
*
* @param a
* The array to sort and strip of duplicate values.
* Warning: this array will be modified in-place.
* @param compFn
* A custom comparison function that accepts two values a and
* b from the given array and returns -1, 0, 1 depending on
* whether a < b, a == b, a > b respectively.
*
* If no compFn is provided, the algorithm will use the
* browsers default sort behaviour and loose comparison to
* detect duplicates.
* @return
* The given array.
*/
function sortUnique(a, compFn) {
var i;
if (compFn) {
a.sort(compFn);
for (i = 1; i < a.length; i++) {
if (0 === compFn(a[i], a[i - 1])) {
a.splice(i--, 1);
}
}
} else {
a.sort();
for (i = 1; i < a.length; i++) {
// Use loosely typed comparsion if no compFn is given
// to avoid sortUnique( [6, "6", 6] ) => [6, "6", 6]
if (a[i] == a[i - 1]) {
a.splice(i--, 1);
}
}
}
return a;
}
/**
* Shallow comparison of two arrays.
*
* @param a, b
* The arrays to compare.
* @param equalFn
* A custom comparison function that accepts two values a and
* b from the given arrays and returns true or false for
* equal and not equal respectively.
*
* If no equalFn is provided, the algorithm will use the strict
* equals operator.
* @return
* True if all items in a and b are equal, false if not.
*/
function equal(a, b, equalFn) {
var i,
len = a.length;
if (len !== b.length) {
return false;
}
if (equalFn) {
for (i = 0; i < len; i++) {
if (!equalFn(a[i], b[i])) {
return false;
}
}
} else {
for (i = 0; i < len; i++) {
if (a[i] !== b[i]) {
return false;
}
}
}
return true;
}
/**
* ECMAScript map replacement
* See https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/map
* And http://es5.github.com/#x15.4.4.19
* It's not exactly according to standard, but it does exactly what one expects.
*/
function map(a, fn) {
var i, len, result = [];
for (i = 0, len = a.length; i < len; i++) {
result.push(fn(a[i]));
}
return result;
}
function mapNative(a, fn) {
// Call map directly on the object instead of going through
// Array.prototype.map. This avoids the problem that we may get
// passed an array-like object (NodeList) which may cause an
// error if the implementation of Array.prototype.map can only
// deal with arrays (Array.prototype.map may be native or
// provided by a javscript framework).
return a.map(fn);
}
/**
* Returns a new array that contains all values in the given a for
* which pred returns true.
*/
function filter(a, pred) {
var i,
len,
value,
result = [];
for (i = 0, len = a.length; i < len; i++) {
value = a[i];
if (pred(value)) {
result.push(value);
}
}
return result;
}
/**
* Finds a value in the given array.
* Strict comparison is used to find the value.
* Returns the index of the first occurrence of the given value in
* the given a, or -1 if a contains no such value.
*/
function indexOf(a, value) {
var i,
len;
for (i = 0, len = a.length; i < len; i++) {
if (value === a[i]) {
return i;
}
}
return -1;
}
/**
* Reduces an array of values to a single value.
*
* For example:
* Arrays.reduce([2, 3, 4], 1, function (a, b) { return a + b; });
* returns the result of (((1 + 2) + 3) + 4)
*
* @param a
* An array of values.
* @param init
* An initial value.
* @param fn
* A function that takes two values and returns the reduction
* of both.
*/
function reduce(a, init, fn) {
var i,
len;
for (i = 0, len = a.length; i < len; i++) {
init = fn(init, a[i]);
}
return init;
}
/**
* Applies the given value to the given function unless the value is
* null, in which case just returns null.
*
* This is a utility function to be used with reduce().
*/
function applyNotNull(value, fn) {
return value == null ? null : fn(value);
}
return {
filter: filter,
indexOf: indexOf,
reduce: reduce,
applyNotNull: applyNotNull,
sortUnique: sortUnique,
equal: equal,
map: Array.prototype.map ? mapNative : map
};
});

View File

@@ -0,0 +1,32 @@
/* ephemera.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
define(['jquery'], function ($) {
'use strict';
return {
ie7: $.browser.msie && parseInt($.browser.version, 10) < 8
};
});

View File

@@ -0,0 +1,78 @@
/* Simple JavaScript Inheritance
* By John Resig http://ejohn.org/
* MIT Licensed.
*/
// Inspired by base2 and Prototype
/*
* MODIFICATIONS:
* * The name of the "constructor" method was changed from "init" to "_constructor"
* * Mixin Support using https://gist.github.com/1006243
* * Modified to be a require.js module
*/
define([], function () {
var initializing = false,
fnTest = /xyz/.test(function () {
xyz;
}) ? /\b_super\b/ : /.*/;
// The base Class implementation (does nothing)
// with doing that Class is available in the global namespace.
this.Class = function () {};
// Create a new Class that inherits from this class
Class.extend = function () {
var _super = this.prototype;
// Instantiate a base class (but only create the instance,
// don't run the init constructor)
initializing = true;
var prototype = new this();
initializing = false;
// Copy the properties over onto the new prototype
for (var i = 0; i < arguments.length; i++) {
var prop = arguments[i];
for (var name in prop) {
// Check if we're overwriting an existing function
prototype[name] = typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ? (function (name, fn) {
return function () {
var tmp = this._super;
// Add a new ._super() method that is the same method
// but on the super-class
this._super = _super[name];
// The method only need to be bound temporarily, so we
// remove it when we're done executing
var ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
};
})(name, prop[name]) : prop[name];
}
}
// The dummy class constructor
function Class() {
// All construction is actually done in the _constructor method
if (!initializing && this._constructor) this._constructor.apply(this, arguments);
}
// Populate our constructed prototype object
Class.prototype = prototype;
// Enforce the constructor to be what we expect
Class.constructor = Class;
// And make this class extendable
Class.extend = arguments.callee;
return Class;
};
return this.Class;
});

1706
media/aloha-0.22.7/lib/util/dom.js Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,301 @@
/* ephemera.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
define([
'jquery',
'util/maps',
'util/strings',
'util/browser'
], function (
$,
Maps,
Strings,
Browser
) {
'use strict';
var spacesRx = /\s+/;
var attrRegex = /\s([^\/<>\s=]+)(?:=(?:"[^"]*"|'[^']*'|[^>\/\s]+))?/g;
/**
* Like insertBefore, inserts firstChild into parent before
* refChild, except also inserts all the following siblings of
* firstChild.
*/
function moveNextAll(parent, firstChild, refChild) {
while (firstChild) {
var nextChild = firstChild.nextSibling;
parent.insertBefore(firstChild, refChild);
firstChild = nextChild;
}
}
/**
* Used to serialize outerHTML of DOM elements in older (pre-HTML5) Gecko,
* Safari, and Opera browsers.
*
* Beware that XMLSerializer generates an XHTML string (<div class="team" />
* instead of <div class="team"></div>). It is noted here:
* http://stackoverflow.com/questions/1700870/how-do-i-do-outerhtml-in-firefox
* that some browsers (like older versions of Firefox) have problems with
* XMLSerializer, and an alternative, albeit more expensive option, is
* described.
*
* @type {XMLSerializer|null}
*/
var Serializer = window.XMLSerializer && new window.XMLSerializer();
/**
* Gets the serialized HTML that describes the given DOM element and its
* innerHTML.
*
* Polyfill for older versions of Gecko, Safari, and Opera browsers.
* @see https://bugzilla.mozilla.org/show_bug.cgi?id=92264 for background.
*
* @param {HTMLElement} node DOM Element.
* @return {String}
*/
function outerHtml(node) {
var html = node.outerHTML;
if (typeof html !== 'undefined') {
return html;
}
try {
return Serializer ? Serializer.serializeToString(node) : node.xml;
} catch (e) {
return node.xml;
}
}
/**
* Retrieves the names of all attributes from the given elmenet.
*
* Correctly handles the case that IE7 and IE8 have approx 70-90
* default attributes on each and every element.
*
* This implementation does not iterate over the elem.attributes
* property since that is much slower on IE7 (even when
* checking the attrNode.specified property). Instead it parses the
* HTML of the element. For elements with few attributes the
* performance on IE7 is improved by an order of magnitued.
*
* On IE7, when you clone a <button disabled="disabled"/> or an
* <input checked="checked"/> element the boolean properties will
* not be set on the cloned node. We choose the speed optimization
* over correctness in this case. The dom-to-xhtml plugin has a
* workaround for this case.
*/
function attrNames(elem) {
var names = [];
var html = outerHtml(elem.cloneNode(false));
var match;
while (null != (match = attrRegex.exec(html))) {
names.push(match[1]);
}
return names;
}
/**
* Gets the attributes of the given element.
*
* See attrNames() for an edge case on IE7.
*
* @param elem
* An element to get the attributes for.
* @return
* An array containing [name, value] tuples for each attribute.
* Attribute values will always be strings, but possibly empty strings.
*/
function attrs(elem) {
var as = [];
var names = attrNames(elem);
var i;
var len;
for (i = 0, len = names.length; i < len; i++) {
var name = names[i];
var value = $.attr(elem, name);
if (null == value) {
value = "";
} else {
value = value.toString();
}
as.push([name, value]);
}
return as;
}
/**
* Like indexByClass() but operates on a list of elements instead.
* The given list may be a NodeList, HTMLCollection, or an array.
*/
function indexByClassHaveList(elems, classMap) {
var index = {},
indexed,
classes,
elem,
cls,
len,
i,
j;
for (i = 0, len = elems.length; i < len; i++) {
elem = elems[i];
if (elem.className) {
classes = Strings.words(elem.className);
for (j = 0; j < classes.length; j++) {
cls = classes[j];
if (classMap[cls]) {
indexed = index[cls];
if (indexed) {
indexed.push(elem);
} else {
index[cls] = [elem];
}
}
}
}
}
return index;
}
/**
* Indexes descendant elements based on the individual classes in
* the class attribute.
*
* Based on these observations;
*
* * $('.class1, .class2') takes twice as long as $('.class1') on IE7.
*
* * $('.class1, .class2') is fast on IE8 (approx the same as
* $('.class'), no matter how many classes), but if the individual
* elements in the result set should be handled differently, the
* subsequent hasClass('.class1') and hasClass('.class2') calls
* slow things down again.
*
* * DOM traversal with elem.firstChild elem.nextSibling is very
* slow on IE7 compared to just iterating over
* root.getElementsByTagName('*').
*
* * $('name.class') is much faster than just $('.class'), but as
* soon as you need a single class in classMap that may be present
* on any element, that optimization doesn't gain anything since
* then you have to examine every element.
*
* This function will always take approx. the same amount of time
* (on IE7 approx. equivalent to a single call to $('.class')) no
* matter how many entries there are in classMap to index.
*
* This function only makes sense for multiple entries in
* classMap. For a single class lookup, $('.class') or
* $('name.class') is fine (even better in the latter case).
*
* @param root
* The root element to search for elements to index
* (will not be included in search).
* @param classMap
* A map from class name to boolean true.
* @return
* A map from class name to an array of elements with that class.
* Every entry in classMap for which elements have been found
* will have a corresponding entry in the returned
* map. Entries for which no elements have been found, may or
* may not have an entry in the returned map.
*/
function indexByClass(root, classMap) {
var elems;
if (Browser.ie7) {
elems = root.getElementsByTagName('*');
} else {
// Optimize for browsers that support querySelectorAll/getElementsByClassName.
// On IE8 for example, if there is a relatively high
// elems/resultSet ratio, performance can improve by a factor of 2.
elems = $(root).find('.' + Maps.keys(classMap).join(',.'));
}
return indexByClassHaveList(elems, classMap);
}
/**
* Indexes descendant elements based on elem.nodeName.
*
* Based on these observations:
*
* * On IE8, for moderate values of names.length, individual calls to
* getElementsByTagName is just as fast as $root.find('name, name,
* name, name').
*
* * On IE7, $root.find('name, name, name, name') is extemely slow
* (can be an order of magnitude slower than individual calls to
* getElementsByTagName, why is that?).
*
* * Although getElementsByTagName is very fast even on IE7, when
* names.length > 7 an alternative implementation that iterates
* over all tags and checks names from a hashmap (similar to how
* indexByClass does it) may become interesting, but
* names.length > 7 is unlikely.
*
* This function only makes sense if the given names array has many
* entries. For only one or two different names, calling $('name')
* or context.getElementsByTagName(name) directly is fine (but
* beware of $('name, name, ...') as explained above).
*
* The signature of this function differs from indexByClass by not
* taking a map but instead an array of names.
*
* @param root
* The root element to search for elements to index
* (will not be included in search).
* @param names
* An array of element names to look for.
* Names must be in all-uppercase (the same as elem.nodeName).
* @return
* A map from element name to an array of elements with that name.
* Names will be all-uppercase.
* Arrays will be proper arrays, not NodeLists.
* Every entry in classMap for which elements have been found
* will have a corresponding entry in the returned
* map. Entries for which no elements have been found, may or
* may not have an entry in the returned map.
*/
function indexByName(root, names) {
var i,
index = {},
len;
for (i = 0, len = names.length; i < len; i++) {
var name = names[i];
index[name] = $.makeArray(root.getElementsByTagName(name));
}
return index;
}
return {
moveNextAll: moveNextAll,
attrNames: attrNames,
attrs: attrs,
indexByClass: indexByClass,
indexByName: indexByName,
indexByClassHaveList: indexByClassHaveList,
outerHtml: outerHtml
};
});

View File

@@ -0,0 +1,41 @@
/* functions.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
define([], function () {
'use strict';
/**
* The identity function returns its single argument.
* Useful for composition when some default behaviour is needed.
*/
function identity(arg) {
return arg;
}
return {
identity: identity
};
});

View File

@@ -0,0 +1,464 @@
/*
http://www.JSON.org/json2.js
2011-02-23
Public Domain.
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
See http://www.JSON.org/js.html
This code should be minified before deployment.
See http://javascript.crockford.com/jsmin.html
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
NOT CONTROL.
This file creates a global JSON object containing two methods: stringify
and parse.
JSON.stringify(value, replacer, space)
value any JavaScript value, usually an object or array.
replacer an optional parameter that determines how object
values are stringified for objects. It can be a
function or an array of strings.
space an optional parameter that specifies the indentation
of nested structures. If it is omitted, the text will
be packed without extra whitespace. If it is a number,
it will specify the number of spaces to indent at each
level. If it is a string (such as '\t' or '&nbsp;'),
it contains the characters used to indent at each level.
This method produces a JSON text from a JavaScript value.
When an object value is found, if the object contains a toJSON
method, its toJSON method will be called and the result will be
stringified. A toJSON method does not serialize: it returns the
value represented by the name/value pair that should be serialized,
or undefined if nothing should be serialized. The toJSON method
will be passed the key associated with the value, and this will be
bound to the value
For example, this would serialize Dates as ISO strings.
Date.prototype.toJSON = function (key) {
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
return this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z';
};
You can provide an optional replacer method. It will be passed the
key and value of each member, with this bound to the containing
object. The value that is returned from your method will be
serialized. If your method returns undefined, then the member will
be excluded from the serialization.
If the replacer parameter is an array of strings, then it will be
used to select the members to be serialized. It filters the results
such that only members with keys listed in the replacer array are
stringified.
Values that do not have JSON representations, such as undefined or
functions, will not be serialized. Such values in objects will be
dropped; in arrays they will be replaced with null. You can use
a replacer function to replace those with JSON values.
JSON.stringify(undefined) returns undefined.
The optional space parameter produces a stringification of the
value that is filled with line breaks and indentation to make it
easier to read.
If the space parameter is a non-empty string, then that string will
be used for indentation. If the space parameter is a number, then
the indentation will be that many spaces.
Example:
text = JSON.stringify(['e', {pluribus: 'unum'}]);
// text is '["e",{"pluribus":"unum"}]'
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
text = JSON.stringify([new Date()], function (key, value) {
return this[key] instanceof Date ?
'Date(' + this[key] + ')' : value;
});
// text is '["Date(---current time---)"]'
JSON.parse(text, reviver)
This method parses a JSON text to produce an object or array.
It can throw a SyntaxError exception.
The optional reviver parameter is a function that can filter and
transform the results. It receives each of the keys and values,
and its return value is used instead of the original value.
If it returns what it received, then the structure is not modified.
If it returns undefined then the member is deleted.
Example:
// Parse the text. Values that look like ISO date strings will
// be converted to Date objects.
myData = JSON.parse(text, function (key, value) {
var a;
if (typeof value === 'string') {
a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
if (a) {
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+a[5], +a[6]));
}
}
return value;
});
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
var d;
if (typeof value === 'string' &&
value.slice(0, 5) === 'Date(' &&
value.slice(-1) === ')') {
d = new Date(value.slice(5, -1));
if (d) {
return d;
}
}
return value;
});
This is a reference implementation. You are free to copy, modify, or
redistribute.
*/
/*jslint evil: true, strict: false, regexp: false */
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
lastIndex, length, parse, prototype, push, replace, slice, stringify,
test, toJSON, toString, valueOf
*/
// Create a JSON object only if one does not already exist.
var JSON;
if (!JSON) {
JSON = {};
}
(function () {
"use strict";
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
if (typeof Date.prototype.toJSON !== 'function') {
Date.prototype.toJSON = function (key) {
return isFinite(this.valueOf()) ? this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z' : null;
};
String.prototype.toJSON = Number.prototype.toJSON = Boolean.prototype.toJSON = function (key) {
return this.valueOf();
};
}
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
gap,
indent,
meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"': '\\"',
'\\': '\\\\'
},
rep;
function quote(string) {
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
escapable.lastIndex = 0;
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
var c = meta[a];
return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"' : '"' + string + '"';
}
function str(key, holder) {
// Produce a string from holder[key].
var i, // The loop counter.
k, // The member key.
v, // The member value.
length,
mind = gap,
partial,
value = holder[key];
// If the value has a toJSON method, call it to obtain a replacement value.
if (value && typeof value === 'object' && typeof value.toJSON === 'function') {
value = value.toJSON(key);
}
// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.
if (typeof rep === 'function') {
value = rep.call(holder, key, value);
}
// What happens next depends on the value's type.
switch (typeof value) {
case 'string':
return quote(value);
case 'number':
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value) ? String(value) : 'null';
case 'boolean':
case 'null':
// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.
return String(value);
// If the type is 'object', we might be dealing with an object or an array or
// null.
case 'object':
// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.
if (!value) {
return 'null';
}
// Make an array to hold the partial results of stringifying this object value.
gap += indent;
partial = [];
// Is the value an array?
if (Object.prototype.toString.apply(value) === '[object Array]') {
// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.
length = value.length;
for (i = 0; i < length; i += 1) {
partial[i] = str(i, value) || 'null';
}
// Join all of the elements together, separated with commas, and wrap them in
// brackets.
v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']';
gap = mind;
return v;
}
// If the replacer is an array, use it to select the members to be stringified.
if (rep && typeof rep === 'object') {
length = rep.length;
for (i = 0; i < length; i += 1) {
if (typeof rep[i] === 'string') {
k = rep[i];
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
} else {
// Otherwise, iterate through all of the keys in the object.
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
}
// Join all of the member texts together, separated with commas,
// and wrap them in braces.
v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}';
gap = mind;
return v;
}
}
// If the JSON object does not yet have a stringify method, give it one.
if (typeof JSON.stringify !== 'function') {
JSON.stringify = function (value, replacer, space) {
// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.
var i;
gap = '';
indent = '';
// If the space parameter is a number, make an indent string containing that
// many spaces.
if (typeof space === 'number') {
for (i = 0; i < space; i += 1) {
indent += ' ';
}
// If the space parameter is a string, it will be used as the indent string.
} else if (typeof space === 'string') {
indent = space;
}
// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.
rep = replacer;
if (replacer && typeof replacer !== 'function' && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) {
throw new Error('JSON.stringify');
}
// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.
return str('', {
'': value
});
};
}
// If the JSON object does not yet have a parse method, give it one.
if (typeof JSON.parse !== 'function') {
JSON.parse = function (text, reviver) {
// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.
var j;
function walk(holder, key) {
// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.
var k, v, value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}
// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.
text = String(text);
cx.lastIndex = 0;
if (cx.test(text)) {
text = text.replace(cx, function (a) {
return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.
// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
if (/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.
j = eval('(' + text + ')');
// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.
return typeof reviver === 'function' ? walk({
'': j
}, '') : j;
}
// If the text is not JSON parseable, then a SyntaxError is thrown.
throw new SyntaxError('JSON.parse');
};
}
}());
define('util/json2', [], function () {
return JSON;
});

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