MDL-39814 actionmenu: improved alignment, constraint handling, and accessibility

This commit is contained in:
Sam Hemelryk 2013-07-18 10:42:11 +12:00
parent e5de4933b0
commit 3665af78ca
13 changed files with 533 additions and 219 deletions

View File

@ -1804,7 +1804,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
(($mod->course == $COURSE->id && course_ajax_enabled($COURSE)) ||
($mod->course == SITEID && course_ajax_enabled($SITE)))) {
// we will not display link if we are on some other-course page (where we should not see this module anyway)
$actions['title'] = new action_menu_secondary_action(
$actions['title'] = new action_menu_link_secondary(
new moodle_url($baseurl, array('update' => $mod->id)),
new pix_icon('t/editstring', $str->edittitle, 'moodle', array('class' => 'iconsmall visibleifjs', 'title' => '')),
$str->edittitle,
@ -1826,7 +1826,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
if ($indent > 0) {
$hiddenclass = '';
}
$actions['moveleft'] = new action_menu_secondary_action(
$actions['moveleft'] = new action_menu_link_secondary(
new moodle_url($baseurl, array('id' => $mod->id, 'indent' => '-1')),
new pix_icon($leftarrow, $str->moveleft, 'moodle', array('class' => 'iconsmall', 'title' => '')),
$str->moveleft,
@ -1836,7 +1836,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
if ($indent >= 0) {
$hiddenclass = '';
}
$actions['moveright'] = new action_menu_secondary_action(
$actions['moveright'] = new action_menu_link_secondary(
new moodle_url($baseurl, array('id' => $mod->id, 'indent' => '1')),
new pix_icon($rightarrow, $str->moveright, 'moodle', array('class' => 'iconsmall', 'title' => '')),
$str->moveright,
@ -1846,7 +1846,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
// Move.
if ($hasmanageactivities) {
$actions['move'] = new action_menu_primary_action(
$actions['move'] = new action_menu_link_primary(
new moodle_url($baseurl, array('copy' => $mod->id)),
new pix_icon('t/move', $str->move, 'moodle', array('class' => 'iconsmall', 'title' => '')),
$str->move,
@ -1856,7 +1856,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
// Update.
if ($hasmanageactivities) {
$actions['update'] = new action_menu_secondary_action(
$actions['update'] = new action_menu_link_secondary(
new moodle_url($baseurl, array('update' => $mod->id)),
new pix_icon('t/edit', $str->update, 'moodle', array('class' => 'iconsmall', 'title' => '')),
$str->update,
@ -1868,7 +1868,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
// Note that restoring on front page is never allowed.
if ($mod->course != SITEID && has_all_capabilities($dupecaps, $coursecontext) &&
plugin_supports('mod', $mod->modname, FEATURE_BACKUP_MOODLE2)) {
$actions['duplicate'] = new action_menu_secondary_action(
$actions['duplicate'] = new action_menu_link_secondary(
new moodle_url($baseurl, array('duplicate' => $mod->id)),
new pix_icon('t/copy', $str->duplicate, 'moodle', array('class' => 'iconsmall', 'title' => '')),
$str->duplicate,
@ -1878,7 +1878,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
// Delete.
if ($hasmanageactivities) {
$actions['delete'] = new action_menu_secondary_action(
$actions['delete'] = new action_menu_link_secondary(
new moodle_url($baseurl, array('delete' => $mod->id)),
new pix_icon('t/delete', $str->delete, 'moodle', array('class' => 'iconsmall', 'title' => '')),
$str->delete,
@ -1889,14 +1889,14 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
// Hide/Show.
if (has_capability('moodle/course:activityvisibility', $modcontext)) {
if ($mod->visible) {
$actions['hide'] = new action_menu_primary_action(
$actions['hide'] = new action_menu_link_primary(
new moodle_url($baseurl, array('hide' => $mod->id)),
new pix_icon('t/hide', $str->hide, 'moodle', array('class' => 'iconsmall', 'title' => '')),
$str->hide,
array('class' => 'editing_hide', 'data-action' => 'hide')
);
} else {
$actions['show'] = new action_menu_primary_action(
$actions['show'] = new action_menu_link_primary(
new moodle_url($baseurl, array('show' => $mod->id)),
new pix_icon('t/show', $str->show, 'moodle', array('class' => 'iconsmall', 'title' => '')),
$str->show,
@ -1932,7 +1932,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
$groupimage = 't/groupn';
}
if (!$mod->coursegroupmodeforce) {
$actions[$actionname] = new action_menu_primary_action(
$actions[$actionname] = new action_menu_link_primary(
new moodle_url($baseurl, array('id' => $mod->id, 'groupmode' => $nextgroupmode)),
new pix_icon($groupimage, $grouptitle, 'moodle', array('class' => 'iconsmall', 'title' => '')),
$grouptitle,
@ -1945,7 +1945,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
// Assign.
if (has_capability('moodle/role:assign', $modcontext)){
$actions['assign'] = new action_menu_secondary_action(
$actions['assign'] = new action_menu_link_secondary(
new moodle_url('/admin/roles/assign.php', array('contextid' => $modcontext->id)),
new pix_icon('t/assignroles', $str->assign, 'moodle', array('class' => 'iconsmall', 'title' => '')),
$str->assign,

View File

@ -349,8 +349,10 @@ class core_course_renderer extends plugin_renderer_base {
$menu = new action_menu();
$menu->set_owner_selector($ownerselector);
$menu->set_contraint('.course-content');
$menu->set_alignment(action_menu::TL, action_menu::TR);
foreach ($actions as $action) {
if ($action instanceof action_menu_action) {
if ($action instanceof action_menu_link) {
$action->add_class('cm-edit-action');
}
$menu->add($action);

View File

@ -721,7 +721,7 @@ YUI.add('moodle-course-toolboxes', function(Y) {
status = 'show'
}
if (visible != shouldbevisible) {
this.handle_resource_dim(buttonnode, buttonnode.get('activity'), status);
this.handle_resource_dim(buttonnode, buttonnode.getData('activity'), status);
}
}
}, {

View File

@ -1038,7 +1038,7 @@ class block_manager {
if ($this->page->user_can_edit_blocks()) {
// Move icon.
$str = new lang_string('moveblock', 'block', $blocktitle);
$controls[] = new action_menu_primary_action(
$controls[] = new action_menu_link_primary(
new moodle_url($actionurl, array('bui_moveid' => $block->instance->id)),
new pix_icon('t/move', $str, 'moodle', array('class' => 'iconsmall', 'title' => '')),
$str,
@ -1050,7 +1050,7 @@ class block_manager {
if ($this->page->user_can_edit_blocks() || $block->user_can_edit()) {
// Edit config icon - always show - needed for positioning UI.
$str = new lang_string('configureblock', 'block', $blocktitle);
$controls[] = new action_menu_primary_action(
$controls[] = new action_menu_link_primary(
new moodle_url($actionurl, array('bui_editid' => $block->instance->id)),
new pix_icon('t/edit', $str, 'moodle', array('class' => 'iconsmall', 'title' => '')),
$str,
@ -1062,7 +1062,7 @@ class block_manager {
if ($this->user_can_delete_block($block)) {
// Delete icon.
$str = new lang_string('deleteblock', 'block', $blocktitle);
$controls[] = new action_menu_secondary_action(
$controls[] = new action_menu_link_secondary(
new moodle_url($actionurl, array('bui_deleteid' => $block->instance->id)),
new pix_icon('t/delete', $str, 'moodle', array('class' => 'iconsmall', 'title' => '')),
$str,
@ -1083,7 +1083,7 @@ class block_manager {
$icon = new pix_icon('t/show', $str, 'moodle', array('class' => 'iconsmall', 'title' => ''));
$attributes = array('class' => 'editing_show');
}
$controls[] = new action_menu_primary_action($url, $icon, $str, $attributes);
$controls[] = new action_menu_link_primary($url, $icon, $str, $attributes);
}
// Assign roles icon.
@ -1098,7 +1098,7 @@ class block_manager {
'returnurl'=>$return));
// Delete icon.
$str = new lang_string('assignrolesinblock', 'block', $blocktitle);
$controls[] = new action_menu_secondary_action(
$controls[] = new action_menu_link_secondary(
$rolesurl,
new pix_icon('t/assignroles', $str, 'moodle', array('class' => 'iconsmall', 'title' => '')),
$str,

View File

@ -3044,6 +3044,30 @@ class tabtree extends tabobject {
*/
class action_menu implements renderable {
/**
* Top right alignment.
*/
const TL = 1;
/**
* Top right alignment.
*/
const TR = 2;
/**
* Top right alignment.
*/
const BL = 3;
/**
* Top right alignment.
*/
const BR = 4;
/**
* The instance number. This is unique to this instance of the action menu.
* @var int
*/
protected $instance = 0;
/**
@ -3093,14 +3117,16 @@ class action_menu implements renderable {
'data-enhance' => 'moodle-core-actionmenu'
);
$this->attributesprimary = array(
'id' => 'action-menu-'.$this->instance.'-primary',
'class' => 'primary'
'id' => 'action-menu-'.$this->instance.'-menubar',
'class' => 'menubar',
'role' => 'menubar'
);
$this->attributessecondary = array(
'id' => 'action-menu-'.$this->instance.'-secondary',
'class' => 'secondary',
'id' => 'action-menu-'.$this->instance.'-menu',
'class' => 'menu',
'data-rel' => 'menu-content',
'aria-labelledby' => 'action-menu-toggle-'.$this->instance,
'role' => 'menu'
);
foreach ($actions as $action) {
$this->add($action);
@ -3127,7 +3153,7 @@ class action_menu implements renderable {
* @param $action
*/
public function add($action) {
if ($action instanceof action_menu_action) {
if ($action instanceof action_menu_link) {
if ($action->primary) {
$this->add_primary_action($action);
} else {
@ -3143,18 +3169,24 @@ class action_menu implements renderable {
/**
* Adds a primary action to the action menu.
*
* @param action_link|string $action
* @param action_menu_link|action_link|pix_icon|string $action
*/
public function add_primary_action($action) {
if ($action instanceof action_link || $action instanceof pix_icon) {
$action->attributes['role'] = 'menuitem';
}
$this->primaryactions[] = $action;
}
/**
* Adds a secondary action to the action menu.
*
* @param action_link|string $action
* @param action_link|pix_icon|string $action
*/
public function add_secondary_action($action) {
if ($action instanceof action_link || $action instanceof pix_icon) {
$action->attributes['role'] = 'menuitem';
}
$this->secondaryactions[] = $action;
}
@ -3174,14 +3206,15 @@ class action_menu implements renderable {
't/contextmenu',
$title,
'moodle',
array('class' => 'iconsmall')
array('class' => 'iconsmall', 'title' => '')
);
$actions = $this->primaryactions;
$attributes = array(
'class' => 'toggle-display',
'title' => $title,
'id' => 'action-menu-toggle-'.$this->instance
'id' => 'action-menu-toggle-'.$this->instance,
'role' => 'menuitem'
);
$actions[] = html_writer::link('#', $pixicon, $attributes);
return $actions;
@ -3202,6 +3235,45 @@ class action_menu implements renderable {
public function set_owner_selector($selector) {
$this->attributes['data-owner'] = $selector;
}
/**
* Sets the alignment of the dialogue in relation to button used to toggle it.
*
* @param int $dialogue One of action_menu::TL, action_menu::TR, action_menu::BL, action_menu::BR.
* @param int $button One of action_menu::TL, action_menu::TR, action_menu::BL, action_menu::BR.
*/
public function set_alignment($dialogue, $button) {
$align = $this->get_align_string($dialogue) . '-' . $this->get_align_string($button);
$this->attributessecondary['data-align'] = $align;
}
/**
* Returns a string to describe the alignment.
*
* @param int $align One of action_menu::TL, action_menu::TR, action_menu::BL, action_menu::BR.
* @return string
*/
protected function get_align_string($align) {
switch ($align) {
case self::TL : return 'tl';
case self::TR : return 'tr';
case self::BL : return 'bl';
case self::BR : return 'br';
default : return 'tl';
}
}
/**
* Sets a constraint for the dialogue.
*
* The constraint is applied when the dialogue is shown and limits the display of the dialogue to within the
* element the constraint identifies.
*
* @param string $ancestorselector A snippet of CSS used to identify the ancestor to contrain the dialogue to.
*/
public function set_contraint($ancestorselector) {
$this->attributessecondary['data-constraint'] = $ancestorselector;
}
}
/**
@ -3212,7 +3284,7 @@ class action_menu implements renderable {
* @copyright 2013 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class action_menu_action implements renderable {
class action_menu_link extends action_link implements renderable {
/**
* True if this is a primary action. False if not.
@ -3220,30 +3292,6 @@ class action_menu_action implements renderable {
*/
public $primary = true;
/**
* The URL for the action.
* @var moodle_url
*/
public $url;
/**
* The icon to represent the action.
* @var pix_icon
*/
public $icon;
/**
* The text describing the action.
* @var string
*/
public $text;
/**
* An array of attributes for the action.
* @var array
*/
public $attributes;
/**
* Constructs the object.
*
@ -3254,35 +3302,11 @@ class action_menu_action implements renderable {
* @param array $attributes Any attribtues associated with the action.
*/
public function __construct(moodle_url $url, pix_icon $icon, $text, $primary = true, array $attributes = array()) {
$this->url = clone($url);
$this->icon = $icon;
$this->text = $text;
parent::__construct($url, $text, null, $attributes, $icon);
$this->primary = (bool)$primary;
$this->attributes = $attributes;
$this->add_class('menu-action');
$this->attributes['role'] = 'menuitem';
}
/**
* Adds a CSS class to this action link object
* @param string $class
*/
public function add_class($class) {
if (empty($this->attributes['class'])) {
$this->attributes['class'] = $class;
} else {
$this->attributes['class'] .= ' ' . $class;
}
}
/**
* Returns true if the specified class has been added to this link.
* @param string $class
* @return bool
*/
public function has_class($class) {
return strpos(' ' . $this->attributes['class'] . ' ', ' ' . $class . ' ') !== false;
}
}
/**
@ -3293,7 +3317,7 @@ class action_menu_action implements renderable {
* @copyright 2013 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class action_menu_primary_action extends action_menu_action {
class action_menu_link_primary extends action_menu_link {
/**
* Constructs the object.
*
@ -3315,7 +3339,7 @@ class action_menu_primary_action extends action_menu_action {
* @copyright 2013 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class action_menu_secondary_action extends action_menu_action {
class action_menu_link_secondary extends action_menu_link {
/**
* Constructs the object.
*

View File

@ -1047,6 +1047,10 @@ class core_renderer extends renderer_base {
/**
* Renders an action menu component.
*
* ARIA references:
* - http://www.w3.org/WAI/GL/wiki/Using_ARIA_menus
* - http://stackoverflow.com/questions/12279113/recommended-wai-aria-implementation-for-navigation-bar-menu
*
* @param action_menu $menu
* @return string HTML
*/
@ -1054,31 +1058,41 @@ class core_renderer extends renderer_base {
$menu->initialise_js($this->page);
$output = html_writer::start_tag('div', $menu->attributes);
$output .= html_writer::start_tag('span', $menu->attributesprimary);
$output .= html_writer::start_tag('ul', $menu->attributesprimary);
foreach ($menu->get_primary_actions($this) as $action) {
if ($action instanceof renderable) {
$output .= $this->render($action);
$content = $this->render($action);
$role = 'presentation';
} else {
$output .= $action;
$content = $action;
$role = 'menuitem';
}
$output .= html_writer::tag('li', $content, array('role' => $role));
}
$output .= html_writer::end_tag('span');
$output .= html_writer::start_tag('div', $menu->attributessecondary);
$output .= html_writer::end_tag('ul');
$output .= html_writer::start_tag('ul', $menu->attributessecondary);
foreach ($menu->get_secondary_actions() as $action) {
$output .= $this->render($action);
if ($action instanceof renderable) {
$content = $this->render($action);
$role = 'presentation';
} else {
$content = $action;
$role = 'menuitem';
}
$output .= html_writer::tag('li', $content, array('role' => $role));
}
$output .= html_writer::end_tag('div');
$output .= html_writer::end_tag('ul');
$output .= html_writer::end_tag('div');
return $output;
}
/**
* Renders an action_menu_action item.
* Renders an action_menu_link item.
*
* @param action_menu_action $action
* @param action_menu_link $action
* @return string HTML fragment
*/
protected function render_action_menu_action(action_menu_action $action) {
protected function render_action_menu_link(action_menu_link $action) {
$iconrendered = false;
@ -1102,10 +1116,10 @@ class core_renderer extends renderer_base {
$text .= html_writer::end_tag('span');
}
// A disabled link is rendered as formatted text
// A disabled link is rendered as formatted text.
if (!empty($action->attributes['disabled'])) {
// do not use div here due to nesting restriction in xhtml strict
return html_writer::tag('span', $text, array('class'=>'currentlink'));
// Do not use div here due to nesting restriction in xhtml strict.
return html_writer::tag('span', $text, array('class'=>'currentlink', 'role' => 'menuitem'));
}
$attributes = $action->attributes;
@ -1116,23 +1130,23 @@ class core_renderer extends renderer_base {
}
/**
* Renders a primary action_menu_action item.
* Renders a primary action_menu_link item.
*
* @param action_menu_primary_action $action
* @param action_menu_link_primary $action
* @return string HTML fragment
*/
protected function render_action_menu_primary_action(action_menu_primary_action $action) {
return $this->render_action_menu_action($action);
protected function render_action_menu_link_primary(action_menu_link_primary $action) {
return $this->render_action_menu_link($action);
}
/**
* Renders a secondary action_menu_action item.
* Renders a secondary action_menu_link item.
*
* @param action_menu_secondary_action $action
* @param action_menu_link_secondary $action
* @return string HTML fragment
*/
protected function render_action_menu_secondary_action(action_menu_secondary_action $action) {
return $this->render_action_menu_action($action);
protected function render_action_menu_link_secondary(action_menu_link_secondary $action) {
return $this->render_action_menu_link($action);
}
/**

View File

@ -11,11 +11,17 @@ var BODY = Y.one(Y.config.doc.body),
MENUSHOWN : 'action-menu-shown'
},
SELECTOR = {
MENU : '[data-enhance=moodle-core-actionmenu]',
MENUCONTENT : '[data-rel=menu-content]',
MENU : '.moodle-actionmenu[data-enhance=moodle-core-actionmenu]',
MENUCONTENT : '.menu[data-rel=menu-content]',
TOGGLE : '.toggle-display'
},
ACTIONMENU;
ACTIONMENU,
ALIGN = {
TL : 'tl',
TR : 'tr',
BL : 'bl',
BR : 'br'
};
/**
* Action menu support.
@ -59,9 +65,16 @@ ACTIONMENU.prototype = {
*/
initializer : function() {
Y.log('Initialising action menu manager', 'note', ACTIONMENU.NAME);
var defaultalign = this.get('align').join('-');
Y.all(SELECTOR.MENU).each(function() {
var menucontent = this.one(SELECTOR.MENUCONTENT);
menucontent.set('aria-hidden', true);
var menucontent = this.one(SELECTOR.MENUCONTENT),
toggle = this.one(SELECTOR.TOGGLE),
align = menucontent.getData('align') || defaultalign;
if (!menucontent) {
return false;
}
toggle.set('aria-haspopup', true);
menucontent.set('aria-hidden', true).addClass('align-'+align);
if (menucontent.hasChildNodes()) {
this.setAttribute('data-enhanced', '1');
}
@ -119,7 +132,7 @@ ACTIONMENU.prototype = {
* @param {EventFacade} e
*/
hideIfOutside : function(e) {
if (!e.target.test('.secondary') && !e.target.ancestor('.secondary')) {
if (!e.target.test(SELECTOR.MENU) && !e.target.ancestor(SELECTOR.MENU)) {
this.hideMenu();
}
},
@ -132,13 +145,13 @@ ACTIONMENU.prototype = {
*/
showMenu : function(menu) {
Y.log('Displaying action menu', 'note', ACTIONMENU.NAME);
var ownerSelector = menu.getData('owner'),
menuContent = menu.one(SELECTOR.MENUCONTENT);
this.owner = (ownerSelector) ? menu.ancestor(ownerSelector) : null;
var ownerselector = menu.getData('owner'),
menucontent = menu.one(SELECTOR.MENUCONTENT);
this.owner = (ownerselector) ? menu.ancestor(ownerselector) : null;
this.dialogue = menu;
menu.addClass('show');
this.owner.addClass(CSS.MENUSHOWN);
this.constrain(menuContent.set('aria-hidden', true));
this.constrain(menucontent.set('aria-hidden', false));
return true;
},
@ -149,41 +162,92 @@ ACTIONMENU.prototype = {
* @param {Node} node
*/
constrain : function(node) {
var x = node.getX(),
nodewidth = node.get('offsetWidth'),
winwidth = node.get('winWidth'),
var selector = node.getData('constraint'),
nx = node.getX(),
ny = node.getY(),
nwidth = node.get('offsetWidth'),
nheight = node.get('offsetHeight'),
cx = 0,
cy = 0,
cwidth,
cheight,
newwidth = null,
newleft = null;
newheight = null,
newleft = null,
newtop = null;
if (x < 0) {
x = 0;
newleft = 0;
} else if (x > winwidth) {
x = winwidth;
newleft = winwidth;
if (selector) {
selector = node.ancestor(selector);
}
if (selector) {
cwidth = selector.get('offsetWidth');
cheight = selector.get('offsetHeight');
cx = selector.getX();
cy = selector.getY();
} else {
cwidth = node.get('docWidth');
cheight = node.get('docHeight');
}
if (x + nodewidth > winwidth) {
if (nodewidth > winwidth) {
newleft = 0;
newwidth = winwidth;
} else {
newleft = winwidth - nodewidth;
// Constrain X.
// First up if the width is more than the constrain its easily full width + full height
if (nwidth > cwidth) {
// The width of the constraint.
newwidth = nwidth = cwidth;
// The constraints xpoint.
newleft = nx = cx;
} else {
if (nx < cx) {
// If nx is less than cx we need to move it right.
newleft = nx = cx;
} else if (nx + nwidth > cx + cwidth) {
// The top right of the node is outside of the constraint, move it in.
newleft = cx + cwidth - nwidth;
}
}
// Constrain Y.
// First up if the width is more than the constrain its easily full width + full height
if (nheight > cheight) {
// The width of the constraint.
newheight = nheight = cheight;
// The constraints xpoint.
newtop = ny = cy;
} else {
if (ny < cy) {
// If ny is less than cy we need to move it right.
newtop = ny = cy;
} else if (ny + nheight > cy + cheight) {
// The top right of the node is outside of the constraint, move it in.
newtop = cy + cheight - nheight;
}
}
if (newleft !== null) {
node.setX(newleft);
}
if (newtop !== null) {
node.setY(newtop);
}
if (newwidth !== null) {
node.setStyle('width', newwidth.toString() + 'px');
}
if (newheight !== null) {
node.setStyle('height', newheight.toString() + 'px');
}
}
};
Y.extend(ACTIONMENU, Y.Base, ACTIONMENU.prototype, {
NAME : 'moodle-core-actionmenu',
ATTRS : {
align : {
value : [
ALIGN.TR, // The dialogue.
ALIGN.BR // The button
]
}
}
});

View File

@ -1 +1 @@
YUI.add("moodle-core-actionmenu",function(e,t){var n=e.one(e.config.doc.body),r={MENUSHOWN:"action-menu-shown"},i={MENU:"[data-enhance=moodle-core-actionmenu]",MENUCONTENT:"[data-rel=menu-content]",TOGGLE:".toggle-display"},s;s=function(){s.superclass.constructor.apply(this,arguments)},s.prototype={dialogue:null,events:[],owner:null,initializer:function(){e.all(i.MENU).each(function(){var e=this.one(i.MENUCONTENT);e.set("aria-hidden",!0),e.hasChildNodes()&&this.setAttribute("data-enhanced","1")}),n.delegate("click",this.toggleMenu,i.MENU+" "+i.TOGGLE,this),n.delegate("key",this.toggleMenu,"enter,space",i.MENU+" "+i.TOGGLE,this)},hideMenu:function(){this.dialogue&&(this.dialogue.removeClass("show"),this.dialogue.one(i.MENUCONTENT).set("aria-hidden",!0),this.dialogue=null),this.owner&&(this.owner.removeClass(r.MENUSHOWN),this.owner=null);for(var e in this.events)this.events[e].detach&&this.events[e].detach();this.events=[]},toggleMenu:function(e){e.halt(!0),this.hideMenu(),this.showMenu(e.target.ancestor(i.MENU)),this.events.push(n.on("key",this.hideMenu,"esc",this)),this.events.push(n.on("click",this.hideIfOutside,this)),this.events.push(n.delegate("focus",this.hideIfOutside,"*",this))},hideIfOutside:function(e){!e.target.test(".secondary")&&!e.target.ancestor(".secondary")&&this.hideMenu()},showMenu:function(e){var t=e.getData("owner"),n=e.one(i.MENUCONTENT);return this.owner=t?e.ancestor(t):null,this.dialogue=e,e.addClass("show"),this.owner.addClass(r.MENUSHOWN),this.constrain(n.set("aria-hidden",!0)),!0},constrain:function(e){var t=e.getX(),n=e.get("offsetWidth"),r=e.get("winWidth"),i=null,s=null;t<0?(t=0,s=0):t>r&&(t=r,s=r),t+n>r&&(n>r?(s=0,i=r):s=r-n),s!==null&&e.setX(s),i!==null&&e.setStyle("width",i.toString()+"px")}},e.extend(s,e.Base,s.prototype,{NAME:"moodle-core-actionmenu",ATTRS:{}}),M.core=M.core||{},M.core.actionmenu=M.core.actionmenu||{},M.core.actionmenu.init=M.core.actionmenu.init||function(e){M.core.actionmenu.instance=M.core.actionmenu.instance||new s(e)}},"@VERSION@",{requires:["base","event"]});
YUI.add("moodle-core-actionmenu",function(e,t){var n=e.one(e.config.doc.body),r={MENUSHOWN:"action-menu-shown"},i={MENU:".moodle-actionmenu[data-enhance=moodle-core-actionmenu]",MENUCONTENT:".menu[data-rel=menu-content]",TOGGLE:".toggle-display"},s,o={TL:"tl",TR:"tr",BL:"bl",BR:"br"};s=function(){s.superclass.constructor.apply(this,arguments)},s.prototype={dialogue:null,events:[],owner:null,initializer:function(){var t=this.get("align").join("-");e.all(i.MENU).each(function(){var e=this.one(i.MENUCONTENT),n=this.one(i.TOGGLE),r=e.getData("align")||t;if(!e)return!1;n.set("aria-haspopup",!0),e.set("aria-hidden",!0).addClass("align-"+r),e.hasChildNodes()&&this.setAttribute("data-enhanced","1")}),n.delegate("click",this.toggleMenu,i.MENU+" "+i.TOGGLE,this),n.delegate("key",this.toggleMenu,"enter,space",i.MENU+" "+i.TOGGLE,this)},hideMenu:function(){this.dialogue&&(this.dialogue.removeClass("show"),this.dialogue.one(i.MENUCONTENT).set("aria-hidden",!0),this.dialogue=null),this.owner&&(this.owner.removeClass(r.MENUSHOWN),this.owner=null);for(var e in this.events)this.events[e].detach&&this.events[e].detach();this.events=[]},toggleMenu:function(e){e.halt(!0),this.hideMenu(),this.showMenu(e.target.ancestor(i.MENU)),this.events.push(n.on("key",this.hideMenu,"esc",this)),this.events.push(n.on("click",this.hideIfOutside,this)),this.events.push(n.delegate("focus",this.hideIfOutside,"*",this))},hideIfOutside:function(e){!e.target.test(i.MENU)&&!e.target.ancestor(i.MENU)&&this.hideMenu()},showMenu:function(e){var t=e.getData("owner"),n=e.one(i.MENUCONTENT);return this.owner=t?e.ancestor(t):null,this.dialogue=e,e.addClass("show"),this.owner.addClass(r.MENUSHOWN),this.constrain(n.set("aria-hidden",!1)),!0},constrain:function(e){var t=e.getData("constraint"),n=e.getX(),r=e.getY(),i=e.get("offsetWidth"),s=e.get("offsetHeight"),o=0,u=0,a,f,l=null,c=null,h=null,p=null;t&&(t=e.ancestor(t)),t?(a=t.get("offsetWidth"),f=t.get("offsetHeight"),o=t.getX(),u=t.getY()):(a=e.get("docWidth"),f=e.get("docHeight")),i>a?(l=i=a,h=n=o):n<o?h=n=o:n+i>o+a&&(h=o+a-i),s>f?(c=s=f,p=r=u):r<u?p=r=u:r+s>u+f&&(p=u+f-s),h!==null&&e.setX(h),p!==null&&e.setY(p),l!==null&&e.setStyle("width",l.toString()+"px"),c!==null&&e.setStyle("height",c.toString()+"px")}},e.extend(s,e.Base,s.prototype,{NAME:"moodle-core-actionmenu",ATTRS:{align:{value:[o.TR,o.BR]}}}),M.core=M.core||{},M.core.actionmenu=M.core.actionmenu||{},M.core.actionmenu.init=M.core.actionmenu.init||function(e){M.core.actionmenu.instance=M.core.actionmenu.instance||new s(e)}},"@VERSION@",{requires:["base","event"]});

View File

@ -11,11 +11,17 @@ var BODY = Y.one(Y.config.doc.body),
MENUSHOWN : 'action-menu-shown'
},
SELECTOR = {
MENU : '[data-enhance=moodle-core-actionmenu]',
MENUCONTENT : '[data-rel=menu-content]',
MENU : '.moodle-actionmenu[data-enhance=moodle-core-actionmenu]',
MENUCONTENT : '.menu[data-rel=menu-content]',
TOGGLE : '.toggle-display'
},
ACTIONMENU;
ACTIONMENU,
ALIGN = {
TL : 'tl',
TR : 'tr',
BL : 'bl',
BR : 'br'
};
/**
* Action menu support.
@ -58,9 +64,16 @@ ACTIONMENU.prototype = {
* @method initializer
*/
initializer : function() {
var defaultalign = this.get('align').join('-');
Y.all(SELECTOR.MENU).each(function() {
var menucontent = this.one(SELECTOR.MENUCONTENT);
menucontent.set('aria-hidden', true);
var menucontent = this.one(SELECTOR.MENUCONTENT),
toggle = this.one(SELECTOR.TOGGLE),
align = menucontent.getData('align') || defaultalign;
if (!menucontent) {
return false;
}
toggle.set('aria-haspopup', true);
menucontent.set('aria-hidden', true).addClass('align-'+align);
if (menucontent.hasChildNodes()) {
this.setAttribute('data-enhanced', '1');
}
@ -118,7 +131,7 @@ ACTIONMENU.prototype = {
* @param {EventFacade} e
*/
hideIfOutside : function(e) {
if (!e.target.test('.secondary') && !e.target.ancestor('.secondary')) {
if (!e.target.test(SELECTOR.MENU) && !e.target.ancestor(SELECTOR.MENU)) {
this.hideMenu();
}
},
@ -130,13 +143,13 @@ ACTIONMENU.prototype = {
* @returns {M.core.dialogue|dialogue}
*/
showMenu : function(menu) {
var ownerSelector = menu.getData('owner'),
menuContent = menu.one(SELECTOR.MENUCONTENT);
this.owner = (ownerSelector) ? menu.ancestor(ownerSelector) : null;
var ownerselector = menu.getData('owner'),
menucontent = menu.one(SELECTOR.MENUCONTENT);
this.owner = (ownerselector) ? menu.ancestor(ownerselector) : null;
this.dialogue = menu;
menu.addClass('show');
this.owner.addClass(CSS.MENUSHOWN);
this.constrain(menuContent.set('aria-hidden', true));
this.constrain(menucontent.set('aria-hidden', false));
return true;
},
@ -147,41 +160,92 @@ ACTIONMENU.prototype = {
* @param {Node} node
*/
constrain : function(node) {
var x = node.getX(),
nodewidth = node.get('offsetWidth'),
winwidth = node.get('winWidth'),
var selector = node.getData('constraint'),
nx = node.getX(),
ny = node.getY(),
nwidth = node.get('offsetWidth'),
nheight = node.get('offsetHeight'),
cx = 0,
cy = 0,
cwidth,
cheight,
newwidth = null,
newleft = null;
newheight = null,
newleft = null,
newtop = null;
if (x < 0) {
x = 0;
newleft = 0;
} else if (x > winwidth) {
x = winwidth;
newleft = winwidth;
if (selector) {
selector = node.ancestor(selector);
}
if (selector) {
cwidth = selector.get('offsetWidth');
cheight = selector.get('offsetHeight');
cx = selector.getX();
cy = selector.getY();
} else {
cwidth = node.get('docWidth');
cheight = node.get('docHeight');
}
if (x + nodewidth > winwidth) {
if (nodewidth > winwidth) {
newleft = 0;
newwidth = winwidth;
} else {
newleft = winwidth - nodewidth;
// Constrain X.
// First up if the width is more than the constrain its easily full width + full height
if (nwidth > cwidth) {
// The width of the constraint.
newwidth = nwidth = cwidth;
// The constraints xpoint.
newleft = nx = cx;
} else {
if (nx < cx) {
// If nx is less than cx we need to move it right.
newleft = nx = cx;
} else if (nx + nwidth > cx + cwidth) {
// The top right of the node is outside of the constraint, move it in.
newleft = cx + cwidth - nwidth;
}
}
// Constrain Y.
// First up if the width is more than the constrain its easily full width + full height
if (nheight > cheight) {
// The width of the constraint.
newheight = nheight = cheight;
// The constraints xpoint.
newtop = ny = cy;
} else {
if (ny < cy) {
// If ny is less than cy we need to move it right.
newtop = ny = cy;
} else if (ny + nheight > cy + cheight) {
// The top right of the node is outside of the constraint, move it in.
newtop = cy + cheight - nheight;
}
}
if (newleft !== null) {
node.setX(newleft);
}
if (newtop !== null) {
node.setY(newtop);
}
if (newwidth !== null) {
node.setStyle('width', newwidth.toString() + 'px');
}
if (newheight !== null) {
node.setStyle('height', newheight.toString() + 'px');
}
}
};
Y.extend(ACTIONMENU, Y.Base, ACTIONMENU.prototype, {
NAME : 'moodle-core-actionmenu',
ATTRS : {
align : {
value : [
ALIGN.TR, // The dialogue.
ALIGN.BR // The button
]
}
}
});

View File

@ -9,11 +9,17 @@ var BODY = Y.one(Y.config.doc.body),
MENUSHOWN : 'action-menu-shown'
},
SELECTOR = {
MENU : '[data-enhance=moodle-core-actionmenu]',
MENUCONTENT : '[data-rel=menu-content]',
MENU : '.moodle-actionmenu[data-enhance=moodle-core-actionmenu]',
MENUCONTENT : '.menu[data-rel=menu-content]',
TOGGLE : '.toggle-display'
},
ACTIONMENU;
ACTIONMENU,
ALIGN = {
TL : 'tl',
TR : 'tr',
BL : 'bl',
BR : 'br'
};
/**
* Action menu support.
@ -57,9 +63,16 @@ ACTIONMENU.prototype = {
*/
initializer : function() {
Y.log('Initialising action menu manager', 'note', ACTIONMENU.NAME);
var defaultalign = this.get('align').join('-');
Y.all(SELECTOR.MENU).each(function() {
var menucontent = this.one(SELECTOR.MENUCONTENT);
menucontent.set('aria-hidden', true);
var menucontent = this.one(SELECTOR.MENUCONTENT),
toggle = this.one(SELECTOR.TOGGLE),
align = menucontent.getData('align') || defaultalign;
if (!menucontent) {
return false;
}
toggle.set('aria-haspopup', true);
menucontent.set('aria-hidden', true).addClass('align-'+align);
if (menucontent.hasChildNodes()) {
this.setAttribute('data-enhanced', '1');
}
@ -117,7 +130,7 @@ ACTIONMENU.prototype = {
* @param {EventFacade} e
*/
hideIfOutside : function(e) {
if (!e.target.test('.secondary') && !e.target.ancestor('.secondary')) {
if (!e.target.test(SELECTOR.MENU) && !e.target.ancestor(SELECTOR.MENU)) {
this.hideMenu();
}
},
@ -130,13 +143,13 @@ ACTIONMENU.prototype = {
*/
showMenu : function(menu) {
Y.log('Displaying action menu', 'note', ACTIONMENU.NAME);
var ownerSelector = menu.getData('owner'),
menuContent = menu.one(SELECTOR.MENUCONTENT);
this.owner = (ownerSelector) ? menu.ancestor(ownerSelector) : null;
var ownerselector = menu.getData('owner'),
menucontent = menu.one(SELECTOR.MENUCONTENT);
this.owner = (ownerselector) ? menu.ancestor(ownerselector) : null;
this.dialogue = menu;
menu.addClass('show');
this.owner.addClass(CSS.MENUSHOWN);
this.constrain(menuContent.set('aria-hidden', true));
this.constrain(menucontent.set('aria-hidden', false));
return true;
},
@ -147,41 +160,92 @@ ACTIONMENU.prototype = {
* @param {Node} node
*/
constrain : function(node) {
var x = node.getX(),
nodewidth = node.get('offsetWidth'),
winwidth = node.get('winWidth'),
var selector = node.getData('constraint'),
nx = node.getX(),
ny = node.getY(),
nwidth = node.get('offsetWidth'),
nheight = node.get('offsetHeight'),
cx = 0,
cy = 0,
cwidth,
cheight,
newwidth = null,
newleft = null;
newheight = null,
newleft = null,
newtop = null;
if (x < 0) {
x = 0;
newleft = 0;
} else if (x > winwidth) {
x = winwidth;
newleft = winwidth;
if (selector) {
selector = node.ancestor(selector);
}
if (selector) {
cwidth = selector.get('offsetWidth');
cheight = selector.get('offsetHeight');
cx = selector.getX();
cy = selector.getY();
} else {
cwidth = node.get('docWidth');
cheight = node.get('docHeight');
}
if (x + nodewidth > winwidth) {
if (nodewidth > winwidth) {
newleft = 0;
newwidth = winwidth;
} else {
newleft = winwidth - nodewidth;
// Constrain X.
// First up if the width is more than the constrain its easily full width + full height
if (nwidth > cwidth) {
// The width of the constraint.
newwidth = nwidth = cwidth;
// The constraints xpoint.
newleft = nx = cx;
} else {
if (nx < cx) {
// If nx is less than cx we need to move it right.
newleft = nx = cx;
} else if (nx + nwidth > cx + cwidth) {
// The top right of the node is outside of the constraint, move it in.
newleft = cx + cwidth - nwidth;
}
}
// Constrain Y.
// First up if the width is more than the constrain its easily full width + full height
if (nheight > cheight) {
// The width of the constraint.
newheight = nheight = cheight;
// The constraints xpoint.
newtop = ny = cy;
} else {
if (ny < cy) {
// If ny is less than cy we need to move it right.
newtop = ny = cy;
} else if (ny + nheight > cy + cheight) {
// The top right of the node is outside of the constraint, move it in.
newtop = cy + cheight - nheight;
}
}
if (newleft !== null) {
node.setX(newleft);
}
if (newtop !== null) {
node.setY(newtop);
}
if (newwidth !== null) {
node.setStyle('width', newwidth.toString() + 'px');
}
if (newheight !== null) {
node.setStyle('height', newheight.toString() + 'px');
}
}
};
Y.extend(ACTIONMENU, Y.Base, ACTIONMENU.prototype, {
NAME : 'moodle-core-actionmenu',
ATTRS : {
align : {
value : [
ALIGN.TR, // The dialogue.
ALIGN.BR // The button
]
}
}
});

View File

@ -1373,30 +1373,67 @@ div.badge .expireimage { width: 100px; height: 100px; left: 20px; top: 0px; }
.path-mod-lesson .centerpadded { padding: 5px; text-align: center; }
/** Action menu component styles **/
.moodle-actionmenu,
.moodle-actionmenu .secondary {display: inline-block;}
.moodle-actionmenu > ul,
.moodle-actionmenu > ul > li {display: inline-block;}
.moodle-actionmenu ul {padding: 0;margin: 0;list-style-type: none;}
.moodle-actionmenu .toggle-display,
.moodle-actionmenu .menu-action-text {display: none;}
.jsenabled .block .editing_move {display: none;}
.jsenabled .moodle-actionmenu {display: block;}
.jsenabled .moodle-actionmenu .secondary {display: none;margin-top: 4px;}
.jsenabled .moodle-actionmenu[data-enhanced].show .secondary {display: block;}
.jsenabled .moodle-actionmenu .toggle-display {display: inline;cursor: auto;opacity: 0.5;filter: alpha(opacity=50);}
.jsenabled .moodle-actionmenu .menu {display: none;}
.jsenabled .moodle-actionmenu .toggle-display {display: inline;opacity: 0.5;filter: alpha(opacity=50);}
.jsenabled .moodle-actionmenu[data-enhanced] .toggle-display {opacity: 1;filter: alpha(opacity=100);}
.jsenabled .moodle-actionmenu[data-enhanced] .menu-action-text {display: inline;}
.moodle-actionmenu[data-enhanced].show {position: relative;}
.moodle-actionmenu[data-enhanced].show .secondary {position: absolute;top: 100%;right: 0;left: auto;background-color: #fff;border: 1px solid #ccc;-webkit-border-radius: 5px;-moz-border-radius: 5px;border-radius: 5px;-webkit-box-shadow: 5px 5px 20px 0 #666666;-moz-box-shadow: 5px 5px 20px 0 #666666;box-shadow: 5px 5px 20px 0 #666666;z-index:1000;}
.moodle-actionmenu[data-enhanced].show .secondary a {display: block;padding: 2px 1em 2px 0.5em;color: #333333;}
.moodle-actionmenu[data-enhanced].show .secondary a:hover,
.moodle-actionmenu[data-enhanced].show .secondary a:focus {color: #ffffff;background-color: #0088cc;}
.moodle-actionmenu[data-enhanced].show .secondary a:first-child {-webkit-border-top-right-radius: 4px;border-top-right-radius: 4px;-webkit-border-top-left-radius: 4px;border-top-left-radius: 4px;-moz-border-radius-topright: 4px;-moz-border-radius-topleft: 4px;}
.moodle-actionmenu[data-enhanced].show .secondary a:last-child {-webkit-border-bottom-right-radius: 4px;border-bottom-right-radius: 4px;-webkit-border-bottom-left-radius: 4px;border-bottom-left-radius: 4px;-moz-border-radius-bottomright: 4px;-moz-border-radius-bottomleft: 4px;}
.moodle-actionmenu[data-enhanced].show .secondary a.hidden {display: none;}
.moodle-actionmenu[data-enhanced].show .secondary img {vertical-align: middle;}
.moodle-actionmenu[data-enhanced].show .secondary .iconsmall {margin-right: 8px;}
.moodle-actionmenu[data-enhanced].show .menu {position: absolute;z-index: 1000;display: block;background-color: #fff;border: 1px solid #ccc;-webkit-border-radius: 5px;-moz-border-radius: 5px;border-radius: 5px;-webkit-box-shadow: 5px 5px 20px 0 #666666;-moz-box-shadow: 5px 5px 20px 0 #666666;box-shadow: 5px 5px 20px 0 #666666;}
.moodle-actionmenu[data-enhanced].show .menu a {display: block;padding: 2px 1em 2px 0.5em;color: #333333;}
.moodle-actionmenu[data-enhanced].show .menu a:hover,
.moodle-actionmenu[data-enhanced].show .menu a:focus {color: #ffffff;background-color: #0088cc;}
.moodle-actionmenu[data-enhanced].show .menu a:first-child {-webkit-border-top-right-radius: 4px;border-top-right-radius: 4px;-webkit-border-top-left-radius: 4px;border-top-left-radius: 4px;-moz-border-radius-topright: 4px;-moz-border-radius-topleft: 4px;}
.moodle-actionmenu[data-enhanced].show .menu a:last-child {-webkit-border-bottom-right-radius: 4px;border-bottom-right-radius: 4px;-webkit-border-bottom-left-radius: 4px;border-bottom-left-radius: 4px;-moz-border-radius-bottomright: 4px;-moz-border-radius-bottomleft: 4px;}
.moodle-actionmenu[data-enhanced].show .menu a.hidden {display: none;}
.moodle-actionmenu[data-enhanced].show .menu img {vertical-align: middle;}
.moodle-actionmenu[data-enhanced].show .menu .iconsmall {margin-right: 8px;}
.moodle-actionmenu[data-enhanced].show .menu > li {display: block;}
.action-menu-shown .moodle-actionmenu[data-enhanced] .toggle-display {background-color: #FFF;}
.block .moodle-actionmenu {text-align: right;}
.dir-rtl .moodle-actionmenu[data-enhanced].show .secondary {right: auto;left: 0;}
.dir-rtl .moodle-actionmenu[data-enhanced].show .secondary .iconsmall {margin-right: 0;margin-left: 8px;}
.dir-rtl .block .moodle-actionmenu {text-align: right;}
.dir-rtl .block .moodle-actionmenu {text-align: right;}
.dir-rtl .moodle-actionmenu[data-enhanced].show .menu {right: auto;left: 0;}
.dir-rtl .moodle-actionmenu[data-enhanced].show .menu .iconsmall {margin-right: 0;margin-left: 8px;}
.menu.align-tl-bl {top: 100%;left: 0;margin-top: 4px;}
.menu.align-tr-bl {top: 100%;right: 100%;}
.menu.align-bl-bl {bottom: 100%;left: 0;}
.menu.align-br-bl {right: 100%;bottom: 100%;}
.menu.align-tl-br {top: 100%;left: 100%;}
.menu.align-tr-br {top: 100%;right: 0;margin-top: 4px;}
.menu.align-bl-br {bottom: 100%;left: 100%;}
.menu.align-br-br {right: 0;bottom: 100%;}
.menu.align-tl-tl {top: 0;left: 0;}
.menu.align-tr-tl {top: 0;right: 100%;margin-right: 4px;}
.menu.align-bl-tl {bottom: 100%;left: 0;margin-bottom: 4px;}
.menu.align-br-tl {right: 100%;bottom: 100%;}
.menu.align-tl-tr {top: 0;left: 100%;margin-left: 4px;}
.menu.align-tr-tr {top: 0;right: 0;}
.menu.align-bl-tr {bottom: 100%;left: 100%;}
.menu.align-br-tr {right: 0;bottom: 100%;margin-bottom: 4px;}
.dir-rtl .menu.align-tl-bl {right: 0;left: auto;}
.dir-rtl .menu.align-tr-bl {right: auto;left: 100%;}
.dir-rtl .menu.align-bl-bl {right: 0;left: auto;}
.dir-rtl .menu.align-br-bl {right: auto;left: 100%;}
.dir-rtl .menu.align-tl-br {right: 100%;left: auto;}
.dir-rtl .menu.align-tr-br {right: auto;left: 0;}
.dir-rtl .menu.align-bl-br {right: 100%;left: auto;}
.dir-rtl .menu.align-br-br {right: auto;left: 0;}
.dir-rtl .menu.align-tl-tl {right: 0;left: auto;}
.dir-rtl .menu.align-tr-tl {right: auto;left: 100%;}
.dir-rtl .menu.align-bl-tl {right: 0;left: auto;}
.dir-rtl .menu.align-br-tl {right: auto;left: 100%;}
.dir-rtl .menu.align-tl-tr {right: 100%;left: auto;}
.dir-rtl .menu.align-tr-tr {right: auto;left: 0;}
.dir-rtl .menu.align-bl-tr {right: 100%;left: auto;}
.dir-rtl .menu.align-br-tr {right: auto;left: 0;}

View File

@ -1911,11 +1911,19 @@ div.badge .expireimage {
margin: 0;
}
/** Action menu component styles **/
.moodle-actionmenu,
.moodle-actionmenu .secondary {
.moodle-actionmenu > ul,
.moodle-actionmenu > ul > li {
display: inline-block;
}
.moodle-actionmenu ul {
padding: 0;
margin: 0;
list-style-type: none;
}
.moodle-actionmenu .toggle-display,
.moodle-actionmenu .menu-action-text {
display: none; /** Hidden by default, display none so that we don't take up space. **/
@ -1927,26 +1935,20 @@ div.badge .expireimage {
}
.moodle-actionmenu {
display: block;
.secondary {
.menu {
display:none;
margin-top: 4px;
}
}
.moodle-actionmenu[data-enhanced].show .secondary {
display:block;
}
.moodle-actionmenu .toggle-display {
display: inline; /** JS is enabled, we'll be using it so return display to normal **/
cursor:auto;
.opacity(50);
}
.moodle-actionmenu[data-enhanced] {
.toggle-display {
.opacity(100);
display: inline; /** JS is enabled, we'll be using it so return display to normal **/
.opacity(50);
}
.menu-action-text {
display:inline;
&[data-enhanced] {
.toggle-display {
.opacity(100);
}
.menu-action-text {
display:inline;
}
}
}
}
@ -1955,12 +1957,10 @@ div.badge .expireimage {
position: relative;
.secondary {
.menu {
display:block;
position: absolute;
top: 100%;
right: 0;
left: auto;
background-color: #fff;
border: 1px solid #ccc;
z-index:1000;
@ -1992,6 +1992,30 @@ div.badge .expireimage {
.iconsmall {
margin-right:8px;
}
> li {
display:block;
}
/** bottom left of button **/
&.align-tl-bl {top: 100%;left:0;margin-top: 4px;}
&.align-tr-bl {top: 100%;right: 100%;}
&.align-bl-bl {bottom: 100%;left:0;}
&.align-br-bl {bottom: 100%;right: 100%;}
/** bottom right of button **/
&.align-tl-br {top: 100%;left:100%;}
&.align-tr-br {top: 100%;right: 0;margin-top: 4px;}
&.align-bl-br {bottom: 100%;left:100%;}
&.align-br-br {bottom: 100%;right: 0;}
/** top left of button **/
&.align-tl-tl {top: 0;left:0;}
&.align-tr-tl {top: 0;right: 100%;margin-right: 4px;}
&.align-bl-tl {bottom: 100%;left:0;margin-bottom: 4px;}
&.align-br-tl {bottom: 100%;right: 100%;}
/** top right of button **/
&.align-tl-tr {top: 0;left:100%;margin-left: 4px;}
&.align-tr-tr {top: 0;right: 0;}
&.align-bl-tr {bottom: 100%;left:100%;}
&.align-br-tr {bottom: 100%;right: 0;margin-bottom: 4px;}
}
}
@ -2005,13 +2029,34 @@ div.badge .expireimage {
.dir-rtl {
.moodle-actionmenu[data-enhanced].show {
.secondary {
.menu {
left: 0;
right: auto;
.iconsmall {
margin-right:0;
margin-left:8px;
}
/** bottom left of button **/
&.align-tl-bl {left: auto; right: 0;}
&.align-tr-bl {right: auto; left: 100%;}
&.align-bl-bl {left: auto; right: 0;}
&.align-br-bl {right: auto; left: 100%;}
/** bottom right of button **/
&.align-tl-br {left: auto; right: 100%;}
&.align-tr-br {right: auto; left: 0;}
&.align-bl-br {left: auto; right: 100%;}
&.align-br-br {right: auto; left: 0;}
/** top left of button **/
&.align-tl-tl {left: auto; right: 0;}
&.align-tr-tl {right: auto; left: 100%;}
&.align-bl-tl {left: auto; right: 0;}
&.align-br-tl {right: auto; left: 100%;}
/** top right of button **/
&.align-tl-tr {left: auto; right: 100%;}
&.align-tr-tr {right: auto; left: 0;}
&.align-bl-tr {left: auto; right: 100%;}
&.align-br-tr {right: auto; left: 0;}
}
}
.block .moodle-actionmenu {

File diff suppressed because one or more lines are too long