mirror of
https://github.com/moodle/moodle.git
synced 2025-04-22 00:42:54 +02:00
MDL-39814 actionmenu: improved alignment, constraint handling, and accessibility
This commit is contained in:
parent
e5de4933b0
commit
3665af78ca
@ -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,
|
||||
|
@ -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);
|
||||
|
2
course/yui/toolboxes/toolboxes.js
vendored
2
course/yui/toolboxes/toolboxes.js
vendored
@ -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);
|
||||
}
|
||||
}
|
||||
}, {
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -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"]});
|
||||
|
@ -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
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
116
lib/yui/src/actionmenu/js/actionmenu.js
vendored
116
lib/yui/src/actionmenu/js/actionmenu.js
vendored
@ -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
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -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;}
|
@ -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
Loading…
x
Reference in New Issue
Block a user