Merge remote-tracking branch 'upstream/master' into file_shortcodes

This commit is contained in:
Sean Harvey 2012-03-03 10:24:06 +13:00
commit b3d977f0e7
75 changed files with 1651 additions and 905 deletions

View File

@ -34,3 +34,4 @@ HtmlEditorConfig::get('cms')->addButtonsToLine(2, 'ssimage', 'ssflash', 'sslink'
HtmlEditorConfig::get('cms')->removeButtons('tablecontrols');
HtmlEditorConfig::get('cms')->addButtonsToLine(3, 'tablecontrols');
CMSMenu::remove_menu_item('CMSProfileController');

View File

@ -0,0 +1,34 @@
<?php
class CMSProfileController extends LeftAndMain {
static $url_segment = 'myprofile';
public function index($request) {
$form = $this->Member_ProfileForm();
return $this->customise(array(
'Content' => ' ',
'Form' => $form
))->renderWith('CMSDialog');
}
public function Member_ProfileForm() {
return new Member_ProfileForm($this, 'Member_ProfileForm', Member::currentUser());
}
function canView($member = null) {
if(!$member && $member !== FALSE) $member = Member::currentUser();
// cms menus only for logged-in members
if(!$member) return false;
// Only check for generic CMS permissions
if(
!Permission::checkMember($member, "CMS_ACCESS_LeftAndMain")
&& !Permission::checkMember($member, "CMS_ACCESS_CMSMain")
) {
return false;
}
return true;
}
}

View File

@ -73,10 +73,8 @@ class LeftAndMain extends Controller {
'savetreenode',
'getitem',
'getsubtree',
'myprofile',
'printable',
'show',
'Member_ProfileForm',
'EditorToolbar',
'EditForm',
'RootForm',
@ -239,6 +237,7 @@ class LeftAndMain extends Controller {
THIRDPARTY_DIR . '/jquery-entwine/dist/jquery.entwine-dist.js',
THIRDPARTY_DIR . '/jquery-cookie/jquery.cookie.js',
THIRDPARTY_DIR . '/jquery-query/jquery.query.js',
THIRDPARTY_DIR . '/jquery-form/jquery.form.js',
SAPPHIRE_ADMIN_DIR . '/thirdparty/jquery-notice/jquery.notice.js',
SAPPHIRE_ADMIN_DIR . '/thirdparty/jsizes/lib/jquery.sizes.js',
SAPPHIRE_ADMIN_DIR . '/thirdparty/jlayout/lib/jlayout.border.js',
@ -283,6 +282,7 @@ class LeftAndMain extends Controller {
))
);
Requirements::css(SAPPHIRE_ADMIN_DIR . '/thirdparty/jquery-notice/jquery.notice.css');
Requirements::css(THIRDPARTY_DIR . '/jquery-ui-themes/smoothness/jquery-ui.css');
Requirements::css(SAPPHIRE_ADMIN_DIR .'/thirdparty/chosen/chosen/chosen.css');
Requirements::css(THIRDPARTY_DIR . '/jstree/themes/apple/style.css');
@ -513,7 +513,7 @@ class LeftAndMain extends Controller {
))
));
$record = $this->currentPage();
if($record) {
if($record && $record->exists()) {
if($record->hasExtension('Hierarchy')) {
$ancestors = $record->getAncestors();
$ancestors = new ArrayList(array_reverse($ancestors->toArray()));
@ -1104,18 +1104,6 @@ class LeftAndMain extends Controller {
return $form;
}
public function myprofile() {
$form = $this->Member_ProfileForm();
return $this->customise(array(
'Content' => ' ',
'Form' => $form
))->renderWith('CMSDialog');
}
public function Member_ProfileForm() {
return new Member_ProfileForm($this, 'Member_ProfileForm', Member::currentUser());
}
public function printable() {
$form = $this->getEditForm($this->currentPageID());
if(!$form) return false;

View File

@ -79,12 +79,6 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider {
);
}
$form->Actions()->insertBefore(
$actionAddMember = new FormAction('addmember',_t('SecurityAdmin.ADDMEMBER','Add Member')),
'action_save'
);
$actionAddMember->setForm($form);
// Filter permissions
$permissionField = $form->Fields()->dataFieldByName('Permissions');
if($permissionField) $permissionField->setHiddenPermissions(self::$hidden_permissions);
@ -107,9 +101,12 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider {
*/
function RootForm() {
$config = new GridFieldConfig_Base(25);
$config->addComponent(new GridFieldAction_Edit());
$config->addComponent(new GridFieldAction_Delete());
$config->addComponent(new GridFieldPopupForms());
$config->addComponent(new GridFieldExporter());
$memberList = new GridField('Members', 'All members', DataList::create('Member'), $config);
$memberList->addExtraClass("members_grid");
$fields = new FieldList(
$root = new TabSet(
@ -158,9 +155,7 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider {
$rolesTab->push($rolesCTF);
}
$actions = new FieldList(
new FormAction('addmember',_t('SecurityAdmin.ADDMEMBER','Add Member'))
);
$actions = new FieldList();
$this->extend('updateRootFormFields', $fields, $actions);

View File

@ -14,3 +14,5 @@ html { overflow: hidden; }
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { background-image: none; }
.jstree li a .ui-icon { text-indent: 0px !important; }
.cms table.ss-gridfield-table tbody td button span.ui-button-text { zoom: 1; }

View File

@ -88,6 +88,8 @@ article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav,
/** ----------------------------- CMS Components ------------------------------ */
/** File: typography.scss Contains the basic typography related styles for the admin interface. */
body, html { font-size: 12px; line-height: 16px; font-family: Arial, sans-serif; color: #444444; }
.cms h2, .cms h3, .cms h4, .cms h5 { font-weight: bold; margin: 16px 0 16px 0; line-height: 16px; }
.cms h2 { font-size: 18px; line-height: 24px; }
.cms h3 { font-size: 16px; }
@ -105,7 +107,7 @@ article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav,
.cms .ui-tabs .ui-tabs-nav.ui-state-active { border-color: gray; }
.cms .ui-tabs .ui-tabs-panel { background: transparent; padding: 0; }
.cms .ui-widget-content, .cms .ui-widget { color: #444444; font-size: 12px; font-family: Arial, sans-serif; border: 0; }
.cms .ui-widget-header { background-color: #b0bec7; padding: 8px 8px 6px 8px; border-bottom: 2px solid #8399a7; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #dde3e7), color-stop(100%, #92a5b2)); background-image: -webkit-linear-gradient(top, #dde3e7, #92a5b2); background-image: -moz-linear-gradient(top, #dde3e7, #92a5b2); background-image: -o-linear-gradient(top, #dde3e7, #92a5b2); background-image: -ms-linear-gradient(top, #dde3e7, #92a5b2); background-image: linear-gradient(top, #dde3e7, #92a5b2); border-bottom: 3px solid #5c7382; padding: 8px; -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; -ms-border-radius: 0; -khtml-border-radius: 0; border-radius: 0; }
.cms .ui-widget-header { background-color: #b0bec7; padding: 8px 8px 6px 8px; border-bottom: 2px solid #8399a7; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #dde3e7), color-stop(100%, #92a5b2)); background-image: -webkit-linear-gradient(#dde3e7, #92a5b2); background-image: -moz-linear-gradient(#dde3e7, #92a5b2); background-image: -o-linear-gradient(#dde3e7, #92a5b2); background-image: -ms-linear-gradient(#dde3e7, #92a5b2); background-image: linear-gradient(#dde3e7, #92a5b2); border-bottom: 3px solid #5c7382; padding: 8px; -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; -ms-border-radius: 0; -khtml-border-radius: 0; border-radius: 0; }
.cms .ui-widget-header .ui-dialog-title { padding: 6px 0; text-shadow: #ced7dc 1px 1px 0; }
.cms .ui-widget-header a.ui-dialog-titlebar-close { position: absolute; top: -8px; right: -15px; width: 30px; height: 30px; z-index: 100000; }
.cms .ui-widget-header a.ui-state-hover { border-color: transparent; background: transparent; }
@ -214,16 +216,7 @@ input.radio { margin-left: 0; }
* (see _tree.scss and _menu.scss).
*/
/** ---------------------------------------------------- Core Styles. ---------------------------------------------------- */
html, body { width: 100%; height: 100%; font-size: 12px; line-height: 16px; font-family: Arial, sans-serif; color: #444444; }
html html, html body, html div, html span, html applet, html object, html iframe, html h1, html h2, html h3, html h4, html h5, html h6, html p, html blockquote, html pre, html a, html abbr, html acronym, html address, html big, html cite, html code, html del, html dfn, html em, html img, html ins, html kbd, html q, html s, html samp, html small, html strike, html strong, html sub, html sup, html tt, html var, html b, html u, html i, html center, html dl, html dt, html dd, html ol, html ul, html li, html fieldset, html form, html label, html legend, html table, html caption, html tbody, html tfoot, html thead, html tr, html th, html td, html article, html aside, html canvas, html details, html embed, html figure, html figcaption, html footer, html header, html hgroup, html menu, html nav, html output, html ruby, html section, html summary, html time, html mark, html audio, html video, body html, body body, body div, body span, body applet, body object, body iframe, body h1, body h2, body h3, body h4, body h5, body h6, body p, body blockquote, body pre, body a, body abbr, body acronym, body address, body big, body cite, body code, body del, body dfn, body em, body img, body ins, body kbd, body q, body s, body samp, body small, body strike, body strong, body sub, body sup, body tt, body var, body b, body u, body i, body center, body dl, body dt, body dd, body ol, body ul, body li, body fieldset, body form, body label, body legend, body table, body caption, body tbody, body tfoot, body thead, body tr, body th, body td, body article, body aside, body canvas, body details, body embed, body figure, body figcaption, body footer, body header, body hgroup, body menu, body nav, body output, body ruby, body section, body summary, body time, body mark, body audio, body video { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; }
html body, body body { line-height: 1; }
html ol, html ul, body ol, body ul { list-style: none; }
html table, body table { border-collapse: collapse; border-spacing: 0; }
html caption, html th, html td, body caption, body th, body td { text-align: left; font-weight: normal; vertical-align: middle; }
html q, html blockquote, body q, body blockquote { quotes: none; }
html q:before, html q:after, html blockquote:before, html blockquote:after, body q:before, body q:after, body blockquote:before, body blockquote:after { content: ""; content: none; }
html a img, body a img { border: none; }
html article, html aside, html details, html figcaption, html figure, html footer, html header, html hgroup, html menu, html nav, html section, html summary, body article, body aside, body details, body figcaption, body figure, body footer, body header, body hgroup, body menu, body nav, body section, body summary { display: block; }
html, body { width: 100%; height: 100%; }
body.cms { overflow: hidden; }
@ -243,24 +236,31 @@ body.cms { overflow: hidden; }
.cms-content-header { padding: 0px 8px 8px; height: 32px; z-index: 60; background-image: url(../images/textures/cms_content_header.png); background-repeat: repeat; }
.cms-content-header a { color: #1556b2; }
.cms-content-header h2 { float: left; padding: 8px 8px 0 0; font-size: 14px; line-height: 24px; font-weight: bold; text-shadow: #bfcad2 1px 1px 0; max-width: 400px; margin: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; o-text-overflow: ellipsis; }
.cms-content-header .backlink { float: left; margin-top: 7px; }
.cms-content-header h2 { float: left; padding: 8px 8px 0 8px; font-size: 14px; line-height: 24px; font-weight: bold; text-shadow: #bfcad2 1px 1px 0; max-width: 400px; margin: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; o-text-overflow: ellipsis; }
.cms-content-header > div { width: 9999em; overflow: hidden; }
.cms-content-header .cms-content-header-tabs { position: fixed; right: 40px; }
.cms-content-header .cms-content-header-tabs .ui-tabs-nav li a { font-weight: bold; line-height: 16px; padding: 12px 20px 11px; text-indent: -9999em; }
.cms-content-header .cms-content-header-tabs .ui-tabs-nav li a.content-treeview { background: url(../images/content-header-tabs-sprite.png) no-repeat 2px 0px; }
.cms-content-header .cms-content-header-tabs .ui-tabs-nav li a.content-galleryview { background: url(../images/content-header-tabs-sprite.png) no-repeat -87px 0px; }
.cms-content-header .cms-content-header-tabs .ui-tabs-nav li a.content-listview { background: url(../images/content-header-tabs-sprite.png) no-repeat -38px 0px; }
.cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-state-default, .cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-widget-content .ui-state-default, .cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-widget-header .ui-state-default { border-top: none; }
.cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-state-active, .cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-widget-content .ui-state-active, .cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-widget-header .ui-state-active { border-top: none; }
.cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-state-active a.content-treeview, .cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-widget-content .ui-state-active a.content-treeview, .cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-widget-header .ui-state-active a.content-treeview { background: url(../images/content-header-tabs-sprite.png) no-repeat 2px -40px; }
.cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-state-active a.content-galleryview, .cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-widget-content .ui-state-active a.content-galleryview, .cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-widget-header .ui-state-active a.content-galleryview { background: url(../images/content-header-tabs-sprite.png) no-repeat -87px -40px; }
.cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-state-active a.content-listview, .cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-widget-content .ui-state-active a.content-listview, .cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-widget-header .ui-state-active a.content-listview { background: url(../images/content-header-tabs-sprite.png) no-repeat -38px -40px; }
.cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-corner-all, .cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-corner-top, .cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-corner-right, .cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-corner-tr { border-radius: 0; }
.cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-corner-all, .cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-corner-top, .cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-corner-left, .cms-content-header .cms-content-header-tabs .ui-tabs-nav .ui-corner-tl { border-radius: 0; }
.cms-edit-form .cms-content-header-tabs .ui-tabs-nav li a { text-indent: 0; }
.cms-edit-form .cms-content-header-tabs .ui-tabs-nav .ui-state-default a, .cms-edit-form .cms-content-header-tabs .ui-tabs-nav .ui-widget-content .ui-state-default a, .cms-edit-form .cms-content-header-tabs .ui-tabs-nav .ui-widget-header .ui-state-default a { color: #1f1f1f; }
/** -------------------------------------------- Tabs -------------------------------------------- */
.ui-tabs .cms-content-header .ui-tabs-nav li, .cms-dialog .ui-tabs-nav li { margin: 0; }
.ui-tabs .cms-content-header .ui-tabs-nav li a, .cms-dialog .ui-tabs-nav li a { font-weight: bold; line-height: 16px; padding: 12px 20px 11px; }
.ui-tabs .cms-content-header .ui-tabs-nav li a.content-treeview, .cms-dialog .ui-tabs-nav li a.content-treeview { background: url(../images/content-header-tabs-sprite.png) no-repeat 2px 0px; }
.ui-tabs .cms-content-header .ui-tabs-nav li a.content-galleryview, .cms-dialog .ui-tabs-nav li a.content-galleryview { background: url(../images/content-header-tabs-sprite.png) no-repeat -87px 0px; }
.ui-tabs .cms-content-header .ui-tabs-nav li a.content-listview, .cms-dialog .ui-tabs-nav li a.content-listview { background: url(../images/content-header-tabs-sprite.png) no-repeat -38px 0px; }
.ui-tabs .cms-content-header .ui-tabs-nav .ui-state-default, .ui-tabs .cms-content-header .ui-tabs-nav .ui-widget-content .ui-state-default, .ui-tabs .cms-content-header .ui-tabs-nav .ui-widget-header .ui-state-default, .cms-dialog .ui-tabs-nav .ui-state-default, .cms-dialog .ui-tabs-nav .ui-widget-content .ui-state-default, .cms-dialog .ui-tabs-nav .ui-widget-header .ui-state-default { background-color: #b0bec7; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #b0bec7), color-stop(100%, #8ca1ae)); background-image: -webkit-linear-gradient(#b0bec7, #8ca1ae); background-image: -moz-linear-gradient(#b0bec7, #8ca1ae); background-image: -o-linear-gradient(#b0bec7, #8ca1ae); background-image: -ms-linear-gradient(#b0bec7, #8ca1ae); background-image: linear-gradient(#b0bec7, #8ca1ae); border-right-color: #a6a6a6; border-left-color: #d9d9d9; border-top: none; border-bottom: none; text-shadow: white 0 1px 0; }
.ui-tabs .cms-content-header .ui-tabs-nav .ui-state-active, .ui-tabs .cms-content-header .ui-tabs-nav .ui-widget-content .ui-state-active, .ui-tabs .cms-content-header .ui-tabs-nav .ui-widget-header .ui-state-active, .cms-dialog .ui-tabs-nav .ui-state-active, .cms-dialog .ui-tabs-nav .ui-widget-content .ui-state-active, .cms-dialog .ui-tabs-nav .ui-widget-header .ui-state-active { background: #eceff1; border-right-color: #a6a6a6; border-left-color: #a6a6a6; border-top: none; margin-right: -1px; margin-left: -1px; z-index: 2; }
.ui-tabs .cms-content-header .ui-tabs-nav .ui-state-default, .ui-tabs .cms-content-header .ui-tabs-nav .ui-widget-content .ui-state-default, .ui-tabs .cms-content-header .ui-tabs-nav .ui-widget-header .ui-state-default, .cms-dialog .ui-tabs-nav .ui-state-default, .cms-dialog .ui-tabs-nav .ui-widget-content .ui-state-default, .cms-dialog .ui-tabs-nav .ui-widget-header .ui-state-default { background-color: #b0bec7; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #b0bec7), color-stop(100%, #8ca1ae)); background-image: -webkit-linear-gradient(#b0bec7, #8ca1ae); background-image: -moz-linear-gradient(#b0bec7, #8ca1ae); background-image: -o-linear-gradient(#b0bec7, #8ca1ae); background-image: -ms-linear-gradient(#b0bec7, #8ca1ae); background-image: linear-gradient(#b0bec7, #8ca1ae); border-right-color: #a6a6a6; border-left-color: #d9d9d9; border-bottom: none; text-shadow: white 0 1px 0; }
.ui-tabs .cms-content-header .ui-tabs-nav .ui-state-active, .ui-tabs .cms-content-header .ui-tabs-nav .ui-widget-content .ui-state-active, .ui-tabs .cms-content-header .ui-tabs-nav .ui-widget-header .ui-state-active, .cms-dialog .ui-tabs-nav .ui-state-active, .cms-dialog .ui-tabs-nav .ui-widget-content .ui-state-active, .cms-dialog .ui-tabs-nav .ui-widget-header .ui-state-active { background: #eceff1; border-right-color: #a6a6a6; border-left-color: #a6a6a6; margin-right: -1px; margin-left: -1px; z-index: 2; }
.ui-tabs .cms-content-header .ui-tabs-nav .ui-state-active a, .ui-tabs .cms-content-header .ui-tabs-nav .ui-widget-content .ui-state-active a, .ui-tabs .cms-content-header .ui-tabs-nav .ui-widget-header .ui-state-active a, .cms-dialog .ui-tabs-nav .ui-state-active a, .cms-dialog .ui-tabs-nav .ui-widget-content .ui-state-active a, .cms-dialog .ui-tabs-nav .ui-widget-header .ui-state-active a { border-bottom: none; }
.ui-tabs .cms-content-header .ui-tabs-nav .ui-state-active a.content-treeview, .ui-tabs .cms-content-header .ui-tabs-nav .ui-widget-content .ui-state-active a.content-treeview, .ui-tabs .cms-content-header .ui-tabs-nav .ui-widget-header .ui-state-active a.content-treeview, .cms-dialog .ui-tabs-nav .ui-state-active a.content-treeview, .cms-dialog .ui-tabs-nav .ui-widget-content .ui-state-active a.content-treeview, .cms-dialog .ui-tabs-nav .ui-widget-header .ui-state-active a.content-treeview { background: url(../images/content-header-tabs-sprite.png) no-repeat 2px -40px; }
.ui-tabs .cms-content-header .ui-tabs-nav .ui-state-active a.content-galleryview, .ui-tabs .cms-content-header .ui-tabs-nav .ui-widget-content .ui-state-active a.content-galleryview, .ui-tabs .cms-content-header .ui-tabs-nav .ui-widget-header .ui-state-active a.content-galleryview, .cms-dialog .ui-tabs-nav .ui-state-active a.content-galleryview, .cms-dialog .ui-tabs-nav .ui-widget-content .ui-state-active a.content-galleryview, .cms-dialog .ui-tabs-nav .ui-widget-header .ui-state-active a.content-galleryview { background: url(../images/content-header-tabs-sprite.png) no-repeat -87px -40px; }
.ui-tabs .cms-content-header .ui-tabs-nav .ui-state-active a.content-listview, .ui-tabs .cms-content-header .ui-tabs-nav .ui-widget-content .ui-state-active a.content-listview, .ui-tabs .cms-content-header .ui-tabs-nav .ui-widget-header .ui-state-active a.content-listview, .cms-dialog .ui-tabs-nav .ui-state-active a.content-listview, .cms-dialog .ui-tabs-nav .ui-widget-content .ui-state-active a.content-listview, .cms-dialog .ui-tabs-nav .ui-widget-header .ui-state-active a.content-listview { background: url(../images/content-header-tabs-sprite.png) no-repeat -38px -40px; }
.ui-tabs .cms-content-header .ui-tabs-nav .ui-corner-all, .ui-tabs .cms-content-header .ui-tabs-nav .ui-corner-top, .ui-tabs .cms-content-header .ui-tabs-nav .ui-corner-right, .ui-tabs .cms-content-header .ui-tabs-nav .ui-corner-tr, .cms-dialog .ui-tabs-nav .ui-corner-all, .cms-dialog .ui-tabs-nav .ui-corner-top, .cms-dialog .ui-tabs-nav .ui-corner-right, .cms-dialog .ui-tabs-nav .ui-corner-tr { border-radius: 0; }
.ui-tabs .cms-content-header .ui-tabs-nav .ui-corner-all, .ui-tabs .cms-content-header .ui-tabs-nav .ui-corner-top, .ui-tabs .cms-content-header .ui-tabs-nav .ui-corner-left, .ui-tabs .cms-content-header .ui-tabs-nav .ui-corner-tl, .cms-dialog .ui-tabs-nav .ui-corner-all, .cms-dialog .ui-tabs-nav .ui-corner-top, .cms-dialog .ui-tabs-nav .ui-corner-left, .cms-dialog .ui-tabs-nav .ui-corner-tl { border-radius: 0; }
/** ------------------------------------------------------- Loading Interface ------------------------------------------------------- */
.cms-content-loading-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 9998; }
@ -308,7 +308,7 @@ body.cms { overflow: hidden; }
/** -------------------------------------------- Content toolbar -------------------------------------------- */
.cms-content-toolbar { display: block; margin: 0 0 15px 0; border-bottom: 1px solid rgba(201, 205, 206, 0.8); -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.8); -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.8); -o-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.8); box-shadow: 0 1px 0 rgba(255, 255, 255, 0.8); *zoom: 1; /* smaller treedropdown */ }
.cms-content-toolbar:after { content: "\0020"; display: block; height: 0; clear: both; overflow: hidden; visibility: hidden; }
.cms-content-toolbar > * { float: right; }
.cms-content-toolbar .cms-tree-view-modes { float: right; padding-top: 5px; }
.cms-content-toolbar .cms-tree-view-modes * { display: inline-block; }
.cms-content-toolbar .cms-tree-view-modes * label { color: #1556b2; }
.cms-content-toolbar .chzn-container-single .chzn-single { height: 26px; line-height: 26px; padding-left: 25px; color: #576468; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #e6e6e6), color-stop(100%, #cdcdcd)); background-image: -webkit-linear-gradient(#e6e6e6, #cdcdcd); background-image: -moz-linear-gradient(#e6e6e6, #cdcdcd); background-image: -o-linear-gradient(#e6e6e6, #cdcdcd); background-image: -ms-linear-gradient(#e6e6e6, #cdcdcd); background-image: linear-gradient(#e6e6e6, #cdcdcd); font-size: 13px; font-weight: bold; text-shadow: #e6e6e6 0 -1px 1px; box-shadow: none; }
@ -320,9 +320,9 @@ body.cms { overflow: hidden; }
/* -------------------------------------------------------- Content Tools is the sidebar on the left of the main content panel */
.cms-content-tools { background-color: #dde3e7; width: 192px; border-right: 1px solid #bfcad2; overflow-y: auto; overflow-x: hidden; z-index: 70; -moz-box-shadow: rgba(107, 120, 123, 0.5) 0 0 4px; -webkit-box-shadow: rgba(107, 120, 123, 0.5) 0 0 4px; -o-box-shadow: rgba(107, 120, 123, 0.5) 0 0 4px; box-shadow: rgba(107, 120, 123, 0.5) 0 0 4px; float: left; position: relative; }
.cms-content-tools .cms-panel-header { padding: 0; margin: 0 0 7px; line-height: 24px; border-bottom: 1px solid rgba(201, 205, 206, 0.8); -webkit-box-shadow: 0 1px 0 rgba(228, 230, 230, 0.8); -moz-box-shadow: 0 1px 0 rgba(228, 230, 230, 0.8); -o-box-shadow: 0 1px 0 rgba(228, 230, 230, 0.8); box-shadow: 0 1px 0 rgba(228, 230, 230, 0.8); }
.cms-content-tools .cms-panel-content { width: 176px; padding: 8px 8px; overflow: auto; }
.cms-content-tools .cms-content-header { background-color: #748d9d; border-bottom: 2px solid #5c7382; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #b0bec7), color-stop(100%, #748d9d)); background-image: -webkit-linear-gradient(#b0bec7, #748d9d); background-image: -moz-linear-gradient(#b0bec7, #748d9d); background-image: -o-linear-gradient(#b0bec7, #748d9d); background-image: -ms-linear-gradient(#b0bec7, #748d9d); background-image: linear-gradient(#b0bec7, #748d9d); }
.cms-content-tools .cms-panel-header { margin: 0 0 7px; line-height: 24px; border-bottom: 1px solid rgba(201, 205, 206, 0.8); -webkit-box-shadow: 0 1px 0 rgba(228, 230, 230, 0.8); -moz-box-shadow: 0 1px 0 rgba(228, 230, 230, 0.8); -o-box-shadow: 0 1px 0 rgba(228, 230, 230, 0.8); box-shadow: 0 1px 0 rgba(228, 230, 230, 0.8); }
.cms-content-tools .cms-panel-content { width: 176px; padding: 8px 8px; overflow: auto; height: 100%; }
.cms-content-tools .cms-content-header { background-color: #748d9d; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #b0bec7), color-stop(100%, #748d9d)); background-image: -webkit-linear-gradient(#b0bec7, #748d9d); background-image: -moz-linear-gradient(#b0bec7, #748d9d); background-image: -o-linear-gradient(#b0bec7, #748d9d); background-image: -ms-linear-gradient(#b0bec7, #748d9d); background-image: linear-gradient(#b0bec7, #748d9d); }
.cms-content-tools .cms-content-header h2 { text-shadow: #5c7382 -1px -1px 0; width: 176px; color: white; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; o-text-overflow: ellipsis; }
.cms-content-tools h3, .cms-content-tools h4, .cms-content-tools h5 { font-weight: bold; line-height: 16px; }
.cms-content-tools h3 { font-size: 13px; }
@ -382,6 +382,9 @@ form.member-profile-form .formattingHelpText li { font-size: 11px; color: #333;
form.member-profile-form #Groups .middleColumn { margin-left: 0; width: 100%; }
form.member-profile-form #Groups .middleColumn .TreeDropdownField { width: 90%; max-width: 90%; }
form.member-profile-form #Permissions .optionset li { float: none; width: auto; }
form.member-profile-form .ui-tabs-nav li { margin: 0 0 -1px 0; }
form.member-profile-form .ui-corner-all, form.member-profile-form .ui-corner-top, form.member-profile-form .ui-corner-right, form.member-profile-form .ui-corner-tr { border-radius: 0; }
form.member-profile-form .ui-corner-all, form.member-profile-form .ui-corner-top, form.member-profile-form .ui-corner-left, form.member-profile-form .ui-corner-tl { border-radius: 0; }
.cms .cms-content { border-right: 1px solid rgba(201, 205, 206, 0.8); -moz-box-shadow: 3px 0 4px rgba(0, 0, 0, 0.15); -webkit-box-shadow: 3px 0 4px rgba(0, 0, 0, 0.15); -o-box-shadow: 3px 0 4px rgba(0, 0, 0, 0.15); box-shadow: 3px 0 4px rgba(0, 0, 0, 0.15); -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; -ms-border-radius: 0; -khtml-border-radius: 0; border-radius: 0; }
.cms .cms-content-fields { /* always show a y scroll bar as popups like TreeDropdowns can trigger longer pages and the extra scroll bar doesn't fire our sizing bar */ overflow-y: auto; overflow-x: auto; background: none; width: 100%; }
@ -396,8 +399,12 @@ form.member-profile-form #Permissions .optionset li { float: none; width: auto;
.cms-panel.collapsed .cms-panel-header * { display: none; }
.cms-panel.collapsed .cms-panel-content { display: none; }
.cms-panel .cms-panel-header { width: 100%; }
.cms-panel#cms-content-tools-CMSPageEditController .cms-panel-content-collapsed { width: 40px; display: none; }
.cms-panel#cms-content-tools-CMSPageEditController .cms-panel-content-collapsed h2, .cms-panel#cms-content-tools-CMSPageEditController .cms-panel-content-collapsed h3 { border-bottom: 0; margin-left: 8px; -moz-transform-origin: bottom right; -webkit-transform-origin: bottom right; -o-transform-origin: bottom right; -ms-transform-origin: bottom right; transform-origin: bottom right; -moz-transform: rotate(270deg); -webkit-transform: rotate(270deg); -o-transform: rotate(270deg); -ms-transform: rotate(270deg); transform: rotate(270deg); }
.cms-panel#cms-content-tools-CMSPageEditController .cms-panel-content-collapsed .cms-panel-header { width: 600px; position: relative; top: 24px; right: 577px; text-align: right; }
.cms-panel .cms-panel-content-collapsed { width: 40px; display: none; }
.cms-panel .cms-panel-content-collapsed h2, .cms-panel .cms-panel-content-collapsed h3 { border-bottom: 0; margin-left: 8px; -moz-transform-origin: bottom left; -webkit-transform-origin: bottom left; -o-transform-origin: bottom left; -ms-transform-origin: bottom left; transform-origin: bottom left; -moz-transform: rotate(90deg); -webkit-transform: rotate(90deg); -o-transform: rotate(90deg); -ms-transform: rotate(90deg); transform: rotate(90deg); }
.cms-panel .cms-panel-content-collapsed h2, .cms-panel .cms-panel-content-collapsed h3 { border-bottom: 0; margin-left: 8px; -moz-transform-origin: bottom right; -webkit-transform-origin: bottom right; -o-transform-origin: bottom right; -ms-transform-origin: bottom right; transform-origin: bottom right; -moz-transform: rotate(270deg); -webkit-transform: rotate(270deg); -o-transform: rotate(270deg); -ms-transform: rotate(270deg); transform: rotate(270deg); }
.cms-panel .cms-panel-content-collapsed .cms-panel-header { width: 600px; position: relative; right: 577px; text-align: right; }
.cms-panel .child-flyout-indicator { width: 0; height: 0; border-right: 3px dashed #1f1f1f; border-top: 3px solid transparent; border-left: 3px solid transparent; border-bottom: 3px dashed #1f1f1f; position: absolute; right: 1px; margin-top: -8px; display: none; /* To be shown by javascript, see LeftAndMain.Panel.js */ }
.cms-panel .collapsed-flyout { display: block !important; left: 41px; margin-top: -40px; position: fixed; width: 191px; }
.cms-panel .collapsed-flyout li a span { display: block !important; }
@ -452,102 +459,108 @@ body.cms-dialog { overflow: auto; background: url("../images/textures/bg_cms_mai
.step-label .title { height: 18px; padding: 4px; }
/** -------------------------------------------- Item Edit Form -------------------------------------------- */
#Form_ItemEditForm .field { width: 100%; }
#Form_ItemEditForm .field .fieldgroup { height: 230px; float: left; }
#Form_ItemEditForm .field .fieldgroup .fieldgroup-field.first { position: relative; margin-left: 0px; }
#Form_ItemEditForm .field .fieldgroup .fieldgroup-field { clear: both; width: 500px; margin-left: 420px; }
#Form_ItemEditForm .field .fieldgroup .fieldgroup-field img { -moz-border-radius: 8px; -webkit-border-radius: 8px; -o-border-radius: 8px; -ms-border-radius: 8px; -khtml-border-radius: 8px; border-radius: 8px; border-width: 3px; border-style: dashed; border-color: #8c99a1; position: absolute; top: 8px; }
#Form_ItemEditForm .field .fieldgroup .fieldgroup-field label { font-weight: bold; float: left; padding-top: 8px; line-height: 16px; text-shadow: white 1px 1px 0; }
#Form_ItemEditForm .field .fieldgroup .fieldgroup-field span { float: left; padding-left: 8px; font-style: italic; color: #777777; }
.cms-file-info { overflow: auto; border-bottom: 1px solid rgba(201, 205, 206, 0.8); -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.8); -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.8); -o-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.8); box-shadow: 0 1px 0 rgba(255, 255, 255, 0.8); margin-bottom: 8px; }
.cms-file-info .cms-file-info-preview { float: left; width: 176px; margin-right: 8px; }
.cms-file-info .cms-file-info-preview img { max-width: 176px; }
.cms-file-info .cms-file-info-data { float: left; }
.cms-file-info .cms-file-info-data .field { margin-bottom: 0; padding-bottom: 8px; border: none; box-shadow: none; }
.cms-file-info .cms-file-info-data .field label, .cms-file-info .cms-file-info-data .field span { padding: 0; }
form.small .cms-file-info-preview { width: 112px; }
form.small .cms-file-info-preview img { max-width: 112px; }
form.small .cms-file-info-data { max-width: 350px; }
form.small .cms-file-info-data .field { padding-bottom: 0; }
form.small .cms-file-info-data .field label { width: 112px; }
form.small .cms-file-info-data .field .middleColumn { margin-left: 120px; }
/** This file defines the jstree base styling (see http://jstree.com), as well as any customizations (see bottom of file). The styles are usually added through jstree.js on DOM load, but we need it earlier in order to correctly display the uninitialized tree. */
.cms .jstree ul { display: block; margin: 0; padding: 0; background: none; list-style-type: none; }
.cms .jstree li { display: block; margin: 0; padding: 0; list-style-type: none; display: block; min-height: 18px; line-height: 18px; white-space: nowrap; margin-left: 18px; min-width: 18px; }
.cms .jstree ins { display: inline-block; text-decoration: none; width: 18px; height: 18px; margin: 0 0 0 0; padding: 0; float: left; }
.cms .jstree a { display: inline-block; line-height: 16px; height: 16px; color: black; white-space: nowrap; text-decoration: none; padding: 1px 2px; margin: 0; border: 1px solid #fff; }
.cms .jstree a:focus, .cms .jstree a:active, .cms .jstree a:hover { outline: none; text-decoration: none; cursor: pointer; text-shadow: none; }
.cms .jstree a > ins { height: 16px; width: 16px; }
.cms .jstree a > .jstree-icon { margin-right: 3px; }
.cms .jstree li.jstree-open > ul { display: block; }
.cms .jstree li.jstree-closed > ul { display: none; }
.cms .jstree li.disabled a { color: #aaaaaa; }
.cms .jstree-rtl a > .jstree-icon { margin-left: 3px; margin-right: 0; }
.cms .jstree-rtl li { margin-left: 0; margin-right: 18px; }
.cms .jstree-rtl > ul > li { margin-right: 0px; }
.cms .jstree > ul > li { margin-left: 0px; }
.cms #vakata-dragged { display: block; margin: 0 0 0 0; padding: 4px 4px 4px 24px; position: absolute; top: -2000px; line-height: 16px; z-index: 10000; }
.cms #vakata-contextmenu { display: block; visibility: hidden; left: 0; top: -200px; position: absolute; margin: 0; padding: 0; min-width: 180px; background: #ebebeb; border: 1px solid silver; z-index: 10000; *width: 180px; }
.cms #vakata-contextmenu ul { min-width: 180px; *width: 180px; }
.cms #vakata-contextmenu ul, .cms #vakata-contextmenu li { margin: 0; padding: 0; list-style-type: none; display: block; }
.cms #vakata-contextmenu li { line-height: 20px; min-height: 20px; position: relative; padding: 0px; }
.cms #vakata-contextmenu li a { padding: 1px 6px; line-height: 17px; display: block; text-decoration: none; margin: 1px 1px 0 1px; }
.cms #vakata-contextmenu li ins { float: left; width: 16px; height: 16px; text-decoration: none; margin-right: 2px; }
.cms #vakata-contextmenu li a:hover, .cms #vakata-contextmenu li.vakata-hover > a { background: gray; color: white; }
.cms #vakata-contextmenu li ul { display: none; position: absolute; top: -2px; left: 100%; background: #ebebeb; border: 1px solid gray; }
.cms #vakata-contextmenu .right { right: 100%; left: auto; }
.cms #vakata-contextmenu .bottom { bottom: -1px; top: auto; }
.cms #vakata-contextmenu li.vakata-separator { min-height: 0; height: 1px; line-height: 1px; font-size: 1px; overflow: hidden; margin: 0 2px; background: silver; /* border-top:1px solid #fefefe; */ padding: 0; }
.cms .jstree ul, .cms .jstree li { display: block; margin: 0 0 0 0; padding: 0 0 0 0; list-style-type: none; }
.cms .jstree li { display: block; min-height: 18px; line-height: 18px; white-space: nowrap; margin-left: 18px; min-width: 18px; }
.cms .jstree-rtl li { margin-left: 0; margin-right: 18px; }
.cms .jstree > ul > li { margin-left: 0px; }
.cms .jstree-rtl > ul > li { margin-right: 0px; }
.cms .jstree ins { display: inline-block; text-decoration: none; width: 18px; height: 18px; margin: 0 0 0 0; padding: 0; }
.cms .jstree a { display: inline-block; line-height: 16px; height: 16px; color: black; white-space: nowrap; text-decoration: none; padding: 1px 2px; margin: 0; }
.cms .jstree a:focus { outline: none; }
.cms .jstree a > ins { height: 16px; width: 16px; }
.cms .jstree a > .jstree-icon { margin-right: 3px; }
.cms .jstree-rtl a > .jstree-icon { margin-left: 3px; margin-right: 0; }
.cms li.jstree-open > ul { display: block; margin-left: -13px; }
.cms li.jstree-open > ul li ul { margin-left: 2px; }
.cms li.jstree-closed > ul { display: none; }
.cms #vakata-dragged ins { display: block; text-decoration: none; width: 16px; height: 16px; margin: 0 0 0 0; padding: 0; position: absolute; top: 4px; left: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-border-radius: 4px; }
.cms #vakata-dragged .jstree-ok { background: green; }
.cms #vakata-dragged .jstree-invalid { background: red; }
.cms #jstree-marker { padding: 0; margin: 0; font-size: 12px; overflow: hidden; height: 12px; width: 8px; position: absolute; top: -30px; z-index: 10001; background-repeat: no-repeat; display: none; background-color: transparent; text-shadow: 1px 1px 1px white; color: black; line-height: 10px; }
.cms #jstree-marker-line { padding: 0; margin: 0; line-height: 0%; font-size: 1px; overflow: hidden; height: 1px; width: 100px; position: absolute; top: -30px; z-index: 10000; background-repeat: no-repeat; display: none; background-color: #456c43; cursor: pointer; border: 1px solid #eeeeee; border-left: 0; -moz-box-shadow: 0px 0px 2px #666; -webkit-box-shadow: 0px 0px 2px #666; box-shadow: 0px 0px 2px #666; -moz-border-radius: 1px; border-radius: 1px; -webkit-border-radius: 1px; }
.cms .jstree .jstree-real-checkbox { display: none; }
.cms .jstree-themeroller .ui-icon { overflow: visible; }
.cms .jstree-themeroller a { padding: 0 2px; }
.cms .jstree-themeroller .jstree-no-icon { display: none; }
.cms .jstree .jstree-wholerow-real { position: relative; z-index: 1; }
.cms .jstree .jstree-wholerow-real li { cursor: pointer; }
.cms .jstree .jstree-wholerow-real a { border-left-color: transparent !important; border-right-color: transparent !important; }
.cms .jstree .jstree-wholerow { position: relative; z-index: 0; height: 0; }
.cms .jstree .jstree-wholerow ul, .cms .jstree .jstree-wholerow li { width: 100%; }
.cms .jstree .jstree-wholerow, .cms .jstree .jstree-wholerow ul, .cms .jstree .jstree-wholerow li, .cms .jstree .jstree-wholerow a { margin: 0 !important; padding: 0 !important; }
.cms .jstree .jstree-wholerow, .cms .jstree .jstree-wholerow ul, .cms .jstree .jstree-wholerow li { background: transparent !important; }
.cms .jstree .jstree-wholerow ins, .cms .jstree .jstree-wholerow span, .cms .jstree .jstree-wholerow input { display: none !important; }
.cms .jstree .jstree-wholerow a, .cms .jstree .jstree-wholerow a:hover { text-indent: -9999px !important; width: 100%; padding: 0 !important; border-right-width: 0px !important; border-left-width: 0px !important; }
.cms .jstree .jstree-wholerow-span { position: absolute; left: 0; margin: 0px; padding: 0; height: 18px; border-width: 0; padding: 0; z-index: 0; }
.cms .jstree-apple.jstree-focused { background: none; }
.cms .jstree-apple.jstree-focused .jstree-apple > ul { background: none; }
.cms .jstree li { line-height: 25px; }
.cms .jstree ul, .TreeDropdownField .treedropdownfield-panel .jstree ul { display: block; margin: 0; padding: 0; background: none; list-style-type: none; }
.cms .jstree li, .TreeDropdownField .treedropdownfield-panel .jstree li { display: block; margin: 0; padding: 0; list-style-type: none; display: block; min-height: 18px; line-height: 18px; white-space: nowrap; margin-left: 18px; min-width: 18px; }
.cms .jstree ins, .TreeDropdownField .treedropdownfield-panel .jstree ins { display: inline-block; text-decoration: none; width: 18px; height: 18px; margin: 0 0 0 0; padding: 0; float: left; }
.cms .jstree a, .TreeDropdownField .treedropdownfield-panel .jstree a { display: inline-block; line-height: 16px; height: 16px; color: black; white-space: nowrap; text-decoration: none; padding: 1px 2px; margin: 0; border: 1px solid #fff; }
.cms .jstree a:focus, .cms .jstree a:active, .cms .jstree a:hover, .TreeDropdownField .treedropdownfield-panel .jstree a:focus, .TreeDropdownField .treedropdownfield-panel .jstree a:active, .TreeDropdownField .treedropdownfield-panel .jstree a:hover { outline: none; text-decoration: none; cursor: pointer; text-shadow: none; }
.cms .jstree a > ins, .TreeDropdownField .treedropdownfield-panel .jstree a > ins { height: 16px; width: 16px; }
.cms .jstree a > .jstree-icon, .TreeDropdownField .treedropdownfield-panel .jstree a > .jstree-icon { margin-right: 3px; }
.cms .jstree li.jstree-open > ul, .TreeDropdownField .treedropdownfield-panel .jstree li.jstree-open > ul { display: block; }
.cms .jstree li.jstree-closed > ul, .TreeDropdownField .treedropdownfield-panel .jstree li.jstree-closed > ul { display: none; }
.cms .jstree li.disabled a, .TreeDropdownField .treedropdownfield-panel .jstree li.disabled a { color: #aaaaaa; }
.cms .jstree-rtl a > .jstree-icon, .TreeDropdownField .treedropdownfield-panel .jstree-rtl a > .jstree-icon { margin-left: 3px; margin-right: 0; }
.cms .jstree-rtl li, .TreeDropdownField .treedropdownfield-panel .jstree-rtl li { margin-left: 0; margin-right: 18px; }
.cms .jstree-rtl > ul > li, .TreeDropdownField .treedropdownfield-panel .jstree-rtl > ul > li { margin-right: 0px; }
.cms .jstree > ul > li, .TreeDropdownField .treedropdownfield-panel .jstree > ul > li { margin-left: 0px; }
.cms #vakata-dragged, .TreeDropdownField .treedropdownfield-panel #vakata-dragged { display: block; margin: 0 0 0 0; padding: 4px 4px 4px 24px; position: absolute; top: -2000px; line-height: 16px; z-index: 10000; }
.cms #vakata-contextmenu, .TreeDropdownField .treedropdownfield-panel #vakata-contextmenu { display: block; visibility: hidden; left: 0; top: -200px; position: absolute; margin: 0; padding: 0; min-width: 180px; background: #ebebeb; border: 1px solid silver; z-index: 10000; *width: 180px; }
.cms #vakata-contextmenu ul, .TreeDropdownField .treedropdownfield-panel #vakata-contextmenu ul { min-width: 180px; *width: 180px; }
.cms #vakata-contextmenu ul, .cms #vakata-contextmenu li, .TreeDropdownField .treedropdownfield-panel #vakata-contextmenu ul, .TreeDropdownField .treedropdownfield-panel #vakata-contextmenu li { margin: 0; padding: 0; list-style-type: none; display: block; }
.cms #vakata-contextmenu li, .TreeDropdownField .treedropdownfield-panel #vakata-contextmenu li { line-height: 20px; min-height: 20px; position: relative; padding: 0px; }
.cms #vakata-contextmenu li a, .TreeDropdownField .treedropdownfield-panel #vakata-contextmenu li a { padding: 1px 6px; line-height: 17px; display: block; text-decoration: none; margin: 1px 1px 0 1px; }
.cms #vakata-contextmenu li ins, .TreeDropdownField .treedropdownfield-panel #vakata-contextmenu li ins { float: left; width: 16px; height: 16px; text-decoration: none; margin-right: 2px; }
.cms #vakata-contextmenu li a:hover, .cms #vakata-contextmenu li.vakata-hover > a, .TreeDropdownField .treedropdownfield-panel #vakata-contextmenu li a:hover, .TreeDropdownField .treedropdownfield-panel #vakata-contextmenu li.vakata-hover > a { background: gray; color: white; }
.cms #vakata-contextmenu li ul, .TreeDropdownField .treedropdownfield-panel #vakata-contextmenu li ul { display: none; position: absolute; top: -2px; left: 100%; background: #ebebeb; border: 1px solid gray; }
.cms #vakata-contextmenu .right, .TreeDropdownField .treedropdownfield-panel #vakata-contextmenu .right { right: 100%; left: auto; }
.cms #vakata-contextmenu .bottom, .TreeDropdownField .treedropdownfield-panel #vakata-contextmenu .bottom { bottom: -1px; top: auto; }
.cms #vakata-contextmenu li.vakata-separator, .TreeDropdownField .treedropdownfield-panel #vakata-contextmenu li.vakata-separator { min-height: 0; height: 1px; line-height: 1px; font-size: 1px; overflow: hidden; margin: 0 2px; background: silver; /* border-top:1px solid #fefefe; */ padding: 0; }
.cms .jstree ul, .cms .jstree li, .TreeDropdownField .treedropdownfield-panel .jstree ul, .TreeDropdownField .treedropdownfield-panel .jstree li { display: block; margin: 0 0 0 0; padding: 0 0 0 0; list-style-type: none; }
.cms .jstree li, .TreeDropdownField .treedropdownfield-panel .jstree li { display: block; min-height: 18px; line-height: 18px; white-space: nowrap; margin-left: 18px; min-width: 18px; }
.cms .jstree-rtl li, .TreeDropdownField .treedropdownfield-panel .jstree-rtl li { margin-left: 0; margin-right: 18px; }
.cms .jstree > ul > li, .TreeDropdownField .treedropdownfield-panel .jstree > ul > li { margin-left: 0px; }
.cms .jstree-rtl > ul > li, .TreeDropdownField .treedropdownfield-panel .jstree-rtl > ul > li { margin-right: 0px; }
.cms .jstree ins, .TreeDropdownField .treedropdownfield-panel .jstree ins { display: inline-block; text-decoration: none; width: 18px; height: 18px; margin: 0 0 0 0; padding: 0; }
.cms .jstree a, .TreeDropdownField .treedropdownfield-panel .jstree a { display: inline-block; line-height: 16px; height: 16px; color: black; white-space: nowrap; text-decoration: none; padding: 1px 2px; margin: 0; }
.cms .jstree a:focus, .TreeDropdownField .treedropdownfield-panel .jstree a:focus { outline: none; }
.cms .jstree a > ins, .TreeDropdownField .treedropdownfield-panel .jstree a > ins { height: 16px; width: 16px; }
.cms .jstree a > .jstree-icon, .TreeDropdownField .treedropdownfield-panel .jstree a > .jstree-icon { margin-right: 3px; }
.cms .jstree-rtl a > .jstree-icon, .TreeDropdownField .treedropdownfield-panel .jstree-rtl a > .jstree-icon { margin-left: 3px; margin-right: 0; }
.cms li.jstree-open > ul, .TreeDropdownField .treedropdownfield-panel li.jstree-open > ul { display: block; margin-left: -13px; }
.cms li.jstree-open > ul li ul, .TreeDropdownField .treedropdownfield-panel li.jstree-open > ul li ul { margin-left: 2px; }
.cms li.jstree-closed > ul, .TreeDropdownField .treedropdownfield-panel li.jstree-closed > ul { display: none; }
.cms #vakata-dragged ins, .TreeDropdownField .treedropdownfield-panel #vakata-dragged ins { display: block; text-decoration: none; width: 16px; height: 16px; margin: 0 0 0 0; padding: 0; position: absolute; top: 4px; left: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-border-radius: 4px; }
.cms #vakata-dragged .jstree-ok, .TreeDropdownField .treedropdownfield-panel #vakata-dragged .jstree-ok { background: green; }
.cms #vakata-dragged .jstree-invalid, .TreeDropdownField .treedropdownfield-panel #vakata-dragged .jstree-invalid { background: red; }
.cms #jstree-marker, .TreeDropdownField .treedropdownfield-panel #jstree-marker { padding: 0; margin: 0; font-size: 12px; overflow: hidden; height: 12px; width: 8px; position: absolute; top: -30px; z-index: 10001; background-repeat: no-repeat; display: none; background-color: transparent; text-shadow: 1px 1px 1px white; color: black; line-height: 10px; }
.cms #jstree-marker-line, .TreeDropdownField .treedropdownfield-panel #jstree-marker-line { padding: 0; margin: 0; line-height: 0%; font-size: 1px; overflow: hidden; height: 1px; width: 100px; position: absolute; top: -30px; z-index: 10000; background-repeat: no-repeat; display: none; background-color: #456c43; cursor: pointer; border: 1px solid #eeeeee; border-left: 0; -moz-box-shadow: 0px 0px 2px #666; -webkit-box-shadow: 0px 0px 2px #666; box-shadow: 0px 0px 2px #666; -moz-border-radius: 1px; border-radius: 1px; -webkit-border-radius: 1px; }
.cms .jstree .jstree-real-checkbox, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-real-checkbox { display: none; }
.cms .jstree-themeroller .ui-icon, .TreeDropdownField .treedropdownfield-panel .jstree-themeroller .ui-icon { overflow: visible; }
.cms .jstree-themeroller a, .TreeDropdownField .treedropdownfield-panel .jstree-themeroller a { padding: 0 2px; }
.cms .jstree-themeroller .jstree-no-icon, .TreeDropdownField .treedropdownfield-panel .jstree-themeroller .jstree-no-icon { display: none; }
.cms .jstree .jstree-wholerow-real, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-wholerow-real { position: relative; z-index: 1; }
.cms .jstree .jstree-wholerow-real li, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-wholerow-real li { cursor: pointer; }
.cms .jstree .jstree-wholerow-real a, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-wholerow-real a { border-left-color: transparent !important; border-right-color: transparent !important; }
.cms .jstree .jstree-wholerow, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-wholerow { position: relative; z-index: 0; height: 0; }
.cms .jstree .jstree-wholerow ul, .cms .jstree .jstree-wholerow li, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-wholerow ul, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-wholerow li { width: 100%; }
.cms .jstree .jstree-wholerow, .cms .jstree .jstree-wholerow ul, .cms .jstree .jstree-wholerow li, .cms .jstree .jstree-wholerow a, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-wholerow, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-wholerow ul, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-wholerow li, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-wholerow a { margin: 0 !important; padding: 0 !important; }
.cms .jstree .jstree-wholerow, .cms .jstree .jstree-wholerow ul, .cms .jstree .jstree-wholerow li, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-wholerow, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-wholerow ul, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-wholerow li { background: transparent !important; }
.cms .jstree .jstree-wholerow ins, .cms .jstree .jstree-wholerow span, .cms .jstree .jstree-wholerow input, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-wholerow ins, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-wholerow span, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-wholerow input { display: none !important; }
.cms .jstree .jstree-wholerow a, .cms .jstree .jstree-wholerow a:hover, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-wholerow a, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-wholerow a:hover { text-indent: -9999px !important; width: 100%; padding: 0 !important; border-right-width: 0px !important; border-left-width: 0px !important; }
.cms .jstree .jstree-wholerow-span, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-wholerow-span { position: absolute; left: 0; margin: 0px; padding: 0; height: 18px; border-width: 0; padding: 0; z-index: 0; }
.cms .jstree-apple.jstree-focused, .TreeDropdownField .treedropdownfield-panel .jstree-apple.jstree-focused { background: none; }
.cms .jstree-apple.jstree-focused .jstree-apple > ul, .TreeDropdownField .treedropdownfield-panel .jstree-apple.jstree-focused .jstree-apple > ul { background: none; }
.cms .jstree li, .TreeDropdownField .treedropdownfield-panel .jstree li { line-height: 25px; }
.jstree-apple li, .jstree-apple .jstree-apple ins { background: none; }
.jstree-apple .jstree-unchecked > a > .jstree-checkbox { margin-right: 3px; }
.jstree-apple .jstree-checked > a > .jstree-checkbox { margin-right: 3px; }
.jstree-apple .jstree-undetermined > a > .jstree-checkbox { margin-right: 3px; }
.cms-tree.jstree-apple { /* comment speech bubble - ccs3 only - source: http://nicolasgallagher.com/pure-css-speech-bubbles/demo/ */ }
.cms-tree.jstree-apple li.Root strong { font-weight: bold; padding-left: 1px; }
.cms-tree.jstree-apple li.Root > a .jstree-icon { background-position: -56px -36px; }
.cms-tree.jstree-apple a, .cms-tree.jstree-apple a:link { color: #1556b2; padding: 3px 6px 3px 3px; border: none; display: inline-block; margin-right: 5px; }
.cms-tree.jstree-apple span.badge { clear: both; text-transform: uppercase; display: inline-block; padding: 0px 3px; font-size: 0.75em; line-height: 1em; margin-left: 3px; margin-right: 6px; margin-top: -1px; -webkit-border-radius: 2px 2px; -moz-border-radius: 2px / 2px; -o-border-radius: 2px / 2px; -ms-border-radius: 2px / 2px; -khtml-border-radius: 2px / 2px; border-radius: 2px / 2px; }
.cms-tree.jstree-apple span.badge.modified { color: #7E7470; border: 1px solid #C9B800; background-color: #FFF0BC; }
.cms-tree.jstree-apple span.badge.addedtodraft { color: #7E7470; border: 1px solid #C9B800; background-color: #FFF0BC; }
.cms-tree.jstree-apple span.badge.deletedonlive { color: #636363; border: 1px solid #E49393; background-color: #F2DADB; }
.cms-tree.jstree-apple span.badge.removedfromdraft { color: #636363; border: 1px solid #E49393; background-color: #F2DADB; }
.cms-tree.jstree-apple span.badge.workflow-approval { color: #56660C; border: 1px solid #7C8816; background-color: #DAE79A; }
.cms-tree.jstree-apple span.comment-count { clear: both; position: relative; text-transform: uppercase; display: inline-block; overflow: visible; padding: 0px 3px; font-size: 0.75em; line-height: 1em; margin-left: 3px; margin-right: 6px; -webkit-border-radius: 2px 2px; -moz-border-radius: 2px / 2px; -o-border-radius: 2px / 2px; -ms-border-radius: 2px / 2px; -khtml-border-radius: 2px / 2px; border-radius: 2px / 2px; color: #7E7470; border: 1px solid #C9B800; background-color: #FFF0BC; }
.cms-tree.jstree-apple span.comment-count:before { content: ""; position: absolute; bottom: -4px; /* value = - border-top-width - border-bottom-width */ left: 3px; /* controls horizontal position */ border-width: 4px 4px 0; border-style: solid; border-color: #C9B800 transparent; /* reduce the damage in FF3.0 */ display: block; width: 0; }
.cms-tree.jstree-apple span.comment-count:after { content: ""; position: absolute; bottom: -3px; /* value = - border-top-width - border-bottom-width */ left: 4px; /* value = (:before left) + (:before border-left) - (:after border-left) */ border-width: 3px 3px 0; border-style: solid; border-color: #FFF0BC transparent; /* reduce the damage in FF3.0 */ display: block; width: 0; }
.cms-tree.jstree-apple .jstree-hovered { text-shadow: none; text-decoration: none; }
.cms-tree.jstree-apple li { padding: 0px; clear: left; }
.cms-tree.jstree-apple ins { background-color: transparent; background-image: url(../images/sitetree_ss_default_icons.png); }
.cms-tree.jstree-apple li.jstree-checked a, .cms-tree.jstree-apple li.jstree-checked a:link { background-color: #efe999; }
.cms-tree.jstree-apple .jstree-closed > ins { background-position: 0 0; }
.cms-tree.jstree-apple .jstree-open > ins { background-position: -20px 0; }
.tree-holder.jstree-apple, .cms-tree.jstree-apple { /* comment speech bubble - ccs3 only - source: http://nicolasgallagher.com/pure-css-speech-bubbles/demo/ */ }
.tree-holder.jstree-apple li.Root strong, .cms-tree.jstree-apple li.Root strong { font-weight: bold; padding-left: 1px; }
.tree-holder.jstree-apple li.Root > a .jstree-icon, .cms-tree.jstree-apple li.Root > a .jstree-icon { background-position: -56px -36px; }
.tree-holder.jstree-apple a, .tree-holder.jstree-apple a:link, .cms-tree.jstree-apple a, .cms-tree.jstree-apple a:link { color: #1556b2; padding: 3px 6px 3px 3px; border: none; display: inline-block; margin-right: 5px; }
.tree-holder.jstree-apple span.badge, .cms-tree.jstree-apple span.badge { clear: both; text-transform: uppercase; display: inline-block; padding: 0px 3px; font-size: 0.75em; line-height: 1em; margin-left: 3px; margin-right: 6px; margin-top: -1px; -webkit-border-radius: 2px 2px; -moz-border-radius: 2px / 2px; -o-border-radius: 2px / 2px; -ms-border-radius: 2px / 2px; -khtml-border-radius: 2px / 2px; border-radius: 2px / 2px; }
.tree-holder.jstree-apple span.badge.modified, .cms-tree.jstree-apple span.badge.modified { color: #7E7470; border: 1px solid #C9B800; background-color: #FFF0BC; }
.tree-holder.jstree-apple span.badge.addedtodraft, .cms-tree.jstree-apple span.badge.addedtodraft { color: #7E7470; border: 1px solid #C9B800; background-color: #FFF0BC; }
.tree-holder.jstree-apple span.badge.deletedonlive, .cms-tree.jstree-apple span.badge.deletedonlive { color: #636363; border: 1px solid #E49393; background-color: #F2DADB; }
.tree-holder.jstree-apple span.badge.removedfromdraft, .cms-tree.jstree-apple span.badge.removedfromdraft { color: #636363; border: 1px solid #E49393; background-color: #F2DADB; }
.tree-holder.jstree-apple span.badge.workflow-approval, .cms-tree.jstree-apple span.badge.workflow-approval { color: #56660C; border: 1px solid #7C8816; background-color: #DAE79A; }
.tree-holder.jstree-apple span.comment-count, .cms-tree.jstree-apple span.comment-count { clear: both; position: relative; text-transform: uppercase; display: inline-block; overflow: visible; padding: 0px 3px; font-size: 0.75em; line-height: 1em; margin-left: 3px; margin-right: 6px; -webkit-border-radius: 2px 2px; -moz-border-radius: 2px / 2px; -o-border-radius: 2px / 2px; -ms-border-radius: 2px / 2px; -khtml-border-radius: 2px / 2px; border-radius: 2px / 2px; color: #7E7470; border: 1px solid #C9B800; background-color: #FFF0BC; }
.tree-holder.jstree-apple span.comment-count:before, .cms-tree.jstree-apple span.comment-count:before { content: ""; position: absolute; bottom: -4px; /* value = - border-top-width - border-bottom-width */ left: 3px; /* controls horizontal position */ border-width: 4px 4px 0; border-style: solid; border-color: #C9B800 transparent; /* reduce the damage in FF3.0 */ display: block; width: 0; }
.tree-holder.jstree-apple span.comment-count:after, .cms-tree.jstree-apple span.comment-count:after { content: ""; position: absolute; bottom: -3px; /* value = - border-top-width - border-bottom-width */ left: 4px; /* value = (:before left) + (:before border-left) - (:after border-left) */ border-width: 3px 3px 0; border-style: solid; border-color: #FFF0BC transparent; /* reduce the damage in FF3.0 */ display: block; width: 0; }
.tree-holder.jstree-apple .jstree-hovered, .cms-tree.jstree-apple .jstree-hovered { text-shadow: none; text-decoration: none; }
.tree-holder.jstree-apple li, .cms-tree.jstree-apple li { padding: 0px; clear: left; }
.tree-holder.jstree-apple ins, .cms-tree.jstree-apple ins { background-color: transparent; background-image: url(../images/sitetree_ss_default_icons.png); }
.tree-holder.jstree-apple li.jstree-checked a, .tree-holder.jstree-apple li.jstree-checked a:link, .cms-tree.jstree-apple li.jstree-checked a, .cms-tree.jstree-apple li.jstree-checked a:link { background-color: #efe999; }
.tree-holder.jstree-apple .jstree-closed > ins, .cms-tree.jstree-apple .jstree-closed > ins { background-position: 0 0; }
.tree-holder.jstree-apple .jstree-open > ins, .cms-tree.jstree-apple .jstree-open > ins { background-position: -20px 0; }
.jstree-apple #record-0.jstree-open > ins { display: none; }
@ -571,7 +584,7 @@ li.class-ErrorPage > a .jstree-pageicon { background-position: 0 -112px; }
.cms-logo { border-bottom: 1px solid #03090c; height: 31px; overflow: hidden; padding: 0 0 0 4px; vertical-align: middle; font-size: 12px; }
.cms-logo .version { display: none; }
.cms-logo a { display: inline-block; height: 24px; width: 24px; float: left; margin-right: 8px; background: url("../images/logo_small.png") no-repeat; text-indent: -9999em; padding-right: 7px; border-right: 1px solid #19435c; }
.cms-logo span { font-weight: bold; font-size: 14px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; o-text-overflow: ellipsis; }
.cms-logo span { font-weight: bold; font-size: 14px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; o-text-overflow: ellipsis; padding-top: 1px; }
.cms-login-status { border-top: 1px solid #19435c; height: 24px; padding: 7px 4px 0 4px; overflow: hidden; line-height: 16px; font-size: 11px; }
.cms-login-status .logout-link { display: inline-block; height: 16px; width: 16px; float: left; margin: 0 8px 0 3px; background: url('../images/sprites-32x32-sa4e142f7f0.png') 0 -669px no-repeat; text-indent: -9999em; }
@ -588,7 +601,7 @@ li.class-ErrorPage > a .jstree-pageicon { background-position: 0 -112px; }
.cms-menu.collapsed.cms-panel .cms-panel-content { display: block; }
.cms-menu-list li { /* Style applied to the menu flyout only when the collapsed setting */ }
.cms-menu-list li a { display: block; height: 24px; line-height: 24px; font-size: 12px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; text-shadow: #bfcad2 1px 1px 0; color: #1f1f1f; padding: 7px 5px 7px 8px; background-color: #b0bec7; cursor: pointer; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #b0bec7), color-stop(100%, #8ca1ae)); background-image: -webkit-linear-gradient(#b0bec7, #8ca1ae); background-image: -moz-linear-gradient(#b0bec7, #8ca1ae); background-image: -o-linear-gradient(#b0bec7, #8ca1ae); background-image: -ms-linear-gradient(#b0bec7, #8ca1ae); background-image: linear-gradient(#b0bec7, #8ca1ae); border-top: 1px solid #ced7dc; border-bottom: 1px solid #748d9d; }
.cms-menu-list li a { display: block; height: 24px; line-height: 24px; font-size: 12px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; text-shadow: #bfcad2 1px 1px 0; color: #1f1f1f; padding: 7px 5px 7px 8px; background-color: #8ca1ae; cursor: pointer; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #b0bec7), color-stop(100%, #8ca1ae)); background-image: -webkit-linear-gradient(#b0bec7, #8ca1ae); background-image: -moz-linear-gradient(#b0bec7, #8ca1ae); background-image: -o-linear-gradient(#b0bec7, #8ca1ae); background-image: -ms-linear-gradient(#b0bec7, #8ca1ae); background-image: linear-gradient(#b0bec7, #8ca1ae); border-top: 1px solid #ced7dc; border-bottom: 1px solid #748d9d; }
.cms-menu-list li a:hover { text-decoration: none; background-color: #b6c3cb; border-bottom: 1px solid #8399a7; color: #2c2c2c; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #bfcad2), color-stop(100%, #b0bec7)); background-image: -webkit-linear-gradient(#bfcad2, #b0bec7); background-image: -moz-linear-gradient(#bfcad2, #b0bec7); background-image: -o-linear-gradient(#bfcad2, #b0bec7); background-image: -ms-linear-gradient(#bfcad2, #b0bec7); background-image: linear-gradient(#bfcad2, #b0bec7); }
.cms-menu-list li a:focus, .cms-menu-list li a:active { border-top: 1px solid #a1b2bc; text-decoration: none; background-color: #a1b2bc; color: #393939; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #92a5b2), color-stop(100%, #a1b2bc)); background-image: -webkit-linear-gradient(#92a5b2, #a1b2bc); background-image: -moz-linear-gradient(#92a5b2, #a1b2bc); background-image: -o-linear-gradient(#92a5b2, #a1b2bc); background-image: -ms-linear-gradient(#92a5b2, #a1b2bc); background-image: linear-gradient(#92a5b2, #a1b2bc); }
.cms-menu-list li a .icon { display: inline-block; float: left; margin: 4px 10px 0 4px; filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=70); opacity: 0.7; }
@ -596,7 +609,6 @@ li.class-ErrorPage > a .jstree-pageicon { background-position: 0 -112px; }
.cms-menu-list li a .toggle-children { display: inline-block; float: right; width: 20px; height: 100%; cursor: pointer; }
.cms-menu-list li a .toggle-children .toggle-children-icon { display: inline-block; width: 8px; height: 8px; background: url('../images/sprites-32x32-sa4e142f7f0.png') 0 -695px no-repeat; vertical-align: middle; }
.cms-menu-list li a .toggle-children.opened .toggle-children-icon { background: url('../images/sprites-32x32-sa4e142f7f0.png') 0 -711px no-repeat; }
.cms-menu-list li ul { display: none; }
.cms-menu-list li.current a { color: white; text-shadow: #1e5270 0 -1px 0; border-top: 1px solid #55a4d2; border-bottom: 1px solid #1e5270; background-color: #338dc1; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #338dc1), color-stop(100%, #287099)); background-image: -webkit-linear-gradient(#338dc1, #287099); background-image: -moz-linear-gradient(#338dc1, #287099); background-image: -o-linear-gradient(#338dc1, #287099); background-image: -ms-linear-gradient(#338dc1, #287099); background-image: linear-gradient(#338dc1, #287099); }
.cms-menu-list li.current a .toggle-children .toggle-children-icon { background: url('../images/sprites-32x32-sa4e142f7f0.png') 0 -727px no-repeat; }
.cms-menu-list li.current a .toggle-children.opened .toggle-children-icon { background: url('../images/sprites-32x32-sa4e142f7f0.png') 0 -743px no-repeat; }
@ -607,6 +619,11 @@ li.class-ErrorPage > a .jstree-pageicon { background-position: 0 -112px; }
.cms-menu-list li.current li a:focus { background: #236184; border-top: 1px solid #1e5270; color: white; }
.cms-menu-list li.current li.current a { font-weight: bold; color: white; }
.cms-menu-list li.current li.first a { border-top: none; }
.cms-menu-list li ul { display: none; }
.cms-menu-list li ul #Menu-CMSPagesController a { background-image: none; font-size: 11px; padding: 0 10px 0 40px; height: 32px; line-height: 32px; }
.cms-menu-list li ul #Menu-CMSPageAddController a { background-image: none; font-size: 11px; padding: 0 10px 0 40px; height: 32px; line-height: 32px; }
.cms-menu-list li ul #Menu-AssetAdmin a { background-image: none; font-size: 11px; padding: 0 10px 0 40px; height: 32px; line-height: 32px; }
.cms-menu-list li ul #Menu-CMSFileAddController a { background-image: none; font-size: 11px; padding: 0 10px 0 40px; height: 32px; line-height: 32px; }
.cms-menu-list li ul.collapsed-flyout { display: block; }
.cms-menu-list li ul.collapsed-flyout li a { font-size: 11px; padding: 0 10px 0 40px; height: 32px; line-height: 32px; }
.cms-menu-list li ul.collapsed-flyout li a.current, .cms-menu-list li ul.collapsed-flyout li a:hover { font-weight: bold; }
@ -631,4 +648,4 @@ li.class-ErrorPage > a .jstree-pageicon { background-position: 0 -112px; }
.ModelAdmin .cms-content-tools #SearchForm_holder div.tab form .Actions button.ss-ui-action-minor { display: none; }
.SecurityAdmin .cms-edit-form .cms-content-header h2 { display: none; }
.SecurityAdmin .permissioncheckboxset .optionset li { float: none; width: auto; }
.SecurityAdmin .permissioncheckboxset .optionset li, .SecurityAdmin .permissioncheckboxsetfield_readonly .optionset li { float: none; width: auto; }

BIN
admin/images/arrows.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
admin/images/spinner.psd Normal file

Binary file not shown.

View File

@ -194,7 +194,7 @@
var form = this.replaceForm(oldForm, data);
if(typeof(Behaviour) != 'undefined') Behaviour.apply(); // refreshes ComplexTableField
this.trigger('reloadeditform', {form: form, origData: origData, xmlhttp: xmlhttp});
}

View File

@ -154,7 +154,7 @@
});
});
$('.cms-edit-form').bind('reloadeditform', function(e, data) {
this.parents('.cms-content:first').bind('reloadeditform', function(e, data) {
self._onLoadNewPage(e, data);
});
},
@ -192,7 +192,7 @@
*/
_onLoadNewPage: function(e, eventData) {
var self = this;
// finds a certain value in an array generated by jQuery.serializeArray()
var findInSerializedArray = function(arr, name) {
for(var i=0; i<arr.length; i++) {
@ -201,15 +201,16 @@
return false;
};
var id = $(e.target.ID).val();
var handledform = $(e.target).children('.cms-edit-form:first')[0];
var id = $(handledform.ID).val();
// check if a form with a valid ID exists
if(id) {
var parentID = $(e.target.ParentID).val(),
var parentID = $(handledform.ParentID).val(),
parentNode = this.find('li[data-id='+parentID+']');
node = this.find('li[data-id='+id+']'),
title = $((e.target.TreeTitle) ? e.target.TreeTitle : e.target.Title).val(),
className = $(e.target.ClassName).val();
title = $((handledform.TreeTitle) ? handledform.TreeTitle : handledform.Title).val(),
className = $(handledform.ClassName).val();
// set title (either from TreeTitle or from Title fields)
// Treetitle has special HTML formatting to denote the status changes.

View File

@ -242,6 +242,7 @@ jQuery.noConflict();
},
error: function(xhr, status, e) {
contentEl.removeClass('loading');
errorMessage(e);
}
});
@ -273,7 +274,7 @@ jQuery.noConflict();
/**
* Trigger dialogs with iframe based on the links href attribute (see ssui-core.js).
*/
$('.cms-container .ss-ui-dialog-link').entwine({
$('.cms .ss-ui-dialog-link').entwine({
UUID: null,
onmatch: function() {
this._super();
@ -335,7 +336,7 @@ jQuery.noConflict();
* the DOM element on creation, rather than onclick - which allows us to decorate
* the field with a calendar icon
*/
$('.cms-container .field.date input.text').entwine({
$('.cms .field.date input.text').entwine({
onmatch: function() {
var holder = $(this).parents('.field.date:first'), config = holder.data();
if(!config.showcalendar) return;
@ -362,9 +363,9 @@ jQuery.noConflict();
* we can fix the height cropping.
*/
$('.cms-container .field.dropdown').entwine({
$('.cms .field.dropdown, .cms .field.checkboxset').entwine({
onmatch: function() {
$(this).find("select:not(.no-chzn)").chosen();
$(this).find("select:not(.no-chzn)").data('placeholder', ' ').chosen();
$(this).addClass("has-chzn");
this._super();
@ -380,139 +381,54 @@ jQuery.noConflict();
});
});
$('.cms-filter-form').entwine({
GridField: null,
/**
* Overload the default GridField behaviour (open a new URL in the browser)
* with the CMS-specific ajax loading.
*/
$('.cms .ss-gridfield').entwine({
showDetailView: function(url) {
// Include any GET parameters from the current URL, as the view state might depend on it.
// For example, a list prefiltered through external search criteria might be passed to GridField.
if(window.location.search) url += window.location.search;
$('.cms-container').entwine('ss').loadPanel(url);
}
});
/**
* Function onmatch
*
* Try to find the related gridfield by looking up the data-gridfield attribute on this
* filter form
*/
onmatch: function() {
var gridfieldName = this.attr('data-gridfield');
this.setGridField($('.grid[data-name='+gridfieldName+']'));
var self = this;
this.getGridField().bind('reload', function(e, gridfield){
self.setFilterValues($(gridfield).getState());
/**
* Generic search form in the CMS, often hooked up to a GridField results display.
*/
$('.cms-search-form').entwine({
onsubmit: function() {
// Remove empty elements and make the URL prettier
var nonEmptyInputs = this.find(':input:not(:submit)').filter(function() {
// Use fieldValue() from jQuery.form plugin rather than jQuery.val(),
// as it handles checkbox values more consistently
var vals = $.grep($(this).fieldValue(), function(val) { return (val);});
return (vals.length);
});
},
/**
* Function: onsubmit
*
* Parameters:
* (Event) e
*/
onsubmit: function(e) {
this.changeState(jQuery(this).find(':submit:first'));
var url = this.attr('action');
if(nonEmptyInputs.length) url += '?' + nonEmptyInputs.serialize();
this.closest('.cms-container').entwine('ss').loadPanel(url);
return false;
},
/**
* Function: setFilterValues
*
* Parameters:
* (JSON) state
*
*/
setFilterValues: function(state){
var filterValues = state.GridFieldFilter.Columns;
if(jQuery.isEmptyObject(filterValues)){
this.resetFilterForm();
return;
}
this.filterFields().each(function(idx, element) {
if(typeof filterValues[element.name] !== "undefined") {
$(element).val(filterValues[element.name]);
}
});
},
/**
* Function: onreset
*
* Parameters:
* (Event) e
* Resets are processed on the serverside, so need to trigger a submit.
*/
onreset: function(e) {
if(this.resetFilterForm()) {
this.changeState(jQuery(this));
}
return false;
},
/**
* Function resetFilterForm
*
**/
resetFilterForm: function() {
var needUpdate = false;
this.filterFields().each(function(idx, element) {
if($(element).val()) {
needUpdate = true;
$(element).val('');
}
if($(element).hasClass('chzn-done')){
$(element).trigger("liszt:updated");
}
});
return needUpdate;
},
/**
* Function: changeState
*
* Change the state of the gridfield, reloads it's and set loading classes on elements
*
* Parameters:
* (Element) element - the element that will get a loading class added / removed
*
*/
changeState: function(element) {
element.addClass('loading');
this.getGridField().setState('GridFieldFilter', {'Columns': this.filterValues()});
this.getGridField().reload(null, function(){
element.removeClass('loading');
});
},
/**
* Function filterFields
* Get all fields that contains filter values
*
*/
filterFields: function() {
return this.find(':input').not(".action, .hidden");
},
/**
* Function: filterValues
*
* Returns an key-value array for the filter values set in the filter form
*
*/
filterValues: function() {
var filterColumns = {};
this.filterFields().each(function(idx,elm){
filterColumns[$(elm).attr('name')] = $(elm).val();
});
return filterColumns;
this.clearForm();
this.submit();
}
});
}(jQuery));
// Backwards compatibility
var statusMessage = function(text, type) {
jQuery.noticeAdd({text: text, type: type});
};
var errorMessage = function(text) {
jQuery.noticeAdd({text: text, type: 'error'});
};
returnFalse = function() {
return false;
};

View File

@ -4,7 +4,7 @@
}
// Same rules in .member-profile-form
.permissioncheckboxset {
.permissioncheckboxset, .permissioncheckboxsetfield_readonly {
.optionset {
li {
float: none;

View File

@ -58,6 +58,7 @@
font-weight: bold;
font-size: 14px;
@include hide-text-overflow();
padding-top:1px;
}
}
@ -142,7 +143,7 @@
text-shadow: lighten($color-base, 5%) 1px 1px 0;
color: $color-text-dark;
padding: ($grid-y - 1) 5px ($grid-y - 1) 8px;
background-color: $color-base;
background-color: darken($color-base, 12%);
cursor: pointer;
@include background-image(linear-gradient(
@ -212,10 +213,6 @@
}
}
}
ul {
display: none;
}
&.current { //need to apply current stlye to flyout also (at least line height)
a {
@ -249,7 +246,6 @@
li {
background-color: darken($color-menu-button, 10%);
a {
font-size: $font-base-size - 1;
padding: 0 10px 0 40px;
@ -286,6 +282,46 @@
}
}
ul {
display: none;
#Menu-CMSPagesController {
a {
background-image:none;
font-size: 11px;
padding: 0 10px 0 40px;
height: 32px;
line-height: 32px;
}
}
#Menu-CMSPageAddController {
a {
background-image:none;
font-size: 11px;
padding: 0 10px 0 40px;
height: 32px;
line-height: 32px;
}
}
#Menu-AssetAdmin {
a {
background-image:none;
font-size: 11px;
padding: 0 10px 0 40px;
height: 32px;
line-height: 32px;
}
}
#Menu-CMSFileAddController {
a {
background-image:none;
font-size: 11px;
padding: 0 10px 0 40px;
height: 32px;
line-height: 32px;
}
}
}
/* Style applied to the menu flyout only when the collapsed setting */
ul.collapsed-flyout {
display: block;

View File

@ -18,16 +18,9 @@
* Core Styles.
* ---------------------------------------------------- */
html,body {
html,body {
width: 100%;
height: 100%;
@include global-reset;
font-size: $font-base-size;
line-height: $grid-y * 2;
font-family: $font-family;
color: $color-text;
}
body.cms {
@ -102,9 +95,14 @@ body.cms {
color: $color-text-blue-link;
}
.backlink {
float:left;
margin-top:$grid-x - 1;
}
h2 {
float: left;
padding: $grid-y $grid-x 0 0;
padding: $grid-y $grid-x 0 $grid-x;
font-size: $font-base-size + 2;
line-height: $grid-x * 3;
font-weight: bold;
@ -122,9 +120,83 @@ body.cms {
.cms-content-header-tabs {
position:fixed;
right:40px;
.ui-tabs-nav {
li {
a {
font-weight: bold;
line-height: $grid-y * 2;
padding: ($grid-y * 2 - 4) ($grid-x * 2 + 4) $grid-y + 3;
text-indent:-9999em;
&.content-treeview {
background:url(../images/content-header-tabs-sprite.png) no-repeat 2px 0px;
}
&.content-galleryview {
background:url(../images/content-header-tabs-sprite.png) no-repeat -87px 0px;
}
&.content-listview {
background:url(../images/content-header-tabs-sprite.png) no-repeat -38px 0px;
}
}
}
.ui-state-default,
.ui-widget-content .ui-state-default,
.ui-widget-header .ui-state-default {
border: {
top:none;
}
}
.ui-state-active,
.ui-widget-content .ui-state-active,
.ui-widget-header .ui-state-active {
border: {
top:none;
}
a {
&.content-treeview {
background:url(../images/content-header-tabs-sprite.png) no-repeat 2px -40px;
}
&.content-galleryview {
background:url(../images/content-header-tabs-sprite.png) no-repeat -87px -40px;
}
&.content-listview {
background:url(../images/content-header-tabs-sprite.png) no-repeat -38px -40px;
}
}
}
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr {
border-radius:0;
}
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl {
border-radius:0;
}
}
}
}
.cms-edit-form {
.cms-content-header-tabs {
.ui-tabs-nav {
li {
a {
text-indent:0;
}
}
.ui-state-default,
.ui-widget-content .ui-state-default,
.ui-widget-header .ui-state-default {
a {
color:$color-text-dark;
}
}
}
}
}
/** --------------------------------------------
* Tabs
* -------------------------------------------- */
@ -135,16 +207,6 @@ body.cms {
font-weight: bold;
line-height: $grid-y * 2;
padding: ($grid-y * 2 - 4) ($grid-x * 2 + 4) $grid-y + 3;
&.content-treeview {
background:url(../images/content-header-tabs-sprite.png) no-repeat 2px 0px;
}
&.content-galleryview {
background:url(../images/content-header-tabs-sprite.png) no-repeat -87px 0px;
}
&.content-listview {
background:url(../images/content-header-tabs-sprite.png) no-repeat -38px 0px;
}
}
}
@ -159,7 +221,6 @@ body.cms {
border: {
right-color: darken($color-tab, 20%);
left-color: $color-tab;
top:none;
bottom:none;
}
@ -173,7 +234,6 @@ body.cms {
border: {
right-color: darken($color-tab, 20%);
left-color: darken($color-tab, 20%);
top:none;
}
margin-right:-1px;
margin-left:-1px;
@ -181,26 +241,8 @@ body.cms {
a {
border-bottom:none;
&.content-treeview {
background:url(../images/content-header-tabs-sprite.png) no-repeat 2px -40px;
}
&.content-galleryview {
background:url(../images/content-header-tabs-sprite.png) no-repeat -87px -40px;
}
&.content-listview {
background:url(../images/content-header-tabs-sprite.png) no-repeat -38px -40px;
}
}
}
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr {
border-radius:0;
}
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl {
border-radius:0;
}
}
/** -------------------------------------------------------
@ -429,15 +471,15 @@ body.cms {
@include doubleborder(bottom, $color-light-separator, lighten($color-light-separator, 50%));
@include legacy-pie-clearfix();
& > * {
float: right;
}
.cms-tree-view-modes * {
display: inline-block;
label {
color:$color-text-blue-link;
.cms-tree-view-modes {
float:right;
padding-top:$grid-y - 3;
* {
display: inline-block;
label {
color:$color-text-blue-link;
}
}
}
@ -502,7 +544,6 @@ body.cms {
position: relative;
.cms-panel-header {
padding: 0;
margin: 0 0 $grid-y - 1;
line-height: $grid-y * 3;
@ -513,12 +554,11 @@ body.cms {
width: ($grid-x * 22);
padding: $grid-y $grid-x;
overflow: auto;
height:100%;
}
.cms-content-header {
background-color: darken($color-widget-bg, 40%);
border-bottom: 2px solid darken($color-widget-bg, 50%);
@include background-image(
linear-gradient(darken($color-widget-bg, 20%), darken($color-widget-bg, 40%))
);
@ -814,6 +854,19 @@ form.member-profile-form {
}
}
}
.ui-tabs-nav {
li {
margin:0 0 -1px 0;
}
}
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr {
border-radius:0;
}
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl {
border-radius:0;
}
}
.cms {
@ -896,6 +949,27 @@ form.member-profile-form {
width: 100%;
}
&#cms-content-tools-CMSPageEditController {
.cms-panel-content-collapsed {
width: 40px;
display: none; // Avoids FOUC
h2, h3 {
border-bottom: 0;
margin-left: $grid-y;
@include transform-origin(bottom, right);
@include rotate(270deg);
}
.cms-panel-header {
width: 600px;
position:relative;
top:24px;
right:577px;
text-align:right;
}
}
}
.cms-panel-content-collapsed {
width: 40px;
display: none; // Avoids FOUC
@ -903,8 +977,14 @@ form.member-profile-form {
h2, h3 {
border-bottom: 0;
margin-left: $grid-y;
@include transform-origin(bottom, left);
@include rotate(90deg);
@include transform-origin(bottom, right);
@include rotate(270deg);
}
.cms-panel-header {
width: 600px;
position:relative;
right:577px;
text-align:right;
}
}
@ -1156,44 +1236,63 @@ body.cms-dialog {
* Item Edit Form
* -------------------------------------------- */
#Form_ItemEditForm {
.field {
width:100%;
.fieldgroup {
height:230px;
float:left;
.fieldgroup-field.first {
position:relative;
margin-left:0px;
}
.fieldgroup-field {
clear:both;
width:500px;
margin-left:420px;
img {
@include border-radius (8px);
border: {
width:3px;
style:dashed;
color:$color-menu-border;
}
position:absolute;
top:8px;
}
label {
font-weight:bold;
float:left;
padding-top:8px;
line-height:16px;
text-shadow: $color-text-light 1px 1px 0;
}
span {
float:left;
padding-left:8px;
font-style:italic;
color:lighten($color-text, 20%);
}
}
.cms-file-info {
overflow: auto;
// Emulate .field bottom border styling without applying .field class,
// as it messes up the nested .field element styling (blocklevel labels)
border-bottom: 1px solid $color-shadow-light;
@include box-shadow(0 1px 0 lighten($color-shadow-light, 95%));
margin-bottom: $grid-x;
// Preview might not always be available
.cms-file-info-preview {
float: left;
width: $grid-x * 22; // Same as ".field label"
margin-right: $grid-x;
img {
max-width: $grid-x * 22; // Same as ".field label"
}
}
}
.cms-file-info-data {
float: left;
.field {
// Unsetting styles from .field, make it more compact visually
margin-bottom: 0;
padding-bottom: $grid-x;
border: none;
box-shadow: none;
label, span {
padding: 0;
}
}
}
}
form.small {
.cms-file-info-preview {
width: $grid-x*14;
img {
max-width: $grid-x*14;
}
}
.cms-file-info-data {
// Ensure it fits beside the image preview
max-width: 350px;
// Reduced label widths to fit everything in smaller space
.field {
padding-bottom: 0;
label {
width: $grid-x*14;
}
.middleColumn {
margin-left: $grid-x*15;
}
}
}
}

View File

@ -6,7 +6,7 @@
* but we need it earlier in order to correctly display the uninitialized tree.
*/
.cms {
.cms, .TreeDropdownField .treedropdownfield-panel {
.jstree {
ul {
display: block;
@ -397,7 +397,7 @@
}
}
.cms-tree.jstree-apple {
.tree-holder.jstree-apple, .cms-tree.jstree-apple {
& li.Root {
& strong {

View File

@ -3,6 +3,12 @@
*
* Contains the basic typography related styles for the admin interface.
*/
body, html {
font-size: $font-base-size;
line-height: $grid-y * 2;
font-family: $font-family;
color: $color-text;
}
.cms {
h2, h3, h4, h5 {

View File

@ -55,10 +55,9 @@
background-color: darken($color-widget-bg, 20%);
padding: 8px 8px 6px 8px;
border-bottom: 2px solid darken($color-widget-bg, 35%);
@include linear-gradient(color-stops(
darken($color-widget-bg, 5%),
darken($color-widget-bg, 30%)
));
@include background-image(
linear-gradient(darken($color-widget-bg, 5%), darken($color-widget-bg, 30%))
);
border-bottom: 3px solid darken($color-widget-bg, 50%);
padding: 8px;
@include border-radius(0);

View File

@ -51,4 +51,18 @@ html {
// fix jstree themeroller plugin bug: tree disappear in IE7
.jstree li a .ui-icon {
text-indent: 0px !important;
}
.cms {
table.ss-gridfield-table {
tbody {
td {
button {
span.ui-button-text {
zoom:1;
}
}
}
}
}
}

View File

@ -3,6 +3,13 @@
<% end_if %>
<div class="cms-content-header north">
<div>
<% if Backlink %>
<a class="backlink ss-ui-button cms-panel-link" data-icon="back" href="$Backlink">
<% _t('Back', 'Back') %>
</a>
<% end_if %>
<h2 id="page-title-heading">
<% control Controller %>
<% include CMSBreadcrumbs %>
@ -22,12 +29,6 @@
<!-- <div class="cms-content-search">...</div> -->
<% if Backlink %>
<a class="backlink ss-ui-button cms-panel-link" data-icon="back" href="$Backlink">
<% _t('Back', 'Back') %>
</a>
<% end_if %>
</div>
</div>

View File

@ -12,7 +12,7 @@
<% control CurrentMember %>
<span>
<% _t('Hello','Hi') %>
<a href="{$AbsoluteBaseURL}admin/settings/myprofile" class="profile-link ss-ui-dialog-link">
<a href="{$AbsoluteBaseURL}admin/myprofile" class="profile-link ss-ui-dialog-link">
<% if FirstName && Surname %>$FirstName $Surname<% else_if FirstName %>$FirstName<% else %>$Email<% end_if %>
</a>
</span>

View File

@ -30,7 +30,7 @@
.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-cancel { position: absolute; top: 7px; right: 7px; }
.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-cancel button { display: block; overflow: hidden; text-indent: -9999px; padding: 0; margin: 0; border: 0; width: 16px; height: 16px; cursor: pointer; -moz-box-shadow: none; -webkit-box-shadow: none; -o-box-shadow: none; box-shadow: none; }
.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-editform { /* don't use display none, for it will break jQuery('iframe').contents().height() */ height: 0; overflow: hidden; clear: both; }
.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-editform iframe { width: 100%; }
.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-editform iframe { margin: 16px; width: 100%; }
.ss-assetuploadfield .ss-uploadfield-addfile .ss-uploadfield-item-info { float: left; margin: 19px 0 0; }
.ss-assetuploadfield .ss-uploadfield-addfile .ss-uploadfield-fromcomputer { position: relative; overflow: hidden; display: block; margin: 0 10px 0 0; }
.ss-assetuploadfield .ss-uploadfield-addfile .ss-uploadfield-item-uploador { float: left; font-weight: bold; font-size: 22px; padding: 0 20px; line-height: 70px; display: none; }

View File

@ -7,20 +7,24 @@
.cms table.ss-gridfield-table tbody { background: #FFF; }
.cms table.ss-gridfield-table tbody td { /* Emulate a link by default */ }
.cms table.ss-gridfield-table tbody td button { border: none; background: none; margin: 0 0 0 2px; padding: 0; width: auto; text-shadow: none; }
.cms table.ss-gridfield-table tbody td button.ui-state-hover { background: none; border: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; }
.cms table.ss-gridfield-table tbody td button span.ui-button-text { text-indent: -9999em; background: url(../images/icons/decline.png) no-repeat 0 2px; padding: 0; width: 20px; height: 20px; }
.cms table.ss-gridfield-table tbody td a.edit-link { display: inline-block; height: 20px; width: 20px; text-indent: -9999em; background: url(../images/icons/document--pencil.png) no-repeat 0 1px; }
.cms table.ss-gridfield-table tfoot { color: #1d2224; }
.cms table.ss-gridfield-table tfoot tr td { background: #95a5ab; padding: .7em; border-bottom: 1px solid rgba(0, 0, 0, 0.1); }
.cms table.ss-gridfield-table tr.title { -moz-border-radius-topleft: 7px; -webkit-border-top-left-radius: 7px; -o-border-top-left-radius: 7px; -ms-border-top-left-radius: 7px; -khtml-border-top-left-radius: 7px; border-top-left-radius: 7px; -moz-border-radius-topright: 7px; -webkit-border-top-right-radius: 7px; -o-border-top-right-radius: 7px; -ms-border-top-right-radius: 7px; -khtml-border-top-right-radius: 7px; border-top-right-radius: 7px; }
.cms table.ss-gridfield-table tr.title th { position: relative; background: #7f9198; border-top: 1px solid rgba(0, 0, 0, 0.1); padding: 5px; min-height: 40px; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #b1c0c5), color-stop(100%, #7f9198)); background-image: -webkit-linear-gradient(#b1c0c5, #7f9198); background-image: -moz-linear-gradient(#b1c0c5, #7f9198); background-image: -o-linear-gradient(#b1c0c5, #7f9198); background-image: -ms-linear-gradient(#b1c0c5, #7f9198); background-image: linear-gradient(#b1c0c5, #7f9198); -moz-border-radius-topleft: 7px; -webkit-border-top-left-radius: 7px; -o-border-top-left-radius: 7px; -ms-border-top-left-radius: 7px; -khtml-border-top-left-radius: 7px; border-top-left-radius: 7px; -moz-border-radius-topright: 7px; -webkit-border-top-right-radius: 7px; -o-border-top-right-radius: 7px; -ms-border-top-right-radius: 7px; -khtml-border-top-right-radius: 7px; border-top-right-radius: 7px; text-shadow: rgba(0, 0, 0, 0.3) 0px -1px 0; }
.cms table.ss-gridfield-table tr.title th h2 { padding: 0px; font-size: 16px; color: #fff; margin: 0; display: inline; }
.cms table.ss-gridfield-table tr.title th .new { font-size: 14px; border-color: rgba(0, 0, 0, 0.1); float: right; }
.cms table.ss-gridfield-table tr.title th h2 { padding: 0px; font-size: 16.8px; color: #fff; margin: 3px 8px 0; display: inline-block; }
.cms table.ss-gridfield-table tr.title th .new { font-size: 14.4px; border-color: rgba(0, 0, 0, 0.1); float: right; }
.cms table.ss-gridfield-table tr.sortable-header { background: #bac8ce; }
.cms table.ss-gridfield-table tr.sortable-header th { padding: 0px; }
.cms table.ss-gridfield-table tr:hover { background: #FFFAD6 !important; }
.cms table.ss-gridfield-table tr:first-child { background: transparent; }
.cms table.ss-gridfield-table tr.ss-gridfield-even { background: #f0f4f7; }
.cms table.ss-gridfield-table tr.ss-gridfield-even.ss-gridfield-last { border-bottom: none; }
.cms table.ss-gridfield-table tr.even { background: #f0f4f7; }
.cms table.ss-gridfield-table tr th { font-weight: bold; font-size: 12px; color: #FFF; padding: 5px; border-right: 1px solid rgba(0, 0, 0, 0.1); }
.cms table.ss-gridfield-table tr th div.fieldgroup, .cms table.ss-gridfield-table tr th div.fieldgroup-field { width: auto; }
.cms table.ss-gridfield-table tr th div.fieldgroup, .cms table.ss-gridfield-table tr th div.fieldgroup-field { width: 100%; position: relative; }
.cms table.ss-gridfield-table tr th div.fieldgroup { min-width: 200px; padding-right: 0; }
.cms table.ss-gridfield-table tr th.extra, .cms table.ss-gridfield-table tr th.action { padding: 0; cursor: default; }
.cms table.ss-gridfield-table tr th.extra button.ss-ui-button, .cms table.ss-gridfield-table tr th.extra button:hover.ss-ui-button, .cms table.ss-gridfield-table tr th.action button.ss-ui-button, .cms table.ss-gridfield-table tr th.action button:hover.ss-ui-button { margin-left: .9em; color: #222; }
@ -28,16 +32,27 @@
.cms table.ss-gridfield-table tr th.main span { text-shadow: rgba(0, 0, 0, 0.3) 0px -1px 0; }
.cms table.ss-gridfield-table tr th.extra { background: #bac8ce; padding: 5px; border-top: rgba(0, 0, 0, 0.3); }
.cms table.ss-gridfield-table tr th.extra span { width: auto; display: inline; position: static; }
.cms table.ss-gridfield-table tr th.extra span input { height: 28px; }
.cms table.ss-gridfield-table tr th.extra button.ss-ui-button { padding: .3em; line-height: 1; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; position: relative; border-bottom-width: 0; -webkit-border-radius: 2px 2px; -moz-border-radius: 2px / 2px; -o-border-radius: 2px / 2px; -ms-border-radius: 2px / 2px; -khtml-border-radius: 2px / 2px; border-radius: 2px / 2px; }
.cms table.ss-gridfield-table tr th.action { border-right: 0; }
.cms table.ss-gridfield-table tr th.first { -moz-border-radius-topleft: 7px; -webkit-border-top-left-radius: 7px; -o-border-top-left-radius: 7px; -ms-border-top-left-radius: 7px; -khtml-border-top-left-radius: 7px; border-top-left-radius: 7px; }
.cms table.ss-gridfield-table tr th.last { -moz-border-radius-topright: 7px; -webkit-border-top-right-radius: 7px; -o-border-top-right-radius: 7px; -ms-border-top-right-radius: 7px; -khtml-border-top-right-radius: 7px; border-top-right-radius: 7px; }
.cms table.ss-gridfield-table tr th button:hover { color: #ccc !important; /* Not sure why IE think it needs this */ }
.cms table.ss-gridfield-table tr th button.ss-gridfield-sort:hover { color: #fff !important; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; }
.cms table.ss-gridfield-table tr th button.ss-gridfield-sort { background: transparent url(../images/arrows-01.png) no-repeat right 2px; border: none; width: 100%; text-align: left; padding: 4px 0; text-shadow: rgba(0, 0, 0, 0.3) 0px -1px 0; color: #fff; -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; -ms-border-radius: 0; -khtml-border-radius: 0; border-radius: 0; }
.cms table.ss-gridfield-table tr th button.ss-gridfield-sort { background: transparent url(../images/arrows.png) no-repeat right 6px; border: none; width: 100%; text-align: left; padding: 4px 0; text-shadow: rgba(0, 0, 0, 0.3) 0px -1px 0; color: #fff; -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; -ms-border-radius: 0; -khtml-border-radius: 0; border-radius: 0; }
.cms table.ss-gridfield-table tr th button.ss-gridfield-sort:hover { background-position: right -34px; }
.cms table.ss-gridfield-table tr th button.ss-gridfield-sort.ss-gridfield-sorted-desc { background-position: right -72px; }
.cms table.ss-gridfield-table tr th button.ss-gridfield-sort.ss-gridfield-sorted-asc { background-position: right -116px; }
.cms table.ss-gridfield-table tr th button.ss-gridfield-button-filter.ss-ui-button { position: absolute; right: 7px; top: -28px; display: block; text-indent: -9999em; width: 30px; height: 28px; border-top-left-radius: 0px; border-bottom-left-radius: 0px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-width: 1px; border-color: #9a9a9a; background: url(../images/icons/filter-icons.png) no-repeat -40px 6px, -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(100%, #d9d9d9)); background: url(../images/icons/filter-icons.png) no-repeat -40px 6px, -webkit-linear-gradient(#ffffff, #d9d9d9); background: url(../images/icons/filter-icons.png) no-repeat -40px 6px, -moz-linear-gradient(#ffffff, #d9d9d9); background: url(../images/icons/filter-icons.png) no-repeat -40px 6px, -o-linear-gradient(#ffffff, #d9d9d9); background: url(../images/icons/filter-icons.png) no-repeat -40px 6px, -ms-linear-gradient(#ffffff, #d9d9d9); background: url(../images/icons/filter-icons.png) no-repeat -40px 6px, linear-gradient(#ffffff, #d9d9d9); }
.cms table.ss-gridfield-table tr th button.ss-gridfield-button-filter.ss-ui-button:hover { background: url(../images/icons/filter-icons.png) no-repeat -16px 6px, -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #4199cd), color-stop(100%, #2e7ead)); background: url(../images/icons/filter-icons.png) no-repeat -16px 6px, -webkit-linear-gradient(#4199cd, #2e7ead); background: url(../images/icons/filter-icons.png) no-repeat -16px 6px, -moz-linear-gradient(#4199cd, #2e7ead); background: url(../images/icons/filter-icons.png) no-repeat -16px 6px, -o-linear-gradient(#4199cd, #2e7ead); background: url(../images/icons/filter-icons.png) no-repeat -16px 6px, -ms-linear-gradient(#4199cd, #2e7ead); background: url(../images/icons/filter-icons.png) no-repeat -16px 6px, linear-gradient(#4199cd, #2e7ead); }
.cms table.ss-gridfield-table tr th button.ss-gridfield-button-filter.ss-ui-button:active { background: url(../images/icons/filter-icons.png) no-repeat -16px -17px, -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #4199cd), color-stop(100%, #2e7ead)); background: url(../images/icons/filter-icons.png) no-repeat -16px -17px, -webkit-linear-gradient(#4199cd, #2e7ead); background: url(../images/icons/filter-icons.png) no-repeat -16px -17px, -moz-linear-gradient(#4199cd, #2e7ead); background: url(../images/icons/filter-icons.png) no-repeat -16px -17px, -o-linear-gradient(#4199cd, #2e7ead); background: url(../images/icons/filter-icons.png) no-repeat -16px -17px, -ms-linear-gradient(#4199cd, #2e7ead); background: url(../images/icons/filter-icons.png) no-repeat -16px -17px, linear-gradient(#4199cd, #2e7ead); -moz-box-shadow: inset 0 1px 3px #17181a, 0 1px 0 rgba(255, 255, 255, 0.6); -webkit-box-shadow: inset 0 1px 3px #17181a, 0 1px 0 rgba(255, 255, 255, 0.6); -o-box-shadow: inset 0 1px 3px #17181a, 0 1px 0 rgba(255, 255, 255, 0.6); box-shadow: inset 0 1px 3px #17181a, 0 1px 0 rgba(255, 255, 255, 0.6); }
.cms table.ss-gridfield-table tr th button.ss-gridfield-button-reset.ss-ui-button { position: absolute; right: 36px; top: -28px; display: block; text-indent: -9999em; width: 30px; height: 28px; float: right; border-radius: 0px; border-bottom-width: 1px; border-color: #9a9a9a; background: url(../images/icons/filter-icons.png) no-repeat 8px 5px, -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(100%, #d9d9d9)); background: url(../images/icons/filter-icons.png) no-repeat 8px 5px, -webkit-linear-gradient(#ffffff, #d9d9d9); background: url(../images/icons/filter-icons.png) no-repeat 8px 5px, -moz-linear-gradient(#ffffff, #d9d9d9); background: url(../images/icons/filter-icons.png) no-repeat 8px 5px, -o-linear-gradient(#ffffff, #d9d9d9); background: url(../images/icons/filter-icons.png) no-repeat 8px 5px, -ms-linear-gradient(#ffffff, #d9d9d9); background: url(../images/icons/filter-icons.png) no-repeat 8px 5px, linear-gradient(#ffffff, #d9d9d9); }
.cms table.ss-gridfield-table tr th button.ss-gridfield-button-reset.ss-ui-button:hover { background: url(../images/icons/filter-icons.png) no-repeat 8px -17px, -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ff0000), color-stop(100%, #cc0000)); background: url(../images/icons/filter-icons.png) no-repeat 8px -17px, -webkit-linear-gradient(#ff0000, #cc0000); background: url(../images/icons/filter-icons.png) no-repeat 8px -17px, -moz-linear-gradient(#ff0000, #cc0000); background: url(../images/icons/filter-icons.png) no-repeat 8px -17px, -o-linear-gradient(#ff0000, #cc0000); background: url(../images/icons/filter-icons.png) no-repeat 8px -17px, -ms-linear-gradient(#ff0000, #cc0000); background: url(../images/icons/filter-icons.png) no-repeat 8px -17px, linear-gradient(#ff0000, #cc0000); }
.cms table.ss-gridfield-table tr th button.ss-gridfield-button-reset.ss-ui-button:active { background: url(../images/icons/filter-icons.png) no-repeat 8px -17px, -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ff0000), color-stop(100%, #cc0000)); background: url(../images/icons/filter-icons.png) no-repeat 8px -17px, -webkit-linear-gradient(#ff0000, #cc0000); background: url(../images/icons/filter-icons.png) no-repeat 8px -17px, -moz-linear-gradient(#ff0000, #cc0000); background: url(../images/icons/filter-icons.png) no-repeat 8px -17px, -o-linear-gradient(#ff0000, #cc0000); background: url(../images/icons/filter-icons.png) no-repeat 8px -17px, -ms-linear-gradient(#ff0000, #cc0000); background: url(../images/icons/filter-icons.png) no-repeat 8px -17px, linear-gradient(#ff0000, #cc0000); -moz-box-shadow: inset 0 1px 3px #17181a, 0 1px 0 rgba(255, 255, 255, 0.6); -webkit-box-shadow: inset 0 1px 3px #17181a, 0 1px 0 rgba(255, 255, 255, 0.6); -o-box-shadow: inset 0 1px 3px #17181a, 0 1px 0 rgba(255, 255, 255, 0.6); box-shadow: inset 0 1px 3px #17181a, 0 1px 0 rgba(255, 255, 255, 0.6); }
.cms table.ss-gridfield-table tr th input.ss-gridfield-sort { padding: 2px; }
.cms table.ss-gridfield-table tr th input.ss-gridfield-sort:focus { -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; }
.cms table.ss-gridfield-table tr td { border-right: 1px solid rgba(0, 0, 0, 0.1); padding: 7px 12px; color: #666666; }
.cms table.ss-gridfield-table tr th span.non-sortable { padding: .4em 1em; }
.cms table.ss-gridfield-table tr td { border-right: 1px solid rgba(0, 0, 0, 0.1); padding: 6.4px 12px; color: #666666; }
.cms table.ss-gridfield-table tr td.bottom-all { -moz-border-radius-bottomleft: 7px; -webkit-border-bottom-left-radius: 7px; -o-border-bottom-left-radius: 7px; -ms-border-bottom-left-radius: 7px; -khtml-border-bottom-left-radius: 7px; border-bottom-left-radius: 7px; -moz-border-radius-bottomright: 7px; -webkit-border-bottom-right-radius: 7px; -o-border-bottom-right-radius: 7px; -ms-border-bottom-right-radius: 7px; -khtml-border-bottom-right-radius: 7px; border-bottom-right-radius: 7px; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #b1c0c5), color-stop(100%, #7f9198)); background-image: -webkit-linear-gradient(#b1c0c5, #7f9198); background-image: -moz-linear-gradient(#b1c0c5, #7f9198); background-image: -o-linear-gradient(#b1c0c5, #7f9198); background-image: -ms-linear-gradient(#b1c0c5, #7f9198); background-image: linear-gradient(#b1c0c5, #7f9198); }
.cms table.ss-gridfield-table tr.last td { border-bottom: 0 none; }
.cms table.ss-gridfield-table td:first-child, .cms table.ss-gridfield-table th:first-child { border-left: 1px solid rgba(0, 0, 0, 0.1); }

View File

@ -28,11 +28,9 @@
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-cancel, .ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-start { position: absolute; top: 10px; right: 0; }
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-cancel button, .ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-start button { display: block; overflow: hidden; text-indent: -9999px; padding: 0; margin: 0; border: 0; width: 16px; height: 16px; cursor: pointer; -moz-box-shadow: none; -webkit-box-shadow: none; -o-box-shadow: none; box-shadow: none; }
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-start { right: 20px; }
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-editform { /* don't use display none, for it will break jQuery('iframe').contents().height() */ height: 0; overflow: hidden; clear: both; margin-top: 8px; }
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-editform iframe { width: 100%; }
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-editform { /* don't use display none, for it will break jQuery('iframe').contents().height() */ height: 0; overflow: hidden; clear: both; }
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-editform iframe { margin-top: 8px; padding-top: 8px; border-top: 1px solid rgba(201, 205, 206, 0.8); width: 100%; }
.ss-uploadfield .ss-uploadfield-addfile.borderTop { border-top: 1px solid #b3b3b3; }
body.ss-uploadfield-edit-iframe { padding: 16px 16px; }
.ss-upload .clear { clear: both; }
.ss-upload .ss-uploadfield-fromcomputer input { /* since we can't really style the file input, we use this hack to make it as big as the button and hide it */ position: absolute; top: 0; right: 0; margin: 0; border: solid #000; border-width: 0 0 100px 200px; opacity: 0; filter: alpha(opacity=0); -o-transform: translate(250px, -50px) scale(1); -moz-transform: translate(-300px, 0) scale(4); direction: ltr; cursor: pointer; }

View File

@ -128,6 +128,13 @@ included through `translatable/_config.php`:
Object::add_extension('SiteTree', 'Translatable');
Object::add_extension('SiteConfig', 'Translatable');
### Moved Group->IPRestrictions into a new 'securityextras' module
IP restrictions for group memberships in the "Security" section were a rarely used feature,
and cluttered up the interface. We've decided to move it to a separate module
called [securityextras](https://github.com/silverstripe-labs/silverstripe-securityextras).
To continue using these restrictions, just install the module - no data migration required.
### Removed "auto-merging" of member records from `Member->onBeforeWrite()`
@ -174,3 +181,4 @@ BreadcrumbsTemplate.ss from cms/template to your theme or application.
* `XML`: Use PHP's built-in SimpleXML instead
* `DataObjectLog`: There is no replacement for this.
* `GeoIP`: Moved to separate ["geoip" module](https://github.com/silverstripe-labs/silverstripe-geoip)
* `NZGovtPasswordValidator`: Moved to ["securityextras" module](https://github.com/silverstripe-labs/silverstripe-securityextras)

View File

@ -51,7 +51,7 @@ If we wanted to make a simpler grid without pagination or filtering, we could do
A `GridFieldConfig` is made up of a new of `GridFieldComponent` objects. `GridFieldComponent` is a family of interfaces.
## Build-in components
## Built-in components
SilverStripe Framework comes with the following components that you can use out of the box.
@ -117,6 +117,18 @@ It's common for a component to implement several of these interfaces in order to
* `GridField_ActionProvider`, to define the sortasc and sortdesc actions that add sort column and direction to the state.
* `GridField_DataManipulator`, to alter the sorting of the data list based on the sort column and direction values in the state.
### GridFieldRelationAdd
A GridFieldRelationAdd is responsible for adding objects to another object's `has_many` and `many_many` relation,
as defined by the `[api:RelationList]` passed to the GridField constructor.
Objects can be searched through an input field (partially matching one or more fields).
Selecting from the results will add the object to the relation.
:::php
$group = DataObject::get_one('Group');
$config = GridFieldConfig::create()->addComponent(new GridFieldRelationAdd(array('FirstName', 'Surname', 'Email'));
$gridField = new GridField('Members', 'Members', $group->Members(), $config);
## Component interfaces
### GridField_HTMLProvider

View File

@ -120,8 +120,28 @@ class File extends DataObject {
'xml','pdf',
);
protected static $labelSeparator = ':';
/**
* @var array Category identifiers mapped to commonly used extensions.
*/
static $app_categories = array(
'audio' => array(
"aif" ,"au" ,"mid" ,"midi" ,"mp3" ,"ra" ,"ram" ,"rm","mp3" ,"wav" ,"m4a" ,"snd" ,"aifc" ,"aiff" ,"wma" ,"apl",
"avr" ,"cda" ,"mp4" ,"ogg"
),
'mov' => array(
"mpeg" ,"mpg" ,"m1v" ,"mp2" ,"mpa" ,"mpe" ,"ifo" ,"vob","avi" ,"wmv" ,"asf" ,"m2v" ,"qt"
),
'zip' => array(
"arc" ,"rar" ,"tar" ,"gz" ,"tgz" ,"bz2" ,"dmg" ,"jar","ace" ,"arj" ,"bz" ,"cab"
),
'image' => array(
"bmp" ,"gif" ,"jpg" ,"jpeg" ,"pcx" ,"tif" ,"png" ,"alpha","als" ,"cel" ,"icon" ,"ico" ,"ps"
),
'flash' => array(
'swf', 'fla'
)
);
/**
* @var If this is true, then restrictions set in {@link $allowed_max_file_size} and
* {@link $allowed_extensions} will be applied to users with admin privileges as
@ -294,57 +314,63 @@ class File extends DataObject {
return $this->canEdit($member);
}
/*
* Generate and return the preview image / file upload / replace field for this File
* @return FormField
/**
* Returns the fields to power the edit screen of files in the CMS
* @return FieldList
*/
protected function getFilePreview() {
//file upload
function getCMSFields() {
// Preview
if($this instanceof Image) {
$formattedImage = $this->getFormattedImage('SetWidth', Image::$asset_preview_width);
$thumbnail = $formattedImage ? $formattedImage->URL : '';
$previewField = new LiteralField("ImageFull",
"<img id='thumbnailImage' class='thumbnail-preview' src='{$thumbnail}?r=" . rand(1,100000) . "' alt='{$this->Name}' />\n"
);
} else {
$previewField = new LiteralField("ImageFull", $this->CMSThumbnail());
}
// Upload
$uploadField = new UploadField('UploadField','Upload Field');
$uploadField->setConfig('previewMaxWidth', 40);
$uploadField->setConfig('previewMaxHeight', 30);
$uploadField->setConfig('allowedMaxFileNumber', 1);
//$uploadField->setTemplate('FileEditUploadField');
if ($this->ParentID) {
$parent = $this->Parent();
if ($parent) { //set the parent that the Upload field should use for uploads
$uploadField->setFolderName($parent->getFilename());
$uploadField->setRecord($parent);
//TODO: make the uploadField replace the existing file
}
}
return $uploadField;
}
/**
* Returns the fields to power the edit screen of files in the CMS
* @return FieldList
*/
function getCMSFields() {
$urlLink = "<div class='field readonly'>";
$urlLink .= "<label class='left'>"._t('AssetTableField.URL','URL')."</label>";
$urlLink .= "<span class='readonly'><a href='{$this->Link()}' target='_blank'>{$this->RelativeLink()}</a></span>";
$urlLink .= "</div>";
//create the file attributes in a FieldGroup
$filePreview = new FieldGroup(
$this->getFilePreview(),
new ReadonlyField("FileType", _t('AssetTableField.TYPE','File type').self::$labelSeparator),
new ReadonlyField("Filename", _t('AssetTableField.FILENAME','File name').self::$labelSeparator),
new ReadonlyField("Size", _t('AssetTableField.SIZE','File size').self::$labelSeparator, $this->getSize()),
new DateField_Disabled("Created", _t('AssetTableField.CREATED','First uploaded').self::$labelSeparator),
new DateField_Disabled("LastEdited", _t('AssetTableField.LASTEDIT','Last changed').self::$labelSeparator)
);
$filePreview->setTitle("File preview");
$filePreview->setName("FilePreview");
$filePreview = FormField::create('CompositeField',
FormField::create('CompositeField',
$previewField
)->setName("FilePreviewImage")->addExtraClass('cms-file-info-preview'),
FormField::create('CompositeField',
FormField::create('CompositeField',
new ReadonlyField("FileType", _t('AssetTableField.TYPE','File type') . ':'),
new ReadonlyField("Size", _t('AssetTableField.SIZE','File size') . ':', $this->getSize()),
$urlField = new ReadonlyField('ClickableURL', _t('AssetTableField.URL','URL'),
sprintf('<a href="%s" target="_blank">%s</a>', $this->Link(), $this->RelativeLink())
),
new DateField_Disabled("Created", _t('AssetTableField.CREATED','First uploaded') . ':'),
new DateField_Disabled("LastEdited", _t('AssetTableField.LASTEDIT','Last changed') . ':')
)
)->setName("FilePreviewData")->addExtraClass('cms-file-info-data')
)->setName("FilePreview")->addExtraClass('cms-file-info');
$urlField->dontEscape = true;
return new FieldList(
new TabSet('Root',
new Tab('Main',
$filePreview,
//TODO: make the uploadField replace the existing file
// $uploadField,
new TextField("Title", _t('AssetTableField.TITLE','Title')),
new TextField("Name", _t('AssetTableField.FILENAME','Filename')),
new LiteralField("AbsoluteURL", $urlLink), //TODO: replace this is a proper preview
new DropdownField("OwnerID", _t('AssetTableField.OWNER','Owner'), Member::mapInCMSGroups())
)
)
@ -361,27 +387,10 @@ class File extends DataObject {
*/
public function appCategory() {
$ext = strtolower($this->Extension);
switch($ext) {
case "aif": case "au": case "mid": case "midi": case "mp3": case "ra": case "ram": case "rm":
case "mp3": case "wav": case "m4a": case "snd": case "aifc": case "aiff": case "wma": case "apl":
case "avr": case "cda": case "mp4": case "ogg":
return "audio";
case "mpeg": case "mpg": case "m1v": case "mp2": case "mpa": case "mpe": case "ifo": case "vob":
case "avi": case "wmv": case "asf": case "m2v": case "qt":
return "mov";
case "arc": case "rar": case "tar": case "gz": case "tgz": case "bz2": case "dmg": case "jar":
case "ace": case "arj": case "bz": case "cab":
return "zip";
case "bmp": case "gif": case "jpg": case "jpeg": case "pcx": case "tif": case "png": case "alpha":
case "als": case "cel": case "icon": case "ico": case "ps":
return "image";
case "swf":
return "flash";
foreach(self::$app_categories as $category => $exts) {
if(in_array($ext, $exts)) return $category;
}
return false;
}
function CMSThumbnail() {
@ -804,46 +813,6 @@ class File extends DataObject {
return 0;
}
}
/**
* We've overridden the DataObject::get function for File so that the very large content field
* is excluded!
*
* @todo Admittedly this is a bit of a hack; but we need a way of ensuring that large
* TEXT fields don't stuff things up for the rest of us. Perhaps a separate search table would
* be a better way of approaching this?
* @deprecated alternative_instance_get()
*/
public function instance_get($filter = "", $sort = "", $join = "", $limit="", $containerClass = "DataObjectSet", $having="") {
Deprecation::notice('2.5', 'Use alternative_instance_get() instead.');
$query = $this->extendedSQL($filter, $sort, $limit, $join, $having);
$baseTable = reset($query->from);
$excludeDbColumns = array('Content');
// Work out which columns we're actually going to select
// In short, we select everything except File.Content
$dataobject_select = array();
foreach($query->select as $item) {
/*
if($item == "\"File\".*") {
$fileColumns = DB::query("SHOW FIELDS IN \"File\"")->column();
$columnsToAdd = array_diff($fileColumns, $excludeDbColumns);
foreach($columnsToAdd as $otherItem) $dataobject_select[] = '"File".' . $otherItem;
} else {
*/
$dataobject_select[] = $item;
//}
}
$query->select = $dataobject_select;
$records = $query->execute();
$ret = $this->buildDataObjectSet($records, $containerClass);
return $ret;
}
public function flushCache() {
parent::flushCache();
@ -895,23 +864,6 @@ class File extends DataObject {
return new ValidationResult(true);
}
/**
* Allow custom fields for uploads in {@link AssetAdmin}.
* Similar to {@link getCMSFields()}, but a more restricted
* set of fields which can be reliably set on any file type.
*
* Needs to be enabled through {@link AssetAdmin::$metadata_upload_enabled}
*
* @return FieldList
*/
function uploadMetadataFields() {
$fields = new FieldList();
$fields->push(new TextField('Title', $this->fieldLabel('Title')));
$this->extend('updateUploadMetadataFields', $fields);
return $fields;
}
/**
* @var Array Only use lowercase extensions in here.

View File

@ -408,7 +408,12 @@ class Folder extends File {
*/
function getCMSFields() {
// Hide field on root level, which can't be renamed
$titleField = (!$this->ID || $this->ID === "root") ? new HiddenField("Name") : new TextField("Name", _t('Folder.NAME'));
if(!$this->ID || $this->ID === "root") {
$titleField = new HiddenField("Name");
} else {
$titleField = new TextField("Name", $this->fieldLabel('Name'));
}
$fields = new FieldList(
$titleField,
new HiddenField('ParentID')

View File

@ -29,6 +29,8 @@ class AjaxUniqueTextField extends TextField {
}
function Field() {
Requirements::javascript(THIRDPARTY_DIR . "/prototype/prototype.js");
Requirements::javascript(THIRDPARTY_DIR . "/behaviour/behaviour.js");
Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang');
Requirements::javascript(SAPPHIRE_DIR . "/javascript/UniqueFields.js");
@ -87,7 +89,7 @@ Behaviour.register({
else {
Element.addClassName(self, 'inuse');
}
}
},
error: function(response) {
}

View File

@ -184,10 +184,16 @@ class CheckboxSetField extends OptionsetField {
$fieldname = $this->name ;
if($fieldname && $record && ($record->has_many($fieldname) || $record->many_many($fieldname))) {
$idList = array();
if($this->value) foreach($this->value as $id => $bool) {
if($bool) {
$idList[] = $id;
}
// Works for both <select multiple> style - array(0 => 'val1', 1 => 'val2')
// and <input type="checkbox"> style - array('val1' => true, 'val2' => true).
// The <select multiple> element doesn't allow for individual keys in parameter names.
$valuesInKeys = (ArrayLib::is_associative($this->value));
if($this->value) foreach($this->value as $k => $v) {
if($valuesInKeys) {
if($v) $idList[] = $k;
} else {
$idList[] = $v;
}
}
$record->$fieldname()->setByIDList($idList);
} elseif($fieldname && $record) {
@ -214,7 +220,6 @@ class CheckboxSetField extends OptionsetField {
$filtered[] = str_replace(",", "{comma}", $item);
}
}
return implode(',', $filtered);
}

View File

@ -298,7 +298,7 @@ class DatetimeField_Readonly extends DatetimeField {
$format = sprintf(
$this->getConfig('datetimeorder'),
$this->dateField->getConfig('dateformat'),
$this->dateField->getConfig('timeformat')
$this->timeField->getConfig('timeformat')
);
$valueObj = new Zend_Date(
sprintf($this->getConfig('datetimeorder'), $valDate, $valTime),

View File

@ -504,7 +504,29 @@ class HtmlEditorField_Toolbar extends RequestHandler {
* @return FieldList
*/
protected function getFieldsForImage($url, $file) {
$formattedImage = $file->getFormattedImage('SetWidth', Image::$asset_preview_width);
$thumbnail = $formattedImage ? $formattedImage->URL : '';
$previewField = new LiteralField("ImageFull",
"<img id='thumbnailImage' class='thumbnail-preview' src='{$thumbnail}?r=" . rand(1,100000) . "' alt='{$file->Name}' />\n"
);
$fields = new FieldList(
$filePreview = FormField::create('CompositeField',
FormField::create('CompositeField',
$previewField
)->setName("FilePreviewImage")->addExtraClass('cms-file-info-preview'),
FormField::create('CompositeField',
FormField::create('CompositeField',
new ReadonlyField("FileType", _t('AssetTableField.TYPE','File type') . ':', $file->FileType),
new ReadonlyField("Size", _t('AssetTableField.SIZE','File size') . ':', $file->getSize()),
$urlField = new ReadonlyField('ClickableURL', _t('AssetTableField.URL','URL'),
sprintf('<a href="%s" target="_blank">%s</a>', $file->Link(), $file->RelativeLink())
),
new DateField_Disabled("Created", _t('AssetTableField.CREATED','First uploaded') . ':', $file->Created),
new DateField_Disabled("LastEdited", _t('AssetTableField.LASTEDIT','Last changed') . ':', $file->LastEdited)
)
)->setName("FilePreviewData")->addExtraClass('cms-file-info-data')
)->setName("FilePreview")->addExtraClass('cms-file-info'),
new TextField(
'AltText',
_t('HtmlEditorField.IMAGEALTTEXT', 'Alternative text (alt) - shown if image cannot be displayed'),
@ -531,6 +553,7 @@ class HtmlEditorField_Toolbar extends RequestHandler {
$heightField = new TextField('Height', " x " . _t('HtmlEditorField.IMAGEHEIGHTPX', 'Height'), $file->Height)
)
);
$urlField->dontEscape = true;
$dimensionsField->addExtraClass('dimensions');
$widthField->setMaxLength(5);
$heightField->setMaxLength(5);
@ -590,6 +613,7 @@ class HtmlEditorField_File extends ViewableData {
function __construct($url, $file = null) {
$this->url = $url;
$this->file = $file;
$this->failover = $file;
parent::__construct();
}

View File

@ -94,8 +94,8 @@ class GridFieldAction_Edit implements GridField_ColumnProvider {
}
/**
* This class is an GridField Component that add Delete action for Objects in the GridField
*
* This class is an GridField Component that add Delete action for Objects in the GridField.
* See {@link GridFieldRelationDelete} for detaching an item from the current relationship instead.
*/
class GridFieldAction_Delete implements GridField_ColumnProvider, GridField_ActionProvider {
@ -170,6 +170,7 @@ class GridFieldAction_Delete implements GridField_ColumnProvider, GridField_Acti
"deleterecord",
array('RecordID' => $record->ID)
);
$field->addExtraClass('gridfield-button-delete');
$output = $field->Field();
return $output;
}
@ -186,6 +187,7 @@ class GridFieldAction_Delete implements GridField_ColumnProvider, GridField_Acti
public function handleAction(GridField $gridField, $actionName, $arguments, $data) {
if($actionName == 'deleterecord') {
$id = $arguments['RecordID'];
// Always deletes a record. Use GridFieldRelationDelete to detach it from the current relationship.
$item = $gridField->getList()->byID($id);
if(!$item) return;
$item->delete();

View File

@ -88,7 +88,7 @@ class GridFieldConfig_Base extends GridFieldConfig {
* @return GridFieldConfig_Base
*/
public static function create($itemsPerPage=15){
return new GridFieldConfig_Base($itemsPerPage=15);
return new GridFieldConfig_Base($itemsPerPage);
}
/**
@ -121,24 +121,22 @@ class GridFieldConfig_ManyManyEditor extends GridFieldConfig {
/**
*
* @param string $fieldToSearch - Which field on the object should be searched for
* @param bool $autoSuggest - Show a jquery.ui.autosuggest dropdown field
* @param int $itemsPerPage - How many items per page should show up
* @return GridFieldConfig_ManyManyEditor
*/
public static function create($fieldToSearch, $autoSuggest=true, $itemsPerPage=25){
return new GridFieldConfig_ManyManyEditor($fieldToSearch, $autoSuggest=true, $itemsPerPage=25);
public static function create($fieldToSearch, $itemsPerPage=15){
return new GridFieldConfig_ManyManyEditor($fieldToSearch, $itemsPerPage=15);
}
/**
*
* @param string $fieldToSearch - Which field on the object should be searched for
* @param bool $autoSuggest - Show a jquery.ui.autosuggest dropdown field
* @param int $itemsPerPage - How many items per page should show up
*/
public function __construct($fieldToSearch, $autoSuggest=true, $itemsPerPage=25) {
$this->addComponent(new GridFieldFilter());
$this->addComponent(new GridFieldRelationAdd($fieldToSearch, $autoSuggest));
public function __construct($fieldToSearch, $itemsPerPage=15) {
$this->addComponent(new GridFieldRelationAdd($fieldToSearch));
$this->addComponent(new GridFieldSortableHeader());
$this->addComponent(new GridFieldFilter());
$this->addComponent(new GridFieldDefaultColumns());
$this->addComponent(new GridFieldAction_Edit());
$this->addComponent(new GridFieldRelationDelete());

View File

@ -59,7 +59,7 @@ class GridFieldDefaultColumns implements GridField_ColumnProvider {
}
public function getColumnAttributes($gridField, $item, $column) {
return array('class' => 'col-' . $column);
return array('class' => 'col-' . preg_replace('/[^\w]/', '-', $column));
}
public function getColumnMetadata($gridField, $column) {

View File

@ -47,7 +47,7 @@ class GridFieldExporter implements GridField_HTMLProvider, GridField_ActionProvi
null
);
return array(
'after' => '<p>' . htmlentities($button->Field()) . '</p>',
'after' => '<p>' . $button->Field() . '</p>',
);
}

View File

@ -72,19 +72,19 @@ class GridFieldFilter implements GridField_HTMLProvider, GridField_DataManipulat
}
$field = new TextField('filter['.$columnField.']', '', $value);
$field->addExtraClass('ss-gridfield-sort');
$field = new FieldGroup(
$field,
$filterbutton = new GridField_Action($gridField, 'filter', _t('GridField.Filter', "Filter"), 'filter', null),
$resetbutton = new GridField_Action($gridField, 'reset', _t('GridField.ResetFilter', "Reset"), 'reset', null)
);
$filterbutton->addExtraClass('ss-gridfield-button-filter');
$resetbutton->addExtraClass('ss-gridfield-button-reset');
} else {
$field = new LiteralField('', '');
}
// Last column, inject action buttons
if($currentColumn == count($columns)) {
$field = new FieldGroup(
$field,
new GridField_Action($gridField, 'filter', _t('GridField.Filter', "Filter"), 'filter', null),
new GridField_Action($gridField, 'reset', _t('GridField.ResetFilter', "Reset"), 'reset', null)
);
}
$field->iteratorProperties($currentColumn-1, count($columns));
$forTemplate->Fields->push($field);
}

View File

@ -1,14 +1,9 @@
<?php
/**
* A GridFieldRelationAdd is responsible for adding objects to another objects
* has_many and many_many relation. It will not attach duplicate objects.
*
* It augments a GridField with fields above the gridfield to search and add
* objects to whatever the SS_List passed into the gridfield.
*
* If the object is set to use autosuggestion it will include jQuery UI
* autosuggestion field that searches for current objects that isn't already
* attached to the list.
* A GridFieldRelationAdd is responsible for adding objects to another object's has_many and many_many relation,
* as defined by the RelationList passed to the GridField constructor.
* Objects can be searched through an input field (partially matching one or more fields).
* Selecting from the results will add the object to the relation.
*/
class GridFieldRelationAdd implements GridField_HTMLProvider, GridField_ActionProvider, GridField_DataManipulator, GridField_URLHandler {
@ -20,27 +15,29 @@ class GridFieldRelationAdd implements GridField_HTMLProvider, GridField_ActionPr
protected $itemClass = 'GridFieldRelationAdd';
/**
* Which column that should be used for doing a StartsWith search
* Which columns that should be used for doing a "StartsWith" search.
* If multiple fields are provided, the filtering is performed non-exclusive.
*
* @var string
* @var Array
*/
protected $fieldToSearch = '';
protected $searchFields = array();
/**
* Use the jQuery.ui.autosuggestion plugin
*
* @var bool
* @var string SSViewer template to render the results presentation
*/
protected $useAutoSuggestion = true;
protected $resultsFormat = '$Title';
/**
* @var String Text shown on the search field, instructing what to search for.
*/
protected $placeholderText;
/**
*
* @param string $fieldToSearch which field on the object in the list should be search
* @param bool $autoSuggestion - if you would like to use the javascript autosuggest feature
* @param array $searchFields Which fields on the object in the list should be searched
*/
public function __construct($fieldToSearch, $autoSuggestion=true) {
$this->fieldToSearch = $fieldToSearch;
$this->useAutoSuggestion = $autoSuggestion;
public function __construct($searchFields) {
$this->searchFields = (array)$searchFields;
}
/**
@ -52,25 +49,24 @@ class GridFieldRelationAdd implements GridField_HTMLProvider, GridField_ActionPr
$searchState = $gridField->State->GridFieldSearchRelation;
if($this->useAutoSuggestion){
Requirements::css(THIRDPARTY_DIR . '/jquery-ui-themes/smoothness/jquery-ui.css');
Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang');
Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js');
Requirements::javascript(SAPPHIRE_DIR . '/thirdparty/jquery-ui/jquery-ui.js');
Requirements::javascript(SAPPHIRE_DIR . "/javascript/GridFieldSearch.js");
}
Requirements::css(THIRDPARTY_DIR . '/jquery-ui-themes/smoothness/jquery-ui.css');
Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang');
Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js');
Requirements::javascript(SAPPHIRE_DIR . '/thirdparty/jquery-ui/jquery-ui.js');
Requirements::javascript(SAPPHIRE_DIR . "/javascript/GridFieldSearch.js");
$forTemplate = new ArrayData(array());
$forTemplate->Fields = new ArrayList();
$value = $this->findSingleEntry($gridField, $this->fieldToSearch, $searchState, $gridField->getList()->dataClass);
$value = $this->findSingleEntry($gridField, $this->searchFields, $searchState, $gridField->getList()->dataClass);
$searchField = new TextField('gridfield_relationsearch', _t('GridField.RelationSearch', "Relation search"), $value);
// Apparently the data-* needs to be double qouted for the jQuery.meta data plugin
$searchField->setAttribute('data-search-url', '\''.Controller::join_links($gridField->Link('search').'\''));
$searchField->setAttribute('placeholder', $this->getPlaceholderText($gridField->getList()->dataClass()));
$searchField->addExtraClass('relation-search');
$findAction = new GridField_Action($gridField, 'gridfield_relationfind', _t('GridField.Find', "Find"), 'find', 'find');
$addAction = new GridField_Action($gridField, 'gridfield_relationadd', _t('GridField.Add', "Add"), 'addto', 'addto');
$addAction = new GridField_Action($gridField, 'gridfield_relationadd', _t('GridField.LinkExisting', "Link Exisiting"), 'addto', 'addto');
// If an object is not found, disable the action
if(!is_int($gridField->State->GridFieldAddRelation)) {
@ -156,15 +152,86 @@ class GridFieldRelationAdd implements GridField_HTMLProvider, GridField_ActionPr
*/
public function doSearch($gridField, $request) {
$allList = DataList::create($gridField->getList()->dataClass());
$results = $allList->subtract($gridField->getList())->filter($this->fieldToSearch.':StartsWith',$request->param('ID'));
$results->sort($this->fieldToSearch, 'ASC');
$filters = array();
$stmts = array();
// TODO Replace with DataList->filterAny() once it correctly supports OR connectives
foreach($this->searchFields as $searchField) {
$stmts[] .= sprintf('"%s" LIKE \'%s%%\'', $searchField, $request->param('ID'));
}
$results = $allList->where(implode(' OR ', $stmts))->subtract($gridField->getList());
$results->sort($this->searchFields[0], 'ASC');
$json = array();
foreach($results as $result) {
$json[$result->ID] = $result->{$this->fieldToSearch};
$json[$result->ID] = SSViewer::fromString($this->resultsFormat)->process($result);
}
return Convert::array2json($json);
}
/**
* @param String
*/
public function setResultsFormat($format) {
$this->resultsFormat = $format;
return $this;
}
/**
* @return String
*/
public function getResultsFormat() {
return $this->resultsFormat;
}
/**
* @param Array
*/
public function setSearchFields($fields) {
$this->searchFields = $fields;
return $this;
}
/**
* @return Array
*/
public function getSearchFields() {
return $this->searchFields;
}
/**
* @param String The class of the object being searched for
* @return String
*/
public function getPlaceholderText($dataClass) {
if($this->placeholderText) {
return $this->placeholderText;
} else {
$labels = array();
foreach($this->searchFields as $searchField) {
$label = singleton($dataClass)->fieldLabel($searchField);
if($label) $labels[] = $label;
}
if($labels) {
return sprintf(
_t('GridField.PlaceHolderWithLabels', 'Find %s by %s', PR_MEDIUM, 'Find <object type> by <field names>'),
singleton($dataClass)->plural_name(),
implode(', ', $labels)
);
} else {
return sprintf(
_t('GridField.PlaceHolder', 'Find %s', PR_MEDIUM, 'Find <object type>'),
singleton($dataClass)->plural_name()
);
}
}
}
/**
* @param String
*/
public function setPlaceholderText($text) {
$this->placeholderText = $text;
}
/**
* This will provide a StartsWith search that only returns a value if we are

View File

@ -1,7 +1,9 @@
<?php
/**
* GridFieldRelationDelete
*
* Allows to detach an item from an existing has_many or many_many relationship.
* Similar to {@link GridFieldAction_Delete}, but allows to distinguish between
* a "delete" and "detach" action in the UI - and to use both in parallel, if required.
* Requires the GridField to be populated with a RelationList rather than a plain DataList.
*/
class GridFieldRelationDelete implements GridField_ColumnProvider, GridField_ActionProvider {

View File

@ -33,9 +33,14 @@ class GridFieldSortableHeader implements GridField_HTMLProvider, GridField_DataM
$field->addExtraClass('ss-gridfield-sort');
if($state->SortColumn == $columnField){
$field->addExtraClass('ss-gridfield-sorted');
if($state->SortDirection == 'asc')
$field->addExtraClass('ss-gridfield-sorted-asc');
else
$field->addExtraClass('ss-gridfield-sorted-desc');
}
} else {
$field = new LiteralField($columnField, $title);
$field = new LiteralField($columnField, '<span class="non-sortable">' . $title . '</span>');
}
$forTemplate->Fields->push($field);
}

BIN
images/arrows-01 copy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
images/arrows.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
images/icons/decline.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 732 B

BIN
images/icons/document--pencil.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -11,6 +11,12 @@
if(!ajaxOpts.data) ajaxOpts.data = [];
ajaxOpts.data = ajaxOpts.data.concat(data);
// Include any GET parameters from the current URL, as the view state might depend on it.
// For example, a list prefiltered through external search criteria might be passed to GridField.
if(window.location.search) {
ajaxOpts.data = window.location.search.replace(/^\?/, '') + '&' + $.param(ajaxOpts.data);
}
form.addClass('loading');
$.ajax($.extend({}, {
@ -34,6 +40,9 @@
}
}, ajaxOpts));
},
showDetailView: function(url) {
window.location.href = url;
},
getItems: function() {
return this.find('.ss-gridfield-item');
},
@ -59,6 +68,24 @@
return this.closest('.ss-gridfield');
}
});
$('.ss-gridfield .ss-gridfield-item').entwine({
onclick: function(e) {
if($(e.target).is('.action')) {
this._super(e);
return;
}
var editLink = this.find('.edit-link');
if(editLink.length) this.getGridField().showDetailView(editLink.prop('href'));
},
onmouseover: function() {
if(this.find('.edit-link').length) this.css('cursor', 'pointer');
},
onmouseout: function() {
this.css('cursor', 'default');
}
});
$('.ss-gridfield .action').entwine({
onclick: function(e){
@ -67,63 +94,23 @@
}
});
$('.ss-gridfield .action-deleterecord').entwine({
$('.ss-gridfield .gridfield-button-delete').entwine({
onclick: function(e){
if(!confirm(ss.i18n._t('TABLEFIELD.DELETECONFIRMMESSAGE'))) return false;
else this._super(e);
}
});
/*
* Upon focusing on a filter <input> element, move "filter" and "reset" buttons and display next to the current <input> element
* ToDo ensure filter-button state is maintained after filtering (see resetState param)
* ToDo get working in IE 6-7
*/
$('.ss-gridfield input.ss-gridfield-sort').entwine({
onfocusin: function(e) {
// Dodgy results in IE <=7 & ignore if only one filter-field
countfields = $('.ss-gridfield input.ss-gridfield-sort').length;
if(($.browser.msie && $.browser.version <= 7) || countfields == 1) {
return false;
}
var eleInput = $(this);
// Remove existing <div> and <button> elements in-lieu of cloning
this.getGridField().find('th > div').each(function(i,v) {$(v).remove();});
var eleButtonSetFilter = $('#action_filter');
var eleButtonResetFilter = $('#action_reset');
// Retain current widths to ensure <th>'s don't shift widths
var eleButtonWidth = eleButtonSetFilter.width();
// Check <th> doesn't already have an (extra) cloned <button> appended, otherwise clone
if(eleInput.closest('th').children().length == 1) {
var newButtonCss = {
'position':'absolute',
'top':'-23px',
'left':'0',
'border':'#EEE solid 1px',
'padding':'0',
'margin-left':'0'
};
// Append a <div> element used purely for CSS positioning - table elements on their own are untrustworthy to style in this manner
$('<div/>').append(
eleButtonSetFilter.clone().css(newButtonCss),
eleButtonResetFilter.clone().css(newButtonCss).css('left',(eleButtonWidth+4)+'px')
).css({'position':'relative','margin':'0 auto','width':'65%'}).appendTo(eleInput.closest('th'));
}
}
});
$('fieldset.ss-gridfield .new-link').entwine({
onclick: function(e) {
$(this).trigger('opennewview', $(this).prop('href'));
this.getGridField().showDetailView($(this).prop('href'));
return false;
}
});
$('fieldset.ss-gridfield .edit-link').entwine({
onclick: function(e) {
$(this).trigger('openeditview', $(this).prop('href'));
this.getGridField().showDetailView($(this).prop('href'));
return false;
}
});
@ -160,4 +147,18 @@
});
/**
* Catch submission event in filter input fields, and submit the correct button
* rather than the whole form.
*/
$('.ss-gridfield .filter-header :input').entwine({
onkeydown: function(e) {
if(e.keyCode == '13') {
btn = this.closest('.filter-header').find('.ss-gridfield-button-filter');
this.getGridField().reload({data: [{name: btn.attr('name'), value: btn.val()}]});
return false;
}
}
});
}(jQuery));

View File

@ -28,7 +28,12 @@ jQuery(function($){
$(this).closest(".ss-gridfield").find("#action_gridfield_relationfind").replaceWith(
'<input type="hidden" name="relationID" value="'+ui.item.id+'" id="relationID"/>'
);
$(this).closest(".ss-gridfield").find("#action_gridfield_relationadd").removeAttr('disabled');
var addbutton = $(this).closest(".ss-gridfield").find("#action_gridfield_relationadd");
if(addbutton.data('button')){
addbutton.button('enable');
}else{
addbutton.removeAttr('disabled');
}
}
});
});

View File

@ -30,6 +30,8 @@
Config: null,
onmatch: function() {
if(this.is('.readonly,.disabled')) return;
var fileInput = this.find('input');
var dropZone = this.find('.ss-uploadfield-dropzone');
var config = $.parseJSON(fileInput.data('config').replace(/'/g,'"'));
@ -38,7 +40,10 @@
this.fileupload($.extend(true,
{
formData: function(form) {
return [{name: 'SecurityID', value: $(form).find(':input[name=SecurityID]').val()}];
return [
{name: 'SecurityID', value: $(form).find(':input[name=SecurityID]').val()},
{name: 'ID', value: $(form).find(':input[name=ID]').val()}
];
},
errorMessages: {
// errorMessages for all error codes suggested from the plugin author, some will be overwritten by the config comming from php
@ -196,18 +201,26 @@
}
});
$('div.ss-upload .ss-uploadfield-item-editform').entwine({
fitHeight: function() {
var iframe = this.find('iframe'), h = iframe.contents().height();
// Set iframe to match its contents height
iframe.height(h);
// set container to match the same height
iframe.parent().height(h);
},
toggleEditForm: function() {
jQuery(this).toggle();
if(this.height() === 0) {
this.fitHeight();
} else {
this.height(0);
}
}
});
$('div.ss-upload .ss-uploadfield-item-editform iframe').entwine({
onmatch: function() {
// TODO entwine event binding doesn't work for iframes
this.load(function() {
var iframe = $(this), h = iframe.contents().height();
// Set iframe to match its contents height
iframe.height(h);
// set container to match the same height
iframe.parent().removeClass('loading').height(h);
$(this).parent().removeClass('loading');
});
}
});

View File

@ -706,7 +706,6 @@ $lang['en_US']['Security']['CHANGEPASSWORDBELOW'] = 'You can change your passwor
$lang['en_US']['Security']['CHANGEPASSWORDHEADER'] = 'Change your password';
$lang['en_US']['Security']['ENTERNEWPASSWORD'] = 'Please enter a new password.';
$lang['en_US']['Security']['ERRORPASSWORDPERMISSION'] = 'You must be logged in in order to change your password!';
$lang['en_US']['Security']['IPADDRESSES'] = 'IP Addresses';
$lang['en_US']['Security']['LOGGEDOUT'] = 'You have been logged out. If you would like to log in again, enter your credentials below.';
$lang['en_US']['Security']['LOGIN'] = 'Log in';
$lang['en_US']['Security']['LOSTPASSWORDHEADER'] = 'Lost Password';
@ -721,15 +720,6 @@ $lang['en_US']['SecurityAdmin']['APPLY_ROLES_HELP'] = 'Ability to edit the roles
$lang['en_US']['SecurityAdmin']['EDITPERMISSIONS'] = 'Manage permissions for groups';
$lang['en_US']['SecurityAdmin']['EDITPERMISSIONS_HELP'] = 'Ability to edit Permissions and IP Addresses for a group. Requires the "Access to \'Security\' section" permission.';
$lang['en_US']['SecurityAdmin']['GROUPNAME'] = 'Group name';
$lang['en_US']['SecurityAdmin']['IPADDRESSESHELP'] = '<p>You can restrict this group to a particular
IP address range (one range per line). <br />Ranges can be in any of the following forms: <br />
203.96.152.12<br />
203.96.152/24<br />
203.96/16<br />
203/8<br /><br />If you enter one or more IP address ranges in this box, then members will only get
the rights of being in this group if they log on from one of the valid IP addresses. It won\'t prevent
people from logging in. This is because the same user might have to log in to access parts of the
system without IP address restrictions.';
$lang['en_US']['SecurityAdmin']['MEMBERS'] = 'Members';
$lang['en_US']['SecurityAdmin']['MENUTITLE'] = array(
'Users',

View File

@ -605,6 +605,21 @@ class Hierarchy extends DataExtension {
return $ancestors;
}
/**
* Returns a human-readable, flattened representation of the path to the object,
* using its {@link Title()} attribute.
*
* @param String
* @return String
*/
public function getBreadcrumbs($separator = ' &raquo; ') {
$crumbs = array();
$ancestors = array_reverse($this->owner->getAncestors()->toArray());
foreach($ancestors as $ancestor) $crumbs[] = $ancestor->Title;
$crumbs[] = $this->owner->Title;
return implode($separator, $crumbs);
}
/**
* Get the next node in the tree of the type. If there is no instance of the className descended from this node,

View File

@ -73,21 +73,6 @@ class Image extends File {
parent::defineMethods();
}
/*
* Generate and return the preview image / file upload / replace field for this File
* @return FormField
*/
protected function getFilePreview() {
$formattedImage = $this->getFormattedImage('AssetLibraryPreview');
$thumbnail = $formattedImage ? $formattedImage->URL : '';
$previewField = new LiteralField("ImageFull",
"<img id='thumbnailImage' class='thumbnail-preview' src='{$thumbnail}?r=" . rand(1,100000) . "' alt='{$this->Name}' />\n"
);
return $previewField;
}
function getCMSFields() {
$fields = parent::getCMSFields();
@ -97,8 +82,8 @@ class Image extends File {
$urlLink .= "</div>";
//attach the addition file information for an image to the existing FieldGroup create in the parent class
$fileAttributes = $fields->FieldByName('Root.Main.FilePreview');
$fileAttributes->push(new ReadonlyField("Dimensions", _t('AssetTableField.DIM','Dimensions').self::$labelSeparator));
$fileAttributes = $fields->fieldByName('Root.Main.FilePreview')->fieldByName('FilePreviewData');
$fileAttributes->push(new ReadonlyField("Dimensions", _t('AssetTableField.DIM','Dimensions') . ':'));
return $fields;
}

View File

@ -31,17 +31,10 @@ class ForeignKey extends Int {
$hasOneClass = $this->object->has_one($relationName);
if($hasOneClass && singleton($hasOneClass) instanceof Image) {
if(isset($params['ajaxSafe']) && $params['ajaxSafe']) {
$field = new ImageField($relationName, $title, $this->value);
} else {
$field = new SimpleImageField($relationName, $title, $this->value);
}
$field = new UploadField($relationName, $title);
$field->getValidator()->setAllowedExtensions(array('jpg', 'jpeg', 'png', 'gif'));
} elseif($hasOneClass && singleton($hasOneClass) instanceof File) {
if(isset($params['ajaxSafe']) && $params['ajaxSafe']) {
$field = new FileIFrameField($relationName, $title, $this->value);
} else {
$field = new FileField($relationName, $title, $this->value);
}
$field = new UploadField($relationName, $title);
} else {
$titleField = (singleton($hasOneClass)->hasField('Title')) ? "Title" : "Name";
$map = DataList::create($hasOneClass)->map("ID", $titleField);

View File

@ -160,11 +160,14 @@
height: 0;
overflow: hidden;
clear: both;
iframe {
margin: $grid-x*2;
width: 100%;
}
}
}
.ss-uploadfield-addfile {
.ss-uploadfield-item-info {

View File

@ -22,7 +22,13 @@ $gf_colour_zebra: #F0F4F7;
$gf_colour_font: #666;
$gf_colour_text_shadow: rgba(0,0,0,.3);
$gf_border_radius: 7px;
$gf_color_border_filter_button: #9A9A9A;
$gf_color_button: #e6e6e6;
$gf_color_button_filter_hover: #338DC1;
$gf_color_button_reset_hover: #FF0000;
$gf_grid_y: 12px;
$gf_grid_x: 16px;
@mixin box-shadow-none {
-moz-box-shadow: none;
@ -71,6 +77,25 @@ $gf_border_radius: 7px;
padding: 0;
width: auto;
text-shadow: none;
&.ui-state-hover {
background:none;
border:none;
@include box-shadow-none;
}
span.ui-button-text {
text-indent:-9999em;
background: url(../images/icons/decline.png) no-repeat 0 2px;
padding:0;
width:20px;
height:20px;
}
}
a.edit-link {
display:inline-block;
height:20px;
width:20px;
text-indent:-9999em;
background: url(../images/icons/document--pencil.png) no-repeat 0 1px;
}
}
}
@ -100,13 +125,13 @@ $gf_border_radius: 7px;
@include single-text-shadow($gf_colour_text_shadow, 0px, -1px, 0);
h2{
padding: 0px;
font-size: 16px;
font-size: $gf_grid_y*1.4;
color:#fff;
margin:0;
display:inline;
margin:3px $gf_grid_x/2 0;
display:inline-block;
}
.new{
font-size: 14px;
font-size: $gf_grid_y*1.2;
border-color: $gf_colour_border;
float: right;
}
@ -114,6 +139,10 @@ $gf_border_radius: 7px;
}
&.sortable-header {
background: $gf_colour_subheader;
th{
padding: 0px;
}
}
&:hover {
background: #FFFAD6 !important;
@ -134,7 +163,7 @@ $gf_border_radius: 7px;
th {
font-weight: bold;
font-size: 12px;
font-size: $gf_grid_y;
color: #FFF;
padding: 5px;
border-right: 1px solid $gf_colour_border;
@ -146,7 +175,8 @@ $gf_border_radius: 7px;
}
div {
&.fieldgroup,&.fieldgroup-field {
width: auto;
width: 100%;
position:relative;
}
&.fieldgroup {
min-width: 200px;
@ -181,6 +211,9 @@ $gf_border_radius: 7px;
width: auto;
display: inline;
position: static;
input {
height:28px;
}
}
button.ss-ui-button {
padding: .3em;
@ -210,7 +243,7 @@ $gf_border_radius: 7px;
@include box-shadow-none;
}
&.ss-gridfield-sort {
background: transparent url(../images/arrows-01.png) no-repeat right 2px;
background: transparent url(../images/arrows.png) no-repeat right 6px;
border:none;
width:100%;
text-align: left;
@ -218,20 +251,109 @@ $gf_border_radius: 7px;
@include single-text-shadow($gf_colour_text_shadow, 0px, -1px, 0);
color: #fff;
@include border-radius(0);
&:hover {
background-position: right -34px;
}
&.ss-gridfield-sorted-desc {
background-position: right -72px;
}
&.ss-gridfield-sorted-asc {
background-position: right -116px;
}
}
&.ss-gridfield-button-filter.ss-ui-button{
position:absolute;
right:$gf_grid_x/2 - 1;
top:$gf_grid_y*-2 - 4;
display:block;
text-indent:-9999em;
width:$gf_grid_x*2 - 2;
height:$gf_grid_y*2 + 4;
border: {
top-left-radius:0px;
bottom-left-radius:0px;
top-right-radius:4px;
bottom-right-radius:4px;
bottom-width:1px;
color:$gf_color_border_filter_button;
}
@include background (url(../images/icons/filter-icons.png) no-repeat -40px 6px,
linear-gradient(
lighten($gf_color_button, 10%),
darken($gf_color_button, 5%)
));
&:hover {
@include background (url(../images/icons/filter-icons.png) no-repeat -16px 6px,
linear-gradient(
lighten($gf_color_button_filter_hover, 5%),
darken($gf_color_button_filter_hover, 5%)
));
}
&:active {
@include background (url(../images/icons/filter-icons.png) no-repeat -16px -17px,
linear-gradient(
lighten($gf_color_button_filter_hover, 5%),
darken($gf_color_button_filter_hover, 5%)
));
@include box-shadow(inset 0 1px 3px rgb(23, 24, 26), 0 1px 0 rgba(255, 255, 255, .6));
}
}
&.ss-gridfield-button-reset.ss-ui-button{
position:absolute;
right:$gf_grid_x*2 + 4;
top:$gf_grid_y*-2 - 4;
display:block;
text-indent:-9999em;
width:$gf_grid_x*2 - 2;
height:$gf_grid_y*2 + 4;
float:right;
border: {
radius:0px;
bottom-width:1px;
color:$gf_color_border_filter_button;
}
@include background (url(../images/icons/filter-icons.png) no-repeat 8px 5px,
linear-gradient(color-stops(
lighten($gf_color_button, 10%),
darken($gf_color_button, 5%)
))
);
&:hover {
@include background (url(../images/icons/filter-icons.png) no-repeat 8px -17px,
linear-gradient(
$gf_color_button_reset_hover,
darken($gf_color_button_reset_hover, 10%)
));
}
&:active {
@include background (url(../images/icons/filter-icons.png) no-repeat 8px -17px,
linear-gradient(
$gf_color_button_reset_hover,
darken($gf_color_button_reset_hover, 10%)
));
@include box-shadow(inset 0 1px 3px rgb(23, 24, 26), 0 1px 0 rgba(255, 255, 255, .6));
}
}
}
input {
&.ss-gridfield-sort {
padding: 2px;
&:focus {
@include box-shadow-none;
}
}
}
span.non-sortable {
padding:.4em 1em;
}
}
td {
border-right: 1px solid $gf_colour_border;
padding: 7px 12px;
padding: $gf_grid_x/2.5 $gf_grid_y;
color: $gf_colour_font;
&.bottom-all {
@include border-bottom-radius($gf_border_radius);

View File

@ -156,8 +156,11 @@
height: 0;
overflow: hidden;
clear: both;
margin-top: $grid-y;
iframe {
margin-top: $grid-y;
padding-top: $grid-y;
border-top: 1px solid $color-light-separator;
width: 100%;
}
}
@ -169,10 +172,6 @@
}
}
body.ss-uploadfield-edit-iframe {
padding: $grid-y*2 $grid-x*2;
}
.ss-upload {
.clear {
clear: both;

View File

@ -162,7 +162,7 @@ class SearchContext extends Object {
* @return SS_List
*/
public function getResults($searchParams, $sort = false, $limit = false) {
$searchParams = array_filter($searchParams, array($this,'clearEmptySearchFields'));
$searchParams = array_filter((array)$searchParams, array($this,'clearEmptySearchFields'));
// getQuery actually returns a DataList
return $this->getQuery($searchParams, $sort, $limit);

View File

@ -104,6 +104,13 @@ abstract class SearchFilter extends Object {
public function getName() {
return $this->name;
}
/**
* @param String
*/
public function setName($name) {
$this->name = $name;
}
/**
* The full name passed to the constructor,
@ -114,6 +121,13 @@ abstract class SearchFilter extends Object {
public function getFullName() {
return $this->fullName;
}
/**
* @param String
*/
public function setFullName($name) {
$this->fullName = $name;
}
/**
* Normalizes the field name to table mapping.

View File

@ -13,7 +13,6 @@ class Group extends DataObject {
"Code" => "Varchar",
"Locked" => "Boolean",
"Sort" => "Int",
"IPRestrictions" => "Text",
"HtmlEditorConfig" => "Varchar"
);
@ -62,10 +61,18 @@ class Group extends DataObject {
public function getCMSFields() {
Requirements::javascript(SAPPHIRE_DIR . '/javascript/PermissionCheckboxSetField.js');
$config = new GridFieldConfig_ManyManyEditor('FirstName', true, 20);
$config->addComponent(new GridFieldExporter());
$config = new GridFieldConfig();
$config->addComponent(new GridFieldTitle());
$configs = new GridFieldConfig_ManyManyEditor('FirstName', 20);
$components = $configs->getComponents();
foreach($components as $component) $config->addComponent($component);
$config->addComponents(new GridFieldExporter());
$config->getComponentByType('GridFieldRelationAdd')
->setResultsFormat('$Title ($Email)')->setSearchFields(array('FirstName', 'Surname', 'Email'));
$memberList = new GridField('Members','Members', $this->Members(), $config);
$memberList->addExtraClass('members_grid');
// @todo Implement permission checking on GridField
//$memberList->setPermissions(array('edit', 'delete', 'export', 'add', 'inlineadd'));
//$memberList->setPopupCaption(_t('SecurityAdmin.VIEWUSER', 'View User'));
@ -84,19 +91,6 @@ class Group extends DataObject {
'GroupID',
$this
)
),
new Tab('IPAddresses', _t('Security.IPADDRESSES', 'IP Addresses'),
new LiteralField("", _t('SecurityAdmin.IPADDRESSESHELP',"<p>You can restrict this group to a particular
IP address range (one range per line). <br />Ranges can be in any of the following forms: <br />
203.96.152.12<br />
203.96.152/24<br />
203.96/16<br />
203/8<br /><br />If you enter one or more IP address ranges in this box, then members will only get
the rights of being in this group if they log on from one of the valid IP addresses. It won't prevent
people from logging in. This is because the same user might have to log in to access parts of the
system without IP address restrictions.")),
new TextareaField("IPRestrictions", "IP Ranges", 10)
)
)
);
@ -172,7 +166,6 @@ class Group extends DataObject {
$labels['Code'] = _t('Group.Code', 'Group Code', PR_MEDIUM, 'Programmatical code identifying a group');
$labels['Locked'] = _t('Group.Locked', 'Locked?', PR_MEDIUM, 'Group is locked in the security administration area');
$labels['Sort'] = _t('Group.Sort', 'Sort Order');
$labels['IPRestrictions'] = _t('Group.IPRestrictions', 'IP Address Restrictions');
if($includerelations){
$labels['Parent'] = _t('Group.Parent', 'Parent Group', PR_MEDIUM, 'One group has one parent group');
$labels['Permissions'] = _t('Group.has_many_Permissions', 'Permissions', PR_MEDIUM, 'One group has many permissions');
@ -409,28 +402,6 @@ class Group extends DataObject {
return $filteredChildren;
}
/**
* Returns true if the given IP address is granted access to this group.
* For unrestricted groups, this always returns true.
*/
function allowedIPAddress($ip) {
if(!$this->IPRestrictions) return true;
if(!$ip) return false;
$ipPatterns = explode("\n", $this->IPRestrictions);
foreach($ipPatterns as $ipPattern) {
$ipPattern = trim($ipPattern);
if(preg_match('/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)$/', $ipPattern, $matches)) {
if($ip == $ipPattern) return true;
} else if(preg_match('/^([0-9]+\.[0-9]+\.[0-9]+)\/24$/', $ipPattern, $matches)
|| preg_match('/^([0-9]+\.[0-9]+)\/16$/', $ipPattern, $matches)
|| preg_match('/^([0-9]+)\/8$/', $ipPattern, $matches)) {
if(substr($ip, 0, strlen($matches[1])) == $matches[1]) return true;
}
}
return false;
}
/**
* Add default records to database.
*

View File

@ -948,14 +948,7 @@ class Member extends DataObject {
$groups = new Member_GroupSet('Group', 'Group_Members', 'GroupID', 'MemberID');
if($this->ID) $groups->setForeignID($this->ID);
// Filter out groups that aren't allowed from this IP
$ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null;
$disallowedGroups = array();
foreach($groups as $group) {
if(!$group->allowedIPAddress($ip)) $disallowedGroups[] = $groupID;
}
if($disallowedGroups) $group->where("\"Group\".\"ID\" NOT IN (" .
implode(',',$disallowedGroups) . ")");
$this->extend('updateGroups', $groups);
return $groups;
}
@ -1140,12 +1133,16 @@ class Member extends DataObject {
// Groups relation will get us into logical conflicts because
// Members are displayed within group edit form in SecurityAdmin
$fields->removeByName('Groups');
if(Permission::check('EDIT_PERMISSIONS')) {
$groupsField = new TreeMultiselectField('Groups', false, 'Group');
$fields->findOrMakeTab('Root.Groups', singleton('Group')->i18n_plural_name());
$fields->addFieldToTab('Root.Groups', $groupsField);
$groupsMap = DataList::create('Group')->map('ID', 'Breadcrumbs')->toArray();
asort($groupsMap);
$fields->addFieldToTab('Root.Main',
Object::create('CheckboxSetField', 'Groups', singleton('Group')->i18n_plural_name())
->setTemplate('CheckboxSetField_Select')
->setSource($groupsMap)
);
// Add permission field (readonly to avoid complicated group assignment logic).
// This should only be available for existing records, as new records start
// with no permissions until they have a group assignment anyway.

View File

@ -1,15 +0,0 @@
<?php
/**
* This {@link PasswordValidator} implements the NZ E-Government Guidelines for passwords
* @package sapphire
* @subpackage security
*/
class NZGovtPasswordValidator extends PasswordValidator {
function __construct() {
parent::__construct();
$this->minLength(7);
$this->checkHistoricalPasswords(6);
$this->characterStrength(3, array('lowercase','uppercase','digits','punctuation'));
}
}

View File

@ -1,4 +1,4 @@
<tr>
<tr class="filter-header">
<% control Fields %>
<th class="extra"><span>$Field</span></th>
<% end_control %>

View File

@ -1,3 +1,3 @@
<tr class="title">
<th colspan="$ColumnCount"><h2>$Title</h2> <a href="$NewLink" class="action ss-ui-action-constructive ss-ui-button ui-button ui-widget ui-state-default ui-corner-all new new-link">Add new</a></th>
<th colspan="$ColumnCount"><h2>$Title</h2> <a href="$NewLink" class="action ss-ui-action-constructive ss-ui-button ui-button ui-widget ui-state-default ui-corner-all new new-link"><% _t('GridField.AddNew', 'Add New') %></a></th>
</tr>

View File

@ -0,0 +1,11 @@
<%-- Renders a CheckboxField with $multiple=true as a select element which can save into relations.--%>
<%-- TODO Make relation saving available on ListboxField --%>
<select id="$ID" class="$extraClass" name="$Name[]" multiple="true">
<% if Options.Count %>
<% control Options %>
<option class="$Class" value="$Value"<% if isChecked %> selected="selected"<% end_if %>>
$Title
</option>
<% end_control %>
<% end_if %>
</select>

View File

@ -65,7 +65,7 @@ class CheckboxSetFieldTest extends SapphireTest {
);
}
function testSaveWithArrayValueSet() {
function testSaveWithAssociativeArrayValueSet() {
$article = $this->objFromFixture('CheckboxSetFieldTest_Article', 'articlewithouttags');
$articleWithTags = $this->objFromFixture('CheckboxSetFieldTest_Article', 'articlewithtags');
$tag1 = $this->objFromFixture('CheckboxSetFieldTest_Tag', 'tag1');
@ -98,6 +98,40 @@ class CheckboxSetFieldTest extends SapphireTest {
'Data shold be saved into CheckboxSetField manymany relation table on the "left end"'
);
}
function testSaveWithNumericArrayValueSet() {
$article = $this->objFromFixture('CheckboxSetFieldTest_Article', 'articlewithouttags');
$articleWithTags = $this->objFromFixture('CheckboxSetFieldTest_Article', 'articlewithtags');
$tag1 = $this->objFromFixture('CheckboxSetFieldTest_Tag', 'tag1');
$tag2 = $this->objFromFixture('CheckboxSetFieldTest_Tag', 'tag2');
/* Create a CheckboxSetField with 2 items selected. Note that the array is in the format (key) => (selected) */
$field = new CheckboxSetField("Tags", "Test field", DataObject::get("CheckboxSetFieldTest_Tag")->map());
$field->setValue(array(
$tag1->ID,
$tag2->ID
));
/* Saving should work */
$field->saveInto($article);
$this->assertEquals(
array($tag1->ID,$tag2->ID),
DB::query("SELECT \"CheckboxSetFieldTest_TagID\"
FROM \"CheckboxSetFieldTest_Article_Tags\"
WHERE \"CheckboxSetFieldTest_Article_Tags\".\"CheckboxSetFieldTest_ArticleID\" = $article->ID
")->column(),
'Data shold be saved into CheckboxSetField manymany relation table on the "right end"'
);
$this->assertEquals(
array($articleWithTags->ID,$article->ID),
DB::query("SELECT \"CheckboxSetFieldTest_ArticleID\"
FROM \"CheckboxSetFieldTest_Article_Tags\"
WHERE \"CheckboxSetFieldTest_Article_Tags\".\"CheckboxSetFieldTest_TagID\" = $tag1->ID
")->column(),
'Data shold be saved into CheckboxSetField manymany relation table on the "left end"'
);
}
function testLoadDataFromObject() {
$article = $this->objFromFixture('CheckboxSetFieldTest_Article', 'articlewithouttags');

View File

@ -3,17 +3,8 @@ CheckboxSetFieldTest_Tag:
Title: Tag 1
tag2:
Title: Tag 2
CheckboxSetFieldTest_Article:
articlewithouttags:
Content: Article 1
articlewithtags:
Content: Article 2
Tags: =>CheckboxSetFieldTest_Tag.tag1,=>CheckboxSetFieldTest_Tag.tag2
CheckboxSetFieldTest_Tag:
tag1:
Title: Tag 1
tag2:
Title: Tag 2
tag3:
Title: Tag 3
CheckboxSetFieldTest_Article:
articlewithouttags:
Content: Article 1

View File

@ -370,4 +370,22 @@ class GridFieldTest_Component implements GridField_ColumnProvider, GridField_Act
}
}
class GridFieldTest_Team extends DataObject implements TestOnly {
static $db = array(
'Name' => 'Varchar',
'City' => 'Varchar'
);
static $many_many = array('Players' => 'GridFieldTest_Player');
}
class GridFieldTest_Player extends DataObject implements TestOnly {
static $db = array(
'Name' => 'Varchar',
'Email' => 'Varchar',
);
static $belongs_many_many = array('Teams' => 'GridFieldTest_Team');
}

View File

@ -0,0 +1,82 @@
<?php
class GridFieldRelationAddTest extends FunctionalTest {
static $fixture_file = 'sapphire/tests/forms/gridfield/GridFieldTest.yml';
protected $extraDataObjects = array('GridFieldTest_Team', 'GridFieldTest_Player');
function testSearch() {
$team1 = $this->objFromFixture('GridFieldTest_Team', 'team1');
$team2 = $this->objFromFixture('GridFieldTest_Team', 'team2');
$response = $this->get('GridFieldRelationAddTest_Controller');
$this->assertFalse($response->isError());
$parser = new CSSContentParser($response->getBody());
$btns = $parser->getBySelector('.ss-gridfield #action_gridfield_relationfind');
$response = $this->post(
'GridFieldRelationAddTest_Controller/Form/field/testfield/search/Team 2',
array(
(string)$btns[0]['name'] => 1
)
);
$this->assertFalse($response->isError());
$result = Convert::json2array($response->getBody());
$this->assertEquals(1, count($result));
$this->assertEquals(array($team2->ID => 'Team 2'), $result);
$response = $this->post(
'GridFieldRelationAddTest_Controller/Form/field/testfield/search/Unknown',
array(
(string)$btns[0]['name'] => 1
)
);
$this->assertFalse($response->isError());
$result = Convert::json2array($response->getBody());
$this->assertFalse($result);
}
function testAdd() {
$team1 = $this->objFromFixture('GridFieldTest_Team', 'team1');
$team2 = $this->objFromFixture('GridFieldTest_Team', 'team2');
$response = $this->get('GridFieldRelationAddTest_Controller');
$this->assertFalse($response->isError());
$parser = new CSSContentParser($response->getBody());
$items = $parser->getBySelector('.ss-gridfield .ss-gridfield-items .ss-gridfield-item');
$this->assertEquals(1, count($items));
$this->assertEquals($team1->ID, (int)$items[0]['data-id']);
$btns = $parser->getBySelector('.ss-gridfield #action_gridfield_relationadd');
$response = $this->post(
'GridFieldRelationAddTest_Controller/Form/field/testfield',
array(
'relationID' => $team2->ID,
(string)$btns[0]['name'] => 1
)
);
$this->assertFalse($response->isError());
$parser = new CSSContentParser($response->getBody());
$items = $parser->getBySelector('.ss-gridfield .ss-gridfield-items .ss-gridfield-item');
$this->assertEquals(2, count($items));
$this->assertEquals($team1->ID, (int)$items[0]['data-id']);
$this->assertEquals($team2->ID, (int)$items[1]['data-id']);
}
}
class GridFieldRelationAddTest_Controller extends Controller implements TestOnly {
protected $template = 'BlankPage';
function Form() {
$player = DataObject::get('GridFieldTest_Player')->find('Email', 'player1@test.com');
$config = GridFieldConfig::create()->addComponents(
$relationComponent = new GridFieldRelationAdd('Name'),
new GridFieldDefaultColumns()
);
$field = new GridField('testfield', 'testfield', $player->Teams(), $config);
return new Form($this, 'Form', new FieldList($field), new FieldList());
}
}

View File

@ -0,0 +1,18 @@
GridFieldTest_Team:
team1:
Name: Team 1
City: Cologne
team2:
Name: Team 2
City: Wellington
team3:
Name: Team 3
City: Auckland
team4:
Name: Team 4
City: Melbourne
GridFieldTest_Player:
player1_team1:
Name: Player 1
Email: player1@test.com
Teams: =>GridFieldTest_Team.team1

View File

@ -150,6 +150,17 @@ class HierarchyTest extends SapphireTest {
$this->assertNotContains("Obj 2b", $children);
}
function testBreadcrumbs() {
$obj1 = $this->objFromFixture('HierarchyTest_Object', 'obj1');
$obj2 = $this->objFromFixture('HierarchyTest_Object', 'obj2');
$obj2a = $this->objFromFixture('HierarchyTest_Object', 'obj2a');
$obj2aa = $this->objFromFixture('HierarchyTest_Object', 'obj2aa');
$this->assertEquals('Obj 1', $obj1->getBreadcrumbs());
$this->assertEquals('Obj 2 &raquo; Obj 2a', $obj2a->getBreadcrumbs());
$this->assertEquals('Obj 2 &raquo; Obj 2a &raquo; Obj 2aa', $obj2aa->getBreadcrumbs());
}
}
class HierarchyTest_Object extends DataObject implements TestOnly {

View File

@ -179,7 +179,7 @@ class MemberTest extends FunctionalTest {
$member = $this->objFromFixture('Member', 'test');
$this->assertNotNull($member);
Member::set_password_validator(new NZGovtPasswordValidator());
Member::set_password_validator(new MemberTest_PasswordValidator());
// BAD PASSWORDS
@ -617,4 +617,14 @@ class MemberTest_EditingAllowedDeletingDeniedExtension extends DataExtension imp
return false;
}
}
class MemberTest_PasswordValidator extends PasswordValidator {
function __construct() {
parent::__construct();
$this->minLength(7);
$this->checkHistoricalPasswords(6);
$this->characterStrength(3, array('lowercase','uppercase','digits','punctuation'));
}
}

View File

@ -363,6 +363,65 @@ after')
function assertEqualIgnoringWhitespace($a, $b) {
$this->assertEquals(preg_replace('/\s+/', '', $a), preg_replace('/\s+/', '', $b));
}
/**
* See {@link ViewableDataTest} for more extensive casting tests,
* this test just ensures that basic casting is correctly applied during template parsing.
*/
function testCastingHelpers() {
$vd = new SSViewerTest_ViewableData();
$vd->TextValue = '<b>html</b>';
$vd->HTMLValue = '<b>html</b>';
$vd->UncastedValue = '<b>html</b>';
// Value casted as "Text"
$this->assertEquals(
'&lt;b&gt;html&lt;/b&gt;',
$t = SSViewer::fromString('$TextValue')->process($vd)
);
$this->assertEquals(
'<b>html</b>',
$t = SSViewer::fromString('$TextValue.RAW')->process($vd)
);
$this->assertEquals(
'&lt;b&gt;html&lt;/b&gt;',
$t = SSViewer::fromString('$TextValue.XML')->process($vd)
);
// Value casted as "HTMLText"
$this->assertEquals(
'<b>html</b>',
$t = SSViewer::fromString('$HTMLValue')->process($vd)
);
$this->assertEquals(
'<b>html</b>',
$t = SSViewer::fromString('$HTMLValue.RAW')->process($vd)
);
$this->assertEquals(
'&lt;b&gt;html&lt;/b&gt;',
$t = SSViewer::fromString('$HTMLValue.XML')->process($vd)
);
// Uncasted value (falls back to ViewableData::$default_cast="HTMLText")
$vd = new SSViewerTest_ViewableData(); // TODO Fix caching
$vd->UncastedValue = '<b>html</b>';
$this->assertEquals(
'<b>html</b>',
$t = SSViewer::fromString('$UncastedValue')->process($vd)
);
$vd = new SSViewerTest_ViewableData(); // TODO Fix caching
$vd->UncastedValue = '<b>html</b>';
$this->assertEquals(
'<b>html</b>',
$t = SSViewer::fromString('$UncastedValue.RAW')->process($vd)
);
$vd = new SSViewerTest_ViewableData(); // TODO Fix caching
$vd->UncastedValue = '<b>html</b>';
$this->assertEquals(
'&lt;b&gt;html&lt;/b&gt;',
$t = SSViewer::fromString('$UncastedValue.XML')->process($vd)
);
}
/**
* Test $Up works when the scope $Up refers to was entered with a "with" block
@ -677,6 +736,12 @@ class SSViewerTestFixture extends ViewableData {
}
class SSViewerTest_ViewableData extends ViewableData implements TestOnly {
public static $casting = array(
'TextValue' => 'Text',
'HTMLValue' => 'HTMLText'
);
function methodWithOneArgument($arg1) {
return "arg1:{$arg1}";
}

View File

@ -1,5 +1,8 @@
<?php
/**
* See {@link SSViewerTest->testCastingHelpers()} for more tests related to casting and ViewableData behaviour,
* from a template-parsing perspective.
*
* @package sapphire
* @subpackage tests
*/

View File

@ -1,12 +1,12 @@
/*!
* jQuery Form Plugin
* version: 2.63 (29-JAN-2011)
* version: 2.96 (16-FEB-2012)
* @requires jQuery v1.3.2 or later
*
* Examples and documentation at: http://malsup.com/jquery/form/
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*/
;(function($) {
@ -14,7 +14,7 @@
Usage Note:
-----------
Do not use both ajaxSubmit and ajaxForm on the same form. These
functions are intended to be exclusive. Use ajaxSubmit if you want
functions are mutually exclusive. Use ajaxSubmit if you want
to bind your own submit handler to the form. For example,
$(document).ready(function() {
@ -34,7 +34,15 @@
target: '#output'
});
});
You can also use ajaxForm with delegation (requires jQuery v1.7+), so the
form does not have to exist when you invoke ajaxForm:
$('#myForm').ajaxForm({
delegation: true,
target: '#output'
});
When using ajaxForm, the ajaxSubmit function will be invoked for you
at the appropriate time.
*/
@ -49,22 +57,26 @@ $.fn.ajaxSubmit = function(options) {
log('ajaxSubmit: skipping submit process - no element selected');
return this;
}
var method, action, url, $form = this;
if (typeof options == 'function') {
options = { success: options };
}
var action = this.attr('action');
var url = (typeof action === 'string') ? $.trim(action) : '';
method = this.attr('method');
action = this.attr('action');
url = (typeof action === 'string') ? $.trim(action) : '';
url = url || window.location.href || '';
if (url) {
// clean url (don't include hash vaue)
url = (url.match(/^([^#]+)/)||[])[1];
}
url = url || window.location.href || '';
options = $.extend(true, {
url: url,
type: this[0].getAttribute('method') || 'GET', // IE7 massage (see issue 57)
success: $.ajaxSettings.success,
type: method || 'GET',
iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
}, options);
@ -83,21 +95,15 @@ $.fn.ajaxSubmit = function(options) {
return this;
}
var n,v,a = this.formToArray(options.semantic);
var traditional = options.traditional;
if ( traditional === undefined ) {
traditional = $.ajaxSettings.traditional;
}
var qx,n,v,a = this.formToArray(options.semantic);
if (options.data) {
options.extraData = options.data;
for (n in options.data) {
if(options.data[n] instanceof Array) {
for (var k in options.data[n]) {
a.push( { name: n, value: options.data[n][k] } );
}
}
else {
v = options.data[n];
v = $.isFunction(v) ? v() : v; // if value is fn, invoke it
a.push( { name: n, value: v } );
}
}
qx = $.param(options.data, traditional);
}
// give pre-submit callback an opportunity to abort the submit
@ -113,8 +119,10 @@ $.fn.ajaxSubmit = function(options) {
return this;
}
var q = $.param(a);
var q = $.param(a, traditional);
if (qx) {
q = ( q ? (q + '&' + qx) : qx );
}
if (options.type.toUpperCase() == 'GET') {
options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
options.data = null; // data is null for 'get'
@ -123,12 +131,12 @@ $.fn.ajaxSubmit = function(options) {
options.data = q; // data is the query string for 'post'
}
var $form = this, callbacks = [];
var callbacks = [];
if (options.resetForm) {
callbacks.push(function() { $form.resetForm(); });
}
if (options.clearForm) {
callbacks.push(function() { $form.clearForm(); });
callbacks.push(function() { $form.clearForm(options.includeHidden); });
}
// perform a load on the target only if dataType is not provided
@ -144,41 +152,116 @@ $.fn.ajaxSubmit = function(options) {
}
options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
var context = options.context || options; // jQuery 1.4+ supports scope context
var context = options.context || options; // jQuery 1.4+ supports scope context
for (var i=0, max=callbacks.length; i < max; i++) {
callbacks[i].apply(context, [data, status, xhr || $form, $form]);
}
};
// are there files to upload?
var fileInputs = $('input:file', this).length > 0;
var fileInputs = $('input:file:enabled[value]', this); // [value] (issue #113)
var hasFileInputs = fileInputs.length > 0;
var mp = 'multipart/form-data';
var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
var fileAPI = !!(hasFileInputs && fileInputs.get(0).files && window.FormData);
log("fileAPI :" + fileAPI);
var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI;
// options.iframe allows user to force iframe mode
// 06-NOV-09: now defaulting to iframe mode if file input is detected
if (options.iframe !== false && (fileInputs || options.iframe || multipart)) {
// hack to fix Safari hang (thanks to Tim Molendijk for this)
// see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
if (options.closeKeepAlive) {
$.get(options.closeKeepAlive, fileUpload);
if (options.iframe !== false && (options.iframe || shouldUseFrame)) {
// hack to fix Safari hang (thanks to Tim Molendijk for this)
// see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
if (options.closeKeepAlive) {
$.get(options.closeKeepAlive, function() {
fileUploadIframe(a);
});
}
else {
fileUpload();
}
}
else {
else {
fileUploadIframe(a);
}
}
else if ((hasFileInputs || multipart) && fileAPI) {
options.progress = options.progress || $.noop;
fileUploadXhr(a);
}
else {
$.ajax(options);
}
// fire 'notify' event
this.trigger('form-submit-notify', [this, options]);
return this;
// XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)
function fileUploadXhr(a) {
var formdata = new FormData();
for (var i=0; i < a.length; i++) {
if (a[i].type == 'file')
continue;
formdata.append(a[i].name, a[i].value);
}
$form.find('input:file:enabled').each(function(){
var name = $(this).attr('name'), files = this.files;
if (name) {
for (var i=0; i < files.length; i++)
formdata.append(name, files[i]);
}
});
if (options.extraData) {
for (var k in options.extraData)
formdata.append(k, options.extraData[k])
}
options.data = null;
var s = $.extend(true, {}, $.ajaxSettings, options, {
contentType: false,
processData: false,
cache: false,
type: 'POST'
});
//s.context = s.context || s;
s.data = null;
var beforeSend = s.beforeSend;
s.beforeSend = function(xhr, o) {
o.data = formdata;
if(xhr.upload) { // unfortunately, jQuery doesn't expose this prop (http://bugs.jquery.com/ticket/10190)
xhr.upload.onprogress = function(event) {
o.progress(event.position, event.total);
};
}
if(beforeSend)
beforeSend.call(o, xhr, options);
};
$.ajax(s);
}
// fire 'notify' event
this.trigger('form-submit-notify', [this, options]);
return this;
// private function for handling file uploads (hat tip to YAHOO!)
function fileUpload() {
var form = $form[0];
function fileUploadIframe(a) {
var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
var useProp = !!$.fn.prop;
if (a) {
if ( useProp ) {
// ensure that every serialized input is still enabled
for (i=0; i < a.length; i++) {
el = $(form[a[i].name]);
el.prop('disabled', false);
}
} else {
for (i=0; i < a.length; i++) {
el = $(form[a[i].name]);
el.removeAttr('disabled');
}
};
}
if ($(':input[name=submit],:input[id=submit]', form).length) {
// if there is an input with a name or id of 'submit' then we won't be
@ -187,15 +270,25 @@ $.fn.ajaxSubmit = function(options) {
return;
}
var s = $.extend(true, {}, $.ajaxSettings, options);
s = $.extend(true, {}, $.ajaxSettings, options);
s.context = s.context || s;
var id = 'jqFormIO' + (new Date().getTime()), fn = '_'+id;
var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+ s.iframeSrc +'" />');
var io = $io[0];
id = 'jqFormIO' + (new Date().getTime());
if (s.iframeTarget) {
$io = $(s.iframeTarget);
n = $io.attr('name');
if (n == null)
$io.attr('name', id);
else
id = n;
}
else {
$io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
$io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
}
io = $io[0];
$io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
var xhr = { // mock object
xhr = { // mock object
aborted: 0,
responseText: null,
responseXML: null,
@ -204,13 +297,19 @@ $.fn.ajaxSubmit = function(options) {
getAllResponseHeaders: function() {},
getResponseHeader: function() {},
setRequestHeader: function() {},
abort: function() {
abort: function(status) {
var e = (status === 'timeout' ? 'timeout' : 'aborted');
log('aborting upload... ' + e);
this.aborted = 1;
$io.attr('src', s.iframeSrc); // abort op in progress
xhr.error = e;
s.error && s.error.call(s.context, xhr, e, status);
g && $.event.trigger("ajaxError", [xhr, s, e]);
s.complete && s.complete.call(s.context, xhr, e);
}
};
var g = s.global;
g = s.global;
// trigger ajax global events so that activity/block indicators work like normal
if (g && ! $.active++) {
$.event.trigger("ajaxStart");
@ -220,7 +319,7 @@ $.fn.ajaxSubmit = function(options) {
}
if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
if (s.global) {
if (s.global) {
$.active--;
}
return;
@ -229,12 +328,10 @@ $.fn.ajaxSubmit = function(options) {
return;
}
var timedOut = 0;
// add submitting element to data if we know it
var sub = form.clk;
sub = form.clk;
if (sub) {
var n = sub.name;
n = sub.name;
if (n && !sub.disabled) {
s.extraData = s.extraData || {};
s.extraData[n] = sub.value;
@ -244,6 +341,22 @@ $.fn.ajaxSubmit = function(options) {
}
}
}
var CLIENT_TIMEOUT_ABORT = 1;
var SERVER_ABORT = 2;
function getDoc(frame) {
var doc = frame.contentWindow ? frame.contentWindow.document : frame.contentDocument ? frame.contentDocument : frame.document;
return doc;
}
// Rails CSRF hack (thanks to Yvan Barthelemy)
var csrf_token = $('meta[name=csrf-token]').attr('content');
var csrf_param = $('meta[name=csrf-param]').attr('content');
if (csrf_param && csrf_token) {
s.extraData = s.extraData || {};
s.extraData[csrf_param] = csrf_token;
}
// take a breath so that pending repaints get some cpu time before the upload starts
function doSubmit() {
@ -252,15 +365,15 @@ $.fn.ajaxSubmit = function(options) {
// update form attrs in IE friendly way
form.setAttribute('target',id);
if (form.getAttribute('method') != 'POST') {
if (!method) {
form.setAttribute('method', 'POST');
}
if (form.getAttribute('action') != s.url) {
if (a != s.url) {
form.setAttribute('action', s.url);
}
// ie borks in some cases when setting encoding
if (! s.skipEncodingOverride) {
if (! s.skipEncodingOverride && (!method || /post/i.test(method))) {
$form.attr({
encoding: 'multipart/form-data',
enctype: 'multipart/form-data'
@ -269,7 +382,23 @@ $.fn.ajaxSubmit = function(options) {
// support timout
if (s.timeout) {
setTimeout(function() { timedOut = true; cb(); }, s.timeout);
timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout);
}
// look for server aborts
function checkState() {
try {
var state = getDoc(io).readyState;
log('state = ' + state);
if (state.toLowerCase() == 'uninitialized')
setTimeout(checkState,50);
}
catch(e) {
log('Server abort: ' , e, ' (', e.name, ')');
cb(SERVER_ABORT);
timeoutHandle && clearTimeout(timeoutHandle);
timeoutHandle = undefined;
}
}
// add "extra" data to form if provided in options
@ -278,14 +407,17 @@ $.fn.ajaxSubmit = function(options) {
if (s.extraData) {
for (var n in s.extraData) {
extraInputs.push(
$('<input type="hidden" name="'+n+'" value="'+s.extraData[n]+'" />')
$('<input type="hidden" name="'+n+'">').attr('value',s.extraData[n])
.appendTo(form)[0]);
}
}
// add iframe to doc and submit the form
$io.appendTo('body');
io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
if (!s.iframeTarget) {
// add iframe to doc and submit the form
$io.appendTo('body');
io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
}
setTimeout(checkState,15);
form.submit();
}
finally {
@ -306,18 +438,37 @@ $.fn.ajaxSubmit = function(options) {
else {
setTimeout(doSubmit, 10); // this lets dom updates render
}
var data, doc, domCheckCount = 50;
function cb() {
doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
if (!doc || doc.location.href == s.iframeSrc) {
// response not received yet
var data, doc, domCheckCount = 50, callbackProcessed;
function cb(e) {
if (xhr.aborted || callbackProcessed) {
return;
}
try {
doc = getDoc(io);
}
catch(ex) {
log('cannot access response document: ', ex);
e = SERVER_ABORT;
}
if (e === CLIENT_TIMEOUT_ABORT && xhr) {
xhr.abort('timeout');
return;
}
else if (e == SERVER_ABORT && xhr) {
xhr.abort('server abort');
return;
}
io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);
var ok = true;
if (!doc || doc.location.href == s.iframeSrc) {
// response not received yet
if (!timedOut)
return;
}
io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);
var status = 'success', errMsg;
try {
if (timedOut) {
throw 'timeout';
@ -339,69 +490,99 @@ $.fn.ajaxSubmit = function(options) {
}
//log('response detected');
xhr.responseText = doc.body ? doc.body.innerHTML : doc.documentElement ? doc.documentElement.innerHTML : null;
var docRoot = doc.body ? doc.body : doc.documentElement;
xhr.responseText = docRoot ? docRoot.innerHTML : null;
xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
if (isXml)
s.dataType = 'xml';
xhr.getResponseHeader = function(header){
var headers = {'content-type': s.dataType};
return headers[header];
};
// support for XHR 'status' & 'statusText' emulation :
if (docRoot) {
xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
}
var scr = /(json|script)/.test(s.dataType);
var dt = (s.dataType || '').toLowerCase();
var scr = /(json|script|text)/.test(dt);
if (scr || s.textarea) {
// see if user embedded response in textarea
var ta = doc.getElementsByTagName('textarea')[0];
if (ta) {
xhr.responseText = ta.value;
// support for XHR 'status' & 'statusText' emulation :
xhr.status = Number( ta.getAttribute('status') ) || xhr.status;
xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
}
else if (scr) {
// account for browsers injecting pre around json response
var pre = doc.getElementsByTagName('pre')[0];
var b = doc.getElementsByTagName('body')[0];
if (pre) {
xhr.responseText = pre.textContent;
xhr.responseText = pre.textContent ? pre.textContent : pre.innerText;
}
else if (b) {
xhr.responseText = b.innerHTML;
xhr.responseText = b.textContent ? b.textContent : b.innerText;
}
}
}
}
else if (s.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
else if (dt == 'xml' && !xhr.responseXML && xhr.responseText != null) {
xhr.responseXML = toXml(xhr.responseText);
}
data = httpData(xhr, s.dataType, s);
try {
data = httpData(xhr, dt, s);
}
catch (e) {
status = 'parsererror';
xhr.error = errMsg = (e || status);
}
}
catch(e){
log('error caught:',e);
ok = false;
xhr.error = e;
s.error.call(s.context, xhr, 'error', e);
g && $.event.trigger("ajaxError", [xhr, s, e]);
catch (e) {
log('error caught: ',e);
status = 'error';
xhr.error = errMsg = (e || status);
}
if (xhr.aborted) {
log('upload aborted');
ok = false;
status = null;
}
if (xhr.status) { // we've set xhr.status
status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
}
// ordering of these callbacks/triggers is odd, but that's how $.ajax does it
if (ok) {
s.success.call(s.context, data, 'success', xhr);
if (status === 'success') {
s.success && s.success.call(s.context, data, 'success', xhr);
g && $.event.trigger("ajaxSuccess", [xhr, s]);
}
else if (status) {
if (errMsg == undefined)
errMsg = xhr.statusText;
s.error && s.error.call(s.context, xhr, status, errMsg);
g && $.event.trigger("ajaxError", [xhr, s, errMsg]);
}
g && $.event.trigger("ajaxComplete", [xhr, s]);
if (g && ! --$.active) {
$.event.trigger("ajaxStop");
}
s.complete && s.complete.call(s.context, xhr, ok ? 'success' : 'error');
s.complete && s.complete.call(s.context, xhr, status);
callbackProcessed = true;
if (s.timeout)
clearTimeout(timeoutHandle);
// clean up
setTimeout(function() {
$io.removeData('form-plugin-onload');
$io.remove();
if (!s.iframeTarget)
$io.remove();
xhr.responseXML = null;
}, 100);
}
@ -420,8 +601,9 @@ $.fn.ajaxSubmit = function(options) {
var parseJSON = $.parseJSON || function(s) {
return window['eval']('(' + s + ')');
};
var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
var ct = xhr.getResponseHeader('content-type') || '',
xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
data = xml ? xhr.responseXML : xhr.responseText;
@ -460,8 +642,11 @@ $.fn.ajaxSubmit = function(options) {
* the form itself.
*/
$.fn.ajaxForm = function(options) {
options = options || {};
options.delegation = options.delegation && $.isFunction($.fn.on);
// in jQuery 1.3+ we can fix mistakes with the ready state
if (this.length === 0) {
if (!options.delegation && this.length === 0) {
var o = { s: this.selector, c: this.context };
if (!$.isReady && o.s) {
log('DOM not ready, queuing ajaxForm');
@ -474,43 +659,61 @@ $.fn.ajaxForm = function(options) {
log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
return this;
}
return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) {
if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
e.preventDefault();
$(this).ajaxSubmit(options);
}
}).bind('click.form-plugin', function(e) {
var target = e.target;
var $el = $(target);
if (!($el.is(":submit,input:image"))) {
// is this a child element of the submit el? (ex: a span within a button)
var t = $el.closest(':submit');
if (t.length == 0) {
return;
}
target = t[0];
}
var form = this;
form.clk = target;
if (target.type == 'image') {
if (e.offsetX != undefined) {
form.clk_x = e.offsetX;
form.clk_y = e.offsetY;
} else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
var offset = $el.offset();
form.clk_x = e.pageX - offset.left;
form.clk_y = e.pageY - offset.top;
} else {
form.clk_x = e.pageX - target.offsetLeft;
form.clk_y = e.pageY - target.offsetTop;
}
}
// clear form vars
setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
});
if ( options.delegation ) {
$(document)
.off('submit.form-plugin', this.selector, doAjaxSubmit)
.off('click.form-plugin', this.selector, captureSubmittingElement)
.on('submit.form-plugin', this.selector, options, doAjaxSubmit)
.on('click.form-plugin', this.selector, options, captureSubmittingElement);
return this;
}
return this.ajaxFormUnbind()
.bind('submit.form-plugin', options, doAjaxSubmit)
.bind('click.form-plugin', options, captureSubmittingElement);
};
// private event handlers
function doAjaxSubmit(e) {
var options = e.data;
if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
e.preventDefault();
$(this).ajaxSubmit(options);
}
}
function captureSubmittingElement(e) {
var target = e.target;
var $el = $(target);
if (!($el.is(":submit,input:image"))) {
// is this a child element of the submit el? (ex: a span within a button)
var t = $el.closest(':submit');
if (t.length == 0) {
return;
}
target = t[0];
}
var form = this;
form.clk = target;
if (target.type == 'image') {
if (e.offsetX != undefined) {
form.clk_x = e.offsetX;
form.clk_y = e.offsetY;
} else if (typeof $.fn.offset == 'function') {
var offset = $el.offset();
form.clk_x = e.pageX - offset.left;
form.clk_y = e.pageY - offset.top;
} else {
form.clk_x = e.pageX - target.offsetLeft;
form.clk_y = e.pageY - target.offsetTop;
}
}
// clear form vars
setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
};
// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
$.fn.ajaxFormUnbind = function() {
return this.unbind('submit.form-plugin click.form-plugin');
@ -538,7 +741,7 @@ $.fn.formToArray = function(semantic) {
if (!els) {
return a;
}
var i,j,n,v,el,max,jmax;
for(i=0, max=els.length; i < max; i++) {
el = els[i];
@ -550,7 +753,7 @@ $.fn.formToArray = function(semantic) {
if (semantic && form.clk && el.type == "image") {
// handle image inputs on the fly when semantic == true
if(!el.disabled && form.clk == el) {
a.push({name: n, value: $(el).val()});
a.push({name: n, value: $(el).val(), type: el.type });
a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
}
continue;
@ -563,7 +766,7 @@ $.fn.formToArray = function(semantic) {
}
}
else if (v !== null && typeof v != 'undefined') {
a.push({name: n, value: v});
a.push({name: n, value: v, type: el.type});
}
}
@ -649,7 +852,7 @@ $.fn.fieldSerialize = function(successful) {
* for each element is returned.
*
* Note: This method *always* returns an array. If no valid value can be determined the
* array will be empty, otherwise it will contain one or more values.
* array will be empty, otherwise it will contain one or more values.
*/
$.fn.fieldValue = function(successful) {
for (var val=[], i=0, max=this.length; i < max; i++) {
@ -713,19 +916,20 @@ $.fieldValue = function(el, successful) {
* - inputs of type submit, button, reset, and hidden will *not* be effected
* - button elements will *not* be effected
*/
$.fn.clearForm = function() {
$.fn.clearForm = function(includeHidden) {
return this.each(function() {
$('input,select,textarea', this).clearFields();
$('input,select,textarea', this).clearFields(includeHidden);
});
};
/**
* Clears the selected form elements.
*/
$.fn.clearFields = $.fn.clearInputs = function() {
$.fn.clearFields = $.fn.clearInputs = function(includeHidden) {
var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list
return this.each(function() {
var t = this.type, tag = this.tagName.toLowerCase();
if (t == 'text' || t == 'password' || tag == 'textarea') {
if (re.test(t) || tag == 'textarea' || (includeHidden && /hidden/.test(t)) ) {
this.value = '';
}
else if (t == 'checkbox' || t == 'radio') {
@ -786,18 +990,20 @@ $.fn.selected = function(select) {
});
};
// expose debug var
$.fn.ajaxSubmit.debug = false;
// helper fn for console logging
// set $.fn.ajaxSubmit.debug to true to enable debug logging
function log() {
if ($.fn.ajaxSubmit.debug) {
var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
if (window.console && window.console.log) {
window.console.log(msg);
}
else if (window.opera && window.opera.postError) {
window.opera.postError(msg);
}
if (!$.fn.ajaxSubmit.debug)
return;
var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
if (window.console && window.console.log) {
window.console.log(msg);
}
else if (window.opera && window.opera.postError) {
window.opera.postError(msg);
}
};
})(jQuery);
})(jQuery);