MDL-39814 frontend: redeveloped overlay to correct tab-flow

Also:
 * fixed zindex issue + spinner placement
 * added notes to course format and theme upgrade texts
 * fixed behat tests after action menu changes
This commit is contained in:
Sam Hemelryk
2013-07-30 16:15:19 +12:00
parent 202fcfa130
commit e5de4933b0
20 changed files with 439 additions and 364 deletions
@@ -21,7 +21,8 @@ Feature: Duplicate activities
And I add a "Database" to section "1" and I fill the form with:
| Name | Test database name |
| Description | Test database description |
When I click on "Duplicate" "link" in the "#section-1" "css_element"
And I click on "Actions" "link" in the "Test database name" activity
When I click on "Duplicate" "link" in the "Test database name" activity
And I press "Continue"
And I press "Edit the new copy"
And I fill the moodle form with:
+5
View File
@@ -2,6 +2,11 @@ This files describes API changes for course formats
Overview of this plugin type at http://docs.moodle.org/dev/Course_formats
=== 2.6 ===
* core_course_renderer::course_section_cm_edit_actions has two new optional arguments and now uses and action_menu component.
* core_course_renderer::course_section_cm has been altered to call core_course_renderer::course_section_cm_edit_actions with the two new arguments
=== 2.5 ===
* Functions responsible for output in course/lib.php are deprecated, the code is moved to
+6 -6
View File
@@ -1865,7 +1865,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
}
// Duplicate (require both target import caps to be able to duplicate and backup2 support, see modduplicate.php)
// note that restoring on front page is never allowed.
// 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(
@@ -1913,19 +1913,19 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
$modgroupmode = $mod->groupmode;
}
if ($modgroupmode == SEPARATEGROUPS) {
$groupmode = NOGROUPS;
$nextgroupmode = VISIBLEGROUPS;
$grouptitle = $str->groupsseparate;
$forcedgrouptitle = $str->forcedgroupsseparate;
$actionname = 'groupsseparate';
$groupimage = 't/groups';
} else if ($modgroupmode == VISIBLEGROUPS) {
$groupmode = SEPARATEGROUPS;
$nextgroupmode = NOGROUPS;
$grouptitle = $str->groupsvisible;
$forcedgrouptitle = $str->forcedgroupsvisible;
$actionname = 'groupsvisible';
$groupimage = 't/groupv';
} else {
$groupmode = VISIBLEGROUPS;
$nextgroupmode = SEPARATEGROUPS;
$grouptitle = $str->groupsnone;
$forcedgrouptitle = $str->forcedgroupsnone;
$actionname = 'groupsnone';
@@ -1933,10 +1933,10 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
}
if (!$mod->coursegroupmodeforce) {
$actions[$actionname] = new action_menu_primary_action(
new moodle_url($baseurl, array('id' => $mod->id, 'groupmode' => $groupmode)),
new moodle_url($baseurl, array('id' => $mod->id, 'groupmode' => $nextgroupmode)),
new pix_icon($groupimage, $grouptitle, 'moodle', array('class' => 'iconsmall', 'title' => '')),
$grouptitle,
array('class' => 'editing_'. $actionname, 'data-action' => $actionname, 'data-groupmode' => $groupmode)
array('class' => 'editing_'. $actionname, 'data-action' => $actionname, 'data-nextgroupmode' => $nextgroupmode)
);
} else {
$actions[$actionname] = new pix_icon($groupimage, $forcedgrouptitle, 'moodle', array('title' => '', 'class' => 'iconsmall'));
@@ -26,7 +26,7 @@ Feature: Indent items on the course page
When I indent right "Test glossary name" activity
Then "#section-1 li.glossary div.mod-indent-1" "css_element" should exists
And I indent right "Test glossary name" activity
And "//li[@id='section-1']/descendant::li[contains(concat(' ', @class, ' '), ' glossary ')]/descendant::a[@title='Move left']" "xpath_element" should exists
And "//li[@id='section-1']/descendant::li[contains(concat(' ', @class, ' '), ' glossary ')]/descendant::a[not(contains(concat(' ', @class, ' '), ' hidden '))]/descendant::span[normalize-space(.)='Move left']" "xpath_element" should exists
And "#section-1 li.glossary div.mod-indent-2" "css_element" should exists
And I reload the page
And "#section-1 li.glossary div.mod-indent-2" "css_element" should exists
@@ -34,4 +34,4 @@ Feature: Indent items on the course page
And I indent left "Test glossary name" activity
And "#section-1 li.glossary div.mod-indent-2" "css_element" should not exists
And "#section-1 li.glossary div.mod-indent-1" "css_element" should not exists
And "//li[@id='section-1']/descendant::li[contains(concat(' ', @class, ' '), ' glossary ')]/descendant::a[@title='Move left']" "xpath_element" should not exists
And "//li[@id='section-1']/descendant::li[contains(concat(' ', @class, ' '), ' glossary ')]/descendant::a[not(contains(concat(' ', @class, ' '), ' hidden '))]/descendant::span[normalize-space(.)='Move left']" "xpath_element" should not exists
+35 -19
View File
@@ -485,8 +485,10 @@ class behat_course extends behat_base {
}
// Adding chr(10) to save changes.
$activity = $this->escape($activityname);
return array(
new Given('I click on "' . get_string('edittitle') . '" "link" in the "' . $this->escape($activityname) .'" activity'),
new Given('I click on "' . get_string('actions', 'moodle') . '" "link" in the "' . $activity . '" activity'),
new Given('I click on "' . get_string('edittitle') . '" "link" in the "' . $activity .'" activity'),
new Given('I fill in "title" with "' . $this->escape($newactivityname) . chr(10) . '"'),
new Given('I wait "2" seconds')
);
@@ -500,9 +502,12 @@ class behat_course extends behat_base {
*/
public function i_indent_right_activity($activityname) {
$steps = array(
new Given('I click on "' . get_string('moveright') . '" "link" in the "' . $this->escape($activityname) . '" activity')
);
$steps = array();
$activity = $this->escape($activityname);
if ($this->running_javascript()) {
$steps[] = new Given('I click on "' . get_string('actions', 'moodle') . '" "link" in the "' . $activity . '" activity');
}
$steps[] = new Given('I click on "' . get_string('moveright') . '" "link" in the "' . $activity . '" activity');
if ($this->running_javascript()) {
$steps[] = new Given('I wait "2" seconds');
@@ -519,9 +524,12 @@ class behat_course extends behat_base {
*/
public function i_indent_left_activity($activityname) {
$steps = array(
new Given('I click on "' . get_string('moveleft') . '" "link" in the "' . $this->escape($activityname) . '" activity')
);
$steps = array();
$activity = $this->escape($activityname);
if ($this->running_javascript()) {
$steps[] = new Given('I click on "' . get_string('actions', 'moodle') . '" "link" in the "' . $activity . '" activity');
}
$steps[] = new Given('I click on "' . get_string('moveleft') . '" "link" in the "' . $activity . '" activity');
if ($this->running_javascript()) {
$steps[] = new Given('I wait "2" seconds');
@@ -572,11 +580,15 @@ class behat_course extends behat_base {
* @param string $activityname
*/
public function i_duplicate_activity($activityname) {
return array(
new Given('I click on "' . get_string('duplicate') . '" "link" in the "' . $this->escape($activityname) . '" activity'),
new Given('I press "' . get_string('continue') .'"'),
new Given('I press "' . get_string('duplicatecontcourse') .'"')
);
$steps = array();
$activity = $this->escape($activityname);
if ($this->running_javascript()) {
$steps[] = new Given('I click on "' . get_string('actions', 'moodle') . '" "link" in the "' . $activity . '" activity');
}
$steps[] = new Given('I click on "' . get_string('duplicate') . '" "link" in the "' . $activity . '" activity');
$steps[] = new Given('I press "' . get_string('continue') .'"');
$steps[] = new Given('I press "' . get_string('duplicatecontcourse') .'"');
return $steps;
}
/**
@@ -587,13 +599,17 @@ class behat_course extends behat_base {
* @param TableNode $data
*/
public function i_duplicate_activity_editing_the_new_copy_with($activityname, TableNode $data) {
return array(
new Given('I click on "' . get_string('duplicate') . '" "link" in the "' . $this->escape($activityname) . '" activity'),
new Given('I press "' . get_string('continue') .'"'),
new Given('I press "' . get_string('duplicatecontedit') . '"'),
new Given('I fill the moodle form with:', $data),
new Given('I press "' . get_string('savechangesandreturntocourse') . '"')
);
$steps = array();
$activity = $this->escape($activityname);
if ($this->running_javascript()) {
$steps[] = new Given('I click on "' . get_string('actions', 'moodle') . '" "link" in the "' . $activity . '" activity');
}
$steps[] = new Given('I click on "' . get_string('duplicate') . '" "link" in the "' . $activity . '" activity');
$steps[] = new Given('I press "' . get_string('continue') .'"');
$steps[] = new Given('I press "' . get_string('duplicatecontedit') . '"');
$steps[] = new Given('I fill the moodle form with:', $data);
$steps[] = new Given('I press "' . get_string('savechangesandreturntocourse') . '"');
return $steps;
}
/**
@@ -40,6 +40,7 @@ Feature: Course activity controls works as expected
And I should see "Turn editing on"
And "Turn editing on" "button" should exists
And I turn editing mode on
And I click on "Actions" "link" in the ".block_recent_activity" "css_element"
And I click on "Delete Recent activity block" "link"
And I press "Yes"
And "#section-2" "css_element" <should_see_other_sections> exists
@@ -54,11 +55,13 @@ Feature: Course activity controls works as expected
And "#section-2" "css_element" <should_see_other_sections> exists
And I indent left "Test forum name 1" activity
And "#section-2" "css_element" <should_see_other_sections> exists
And I click on "Actions" "link" in the "Test forum name 1" activity
And I click on "Update" "link" in the "Test forum name 1" activity
And I should see "Updating Forum"
And I should see "Display description on course page"
And I press "Save and return to course"
And "#section-2" "css_element" <should_see_other_sections> exists
And I click on "Actions" "link" in the "Test forum name 1" activity
And I click on "Hide" "link" in the "Test forum name 1" activity
And "#section-2" "css_element" <should_see_other_sections> exists
And I duplicate "Test forum name 2" activity editing the new copy with:
@@ -111,6 +114,7 @@ Feature: Course activity controls works as expected
And I should see "Turn editing on"
And "Turn editing on" "button" should exists
And I turn editing mode on
And I click on "Actions" "link" in the ".block_recent_activity" "css_element"
And I click on "Delete Recent activity block" "link"
And I press "Yes"
And "#section-2" "css_element" <should_see_other_sections> exists
@@ -125,11 +129,13 @@ Feature: Course activity controls works as expected
And "#section-2" "css_element" <should_see_other_sections> exists
And I indent left "Test forum name 1" activity
And "#section-2" "css_element" <should_see_other_sections> exists
And I click on "Actions" "link" in the "Test forum name 1" activity
And I click on "Update" "link" in the "Test forum name 1" activity
And I should see "Updating Forum"
And I should see "Display description on course page"
And I press "Save and return to course"
And "#section-2" "css_element" <should_see_other_sections> exists
And I click on "Actions" "link" in the "Test forum name 1" activity
And I click on "Hide" "link" in the "Test forum name 1" activity
And "#section-2" "css_element" <should_see_other_sections> exists
And I delete "Test forum name 1" activity
+41 -22
View File
@@ -237,6 +237,7 @@ YUI.add('moodle-course-toolboxes', function(Y) {
initializer : function(config) {
M.course.coursebase.register_module(this);
Y.all(SELECTOR.ACTIVITYLI).each(function(activity){
activity.setData('toolbox', this);
activity.all(SELECTOR.COMMANDSPAN+ ' ' + SELECTOR.ACTIVITYACTION).each(function(){
this.setData('activity', activity);
});
@@ -343,11 +344,20 @@ YUI.add('moodle-course-toolboxes', function(Y) {
'field' : 'indent',
'value' : newindent,
'id' : this.get_element_id(activity)
};
var spinner = M.util.add_spinner(Y, activity.one(SELECTOR.COMMANDSPAN));
},
commands = activity.one(SELECTOR.COMMANDSPAN),
spinner = M.util.add_spinner(Y, commands).setStyles({
position: 'absolute',
top: 0
});
if (BODY.hasClass('dir-ltr')) {
spinner.setStyle('left', '100%');
} else {
spinner.setStyle('right', '100%');
}
this.send_request(data, spinner);
// Handle removal/addition of the moveleft button
// Handle removal/addition of the moveleft button.
if (newindent == 0) {
button.addClass('hidden');
} else if (newindent == 1 && oldindent == 0) {
@@ -507,14 +517,18 @@ YUI.add('moodle-course-toolboxes', function(Y) {
ev.preventDefault();
// Current Mode
var oldgroupmode = button.getData('groupmode');
var groupmode = parseInt(oldgroupmode, 10) + 1;
if (groupmode > 2) {
groupmode = 0;
var groupmode = parseInt(button.getData('nextgroupmode'), 10),
newtitle = '',
iconsrc = '',
newtitlestr,
data,
spinner,
nextgroupmode = groupmode + 1;
if (nextgroupmode > 2) {
nextgroupmode = 0;
}
var newtitle = '';
var iconsrc = '';
if (groupmode === this.GROUPS_NONE) {
newtitle = 'groupsnone';
iconsrc = M.util.image_url('t/groupn', 'moodle');
@@ -525,24 +539,25 @@ YUI.add('moodle-course-toolboxes', function(Y) {
newtitle = 'groupsvisible';
iconsrc = M.util.image_url('t/groupv', 'moodle');
}
var newtitlestr = M.util.get_string(newtitle, 'moodle'),
newtitlestr = M.util.get_string('clicktochangeinbrackets', 'moodle', newtitlestr);
newtitlestr = M.util.get_string(newtitle, 'moodle'),
newtitlestr = M.util.get_string('clicktochangeinbrackets', 'moodle', newtitlestr);
// Change the UI
button.one('img').setAttrs({
'alt' : newtitlestr,
'src' : iconsrc
});
button.setAttribute('title', newtitlestr).setData('action', newtitle).setData('groupmode', groupmode);
button.setAttribute('title', newtitlestr).setData('action', newtitle).setData('nextgroupmode', nextgroupmode);
// And send the request
var data = {
data = {
'class' : 'resource',
'field' : 'groupmode',
'value' : groupmode,
'id' : this.get_element_id(activity)
};
var spinner = M.util.add_spinner(Y, activity.one(SELECTOR.COMMANDSPAN));
spinner = M.util.add_spinner(Y, activity.one(SELECTOR.COMMANDSPAN));
this.send_request(data, spinner);
return false; // Need to return false to stop the delegate for the new state firing
},
@@ -696,15 +711,17 @@ YUI.add('moodle-course-toolboxes', function(Y) {
* and 'visible' being the state that the visibility should be set to.
*/
set_visibility_resource_ui: function(args) {
var element = args.element;
var shouldbevisible = args.visible;
var buttonnode = element.one(SELECTOR.SHOW);
var visible = (buttonnode === null);
var element = args.element,
shouldbevisible = args.visible,
buttonnode = element.one(SELECTOR.SHOW),
visible = (buttonnode === null),
status = 'hide';
if (visible) {
buttonnode = element.one(SELECTOR.HIDE);
status = 'show'
}
if (visible != shouldbevisible) {
this.change_visibility_ui(buttonnode);
this.handle_resource_dim(buttonnode, buttonnode.get('activity'), status);
}
}
}, {
@@ -768,17 +785,19 @@ YUI.add('moodle-course-toolboxes', function(Y) {
// The value to submit
var value;
// The status text for strings and images
var status;
var status,
oldstatus;
if (!section.hasClass(CSS.SECTIONHIDDENCLASS)) {
section.addClass(CSS.SECTIONHIDDENCLASS);
value = 0;
status = 'show';
oldstatus = 'hide';
} else {
section.removeClass(CSS.SECTIONHIDDENCLASS);
value = 1;
status = 'hide';
oldstatus = 'show';
}
var newstring = M.util.get_string(status + 'fromothers', 'format_' + this.get('format'));
@@ -811,7 +830,7 @@ YUI.add('moodle-course-toolboxes', function(Y) {
var activityid = this.get_element_id(node);
if (Y.Array.indexOf(response.resourcestotoggle, activityid) != -1) {
this.change_visibility_ui(button);
node.getData('toolbox').handle_resource_dim(button, node, oldstatus);
}
}, this);
},
+21 -9
View File
@@ -3044,6 +3044,8 @@ class tabtree extends tabobject {
*/
class action_menu implements renderable {
protected $instance = 0;
/**
* An array of primary actions. Please use {@see action_menu::add_primary_action()} to add actions.
* @var array
@@ -3082,25 +3084,27 @@ class action_menu implements renderable {
*/
public function __construct(array $actions = array()) {
static $initialised = 0;
$this->instance = $initialised;
$initialised++;
$this->attributes = array(
'id' => 'action-menu-'.$initialised,
'id' => 'action-menu-'.$this->instance,
'class' => 'moodle-actionmenu',
'data-enhance' => 'moodle-core-actionmenu'
);
$this->attributesprimary = array(
'id' => 'action-menu-'.$initialised.'-primary',
'id' => 'action-menu-'.$this->instance.'-primary',
'class' => 'primary'
);
$this->attributessecondary = array(
'id' => 'action-menu-'.$initialised.'-secondary',
'id' => 'action-menu-'.$this->instance.'-secondary',
'class' => 'secondary',
'data-rel' => 'menu-content',
'aria-labelledby' => 'action-menu-toggle-'.$this->instance,
);
foreach ($actions as $action) {
$this->add($action);
}
// We've initialised!
$initialised++;
}
/**
@@ -3165,13 +3169,21 @@ class action_menu implements renderable {
if ($output === null) {
$output = $OUTPUT;
}
$actions = $this->primaryactions;
$actions[] = $output->pix_icon(
$title = get_string('actions', 'moodle');
$pixicon = $output->pix_icon(
't/contextmenu',
get_string('actions', 'moodle'),
$title,
'moodle',
array('class' => 'toggle-display iconsmall')
array('class' => 'iconsmall')
);
$actions = $this->primaryactions;
$attributes = array(
'class' => 'toggle-display',
'title' => $title,
'id' => 'action-menu-toggle-'.$this->instance
);
$actions[] = html_writer::link('#', $pixicon, $attributes);
return $actions;
}
@@ -61,9 +61,9 @@ ACTIONMENU.prototype = {
Y.log('Initialising action menu manager', 'note', ACTIONMENU.NAME);
Y.all(SELECTOR.MENU).each(function() {
var menucontent = this.one(SELECTOR.MENUCONTENT);
menucontent.set('aria-hidden', true);
if (menucontent.hasChildNodes()) {
this.setAttribute('data-enhanced', '1');
this.setData('menucontent', menucontent);
}
});
BODY.delegate('click', this.toggleMenu, SELECTOR.MENU + ' ' + SELECTOR.TOGGLE, this);
@@ -76,7 +76,13 @@ ACTIONMENU.prototype = {
*/
hideMenu : function() {
if (this.dialogue) {
this.dialogue.hide();
this.dialogue.removeClass('show');
this.dialogue.one(SELECTOR.MENUCONTENT).set('aria-hidden', true);
this.dialogue = null;
}
if (this.owner) {
this.owner.removeClass(CSS.MENUSHOWN);
this.owner = null;
}
for (var i in this.events) {
if (this.events[i].detach) {
@@ -95,21 +101,27 @@ ACTIONMENU.prototype = {
// Stop all immediate propogation of the events we attach later will be
// triggered and the dialogue immediately hidden again.
e.halt(true);
this.showMenu(e.target.ancestor(SELECTOR.MENU), align = this.calculateAlign(e.target));
this.hideMenu();
this.showMenu(e.target.ancestor(SELECTOR.MENU));
// Close the menu if the user presses escape.
this.events.push(BODY.on('key', this.hideMenu, 'esc', this));
// Close the menu if the user clicks outside the menu.
this.events.push(BODY.on('click', this.hideIfOutside, this));
// Close the menu if the user focuses outside the menu.
this.events.push(BODY.delegate('focus', this.hideIfOutside, '*', this));
},
/**
* Calculates the alignment point for the menu.
* @param {Node} node
* @returns {{node: *, points: Array}}
* Hides the menu if the event happened outside the menu.
*
* @protected
* @method hideIfOutside
* @param {EventFacade} e
*/
calculateAlign : function(node) {
var points = [Y.WidgetPositionAlign.TR, Y.WidgetPositionAlign.BR];
if (BODY.hasClass('dir-rtl')) {
points = [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL];
hideIfOutside : function(e) {
if (!e.target.test('.secondary') && !e.target.ancestor('.secondary')) {
this.hideMenu();
}
return {node: node, points : points};
},
/**
@@ -118,67 +130,60 @@ ACTIONMENU.prototype = {
* @param Array align
* @returns {M.core.dialogue|dialogue}
*/
showMenu : function(menu, align) {
showMenu : function(menu) {
Y.log('Displaying action menu', 'note', ACTIONMENU.NAME);
var bodyContent = menu.getData('menucontent'),
ownerSelector = menu.getData('owner');
var ownerSelector = menu.getData('owner'),
menuContent = menu.one(SELECTOR.MENUCONTENT);
this.owner = (ownerSelector) ? menu.ancestor(ownerSelector) : null;
if (!this.dialogue) {
this.dialogue = new M.core.dialogue({
visible : false,
bodyContent : bodyContent,
align : align,
lightbox : false,
closeButton : false,
additionalBaseClass : 'action-menu-dialogue',
width : 'auto',
constrain : BODY,
hideOn : [
{
eventName: 'clickoutside'
}
]
});
this.dialogue.after('visibleChange', this.flagOwner, this);
this.flagOwner({attrName: 'visible', newVal: true});
} else {
if (this.dialogue.get('visible')) {
this.dialogue.hide();
}
this.dialogue.set('bodyContent', bodyContent);
this.dialogue.set('align', align);
this.dialogue.show();
}
return this.dialogue;
this.dialogue = menu;
menu.addClass('show');
this.owner.addClass(CSS.MENUSHOWN);
this.constrain(menuContent.set('aria-hidden', true));
return true;
},
/**
* Flags the owner appropriately when the visibility of the dialogue changes.
* @param {EventFacade} e
* Constrains the node to its the page width.
*
* @method constrain
* @param {Node} node
*/
flagOwner : function(e) {
if (this.owner && e.attrName === 'visible') {
if (e.newVal === true) {
this.owner.addClass(CSS.MENUSHOWN);
constrain : function(node) {
var x = node.getX(),
nodewidth = node.get('offsetWidth'),
winwidth = node.get('winWidth'),
newwidth = null,
newleft = null;
if (x < 0) {
x = 0;
newleft = 0;
} else if (x > winwidth) {
x = winwidth;
newleft = winwidth;
}
if (x + nodewidth > winwidth) {
if (nodewidth > winwidth) {
newleft = 0;
newwidth = winwidth;
} else {
this.owner.removeClass(CSS.MENUSHOWN);
this.owner = null;
newleft = winwidth - nodewidth;
}
}
if (newleft !== null) {
node.setX(newleft);
}
if (newwidth !== null) {
node.setStyle('width', newwidth.toString() + 'px');
}
}
};
Y.extend(ACTIONMENU, Y.Base, ACTIONMENU.prototype, {
NAME : 'moodle-core-actionmenu',
ATTRS : {
/**
* A selector to use to get the owner of the menu if there is one.
* @attribute owner
* @type String
*/
owner : {
value : null
}
}
});
@@ -208,4 +213,4 @@ M.core.actionmenu.init = M.core.actionmenu.init || function(params) {
};
}, '@VERSION@', {"requires": ["base", "event", "moodle-core-notification"]});
}, '@VERSION@', {"requires": ["base", "event"]});
@@ -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.hasChildNodes()&&(this.setAttribute("data-enhanced","1"),this.setData("menucontent",e))}),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.hide();for(var e in this.events)this.events[e].detach&&this.events[e].detach();this.events=[]},toggleMenu:function(e){e.halt(!0),this.showMenu(e.target.ancestor(i.MENU),align=this.calculateAlign(e.target)),this.events.push(n.on("key",this.hideMenu,"esc",this))},calculateAlign:function(t){var r=[e.WidgetPositionAlign.TR,e.WidgetPositionAlign.BR];return n.hasClass("dir-rtl")&&(r=[e.WidgetPositionAlign.TL,e.WidgetPositionAlign.BL]),{node:t,points:r}},showMenu:function(e,t){var r=e.getData("menucontent"),i=e.getData("owner");return this.owner=i?e.ancestor(i):null,this.dialogue?(this.dialogue.get("visible")&&this.dialogue.hide(),this.dialogue.set("bodyContent",r),this.dialogue.set("align",t),this.dialogue.show()):(this.dialogue=new M.core.dialogue({visible:!1,bodyContent:r,align:t,lightbox:!1,closeButton:!1,additionalBaseClass:"action-menu-dialogue",width:"auto",constrain:n,hideOn:[{eventName:"clickoutside"}]}),this.dialogue.after("visibleChange",this.flagOwner,this),this.flagOwner({attrName:"visible",newVal:!0})),this.dialogue},flagOwner:function(e){this.owner&&e.attrName==="visible"&&(e.newVal===!0?this.owner.addClass(r.MENUSHOWN):(this.owner.removeClass(r.MENUSHOWN),this.owner=null))}},e.extend(s,e.Base,s.prototype,{NAME:"moodle-core-actionmenu",ATTRS:{owner:{value:null}}}),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","moodle-core-notification"]});
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"]});
@@ -60,9 +60,9 @@ ACTIONMENU.prototype = {
initializer : function() {
Y.all(SELECTOR.MENU).each(function() {
var menucontent = this.one(SELECTOR.MENUCONTENT);
menucontent.set('aria-hidden', true);
if (menucontent.hasChildNodes()) {
this.setAttribute('data-enhanced', '1');
this.setData('menucontent', menucontent);
}
});
BODY.delegate('click', this.toggleMenu, SELECTOR.MENU + ' ' + SELECTOR.TOGGLE, this);
@@ -75,7 +75,13 @@ ACTIONMENU.prototype = {
*/
hideMenu : function() {
if (this.dialogue) {
this.dialogue.hide();
this.dialogue.removeClass('show');
this.dialogue.one(SELECTOR.MENUCONTENT).set('aria-hidden', true);
this.dialogue = null;
}
if (this.owner) {
this.owner.removeClass(CSS.MENUSHOWN);
this.owner = null;
}
for (var i in this.events) {
if (this.events[i].detach) {
@@ -94,21 +100,27 @@ ACTIONMENU.prototype = {
// Stop all immediate propogation of the events we attach later will be
// triggered and the dialogue immediately hidden again.
e.halt(true);
this.showMenu(e.target.ancestor(SELECTOR.MENU), align = this.calculateAlign(e.target));
this.hideMenu();
this.showMenu(e.target.ancestor(SELECTOR.MENU));
// Close the menu if the user presses escape.
this.events.push(BODY.on('key', this.hideMenu, 'esc', this));
// Close the menu if the user clicks outside the menu.
this.events.push(BODY.on('click', this.hideIfOutside, this));
// Close the menu if the user focuses outside the menu.
this.events.push(BODY.delegate('focus', this.hideIfOutside, '*', this));
},
/**
* Calculates the alignment point for the menu.
* @param {Node} node
* @returns {{node: *, points: Array}}
* Hides the menu if the event happened outside the menu.
*
* @protected
* @method hideIfOutside
* @param {EventFacade} e
*/
calculateAlign : function(node) {
var points = [Y.WidgetPositionAlign.TR, Y.WidgetPositionAlign.BR];
if (BODY.hasClass('dir-rtl')) {
points = [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL];
hideIfOutside : function(e) {
if (!e.target.test('.secondary') && !e.target.ancestor('.secondary')) {
this.hideMenu();
}
return {node: node, points : points};
},
/**
@@ -117,66 +129,59 @@ ACTIONMENU.prototype = {
* @param Array align
* @returns {M.core.dialogue|dialogue}
*/
showMenu : function(menu, align) {
var bodyContent = menu.getData('menucontent'),
ownerSelector = menu.getData('owner');
showMenu : function(menu) {
var ownerSelector = menu.getData('owner'),
menuContent = menu.one(SELECTOR.MENUCONTENT);
this.owner = (ownerSelector) ? menu.ancestor(ownerSelector) : null;
if (!this.dialogue) {
this.dialogue = new M.core.dialogue({
visible : false,
bodyContent : bodyContent,
align : align,
lightbox : false,
closeButton : false,
additionalBaseClass : 'action-menu-dialogue',
width : 'auto',
constrain : BODY,
hideOn : [
{
eventName: 'clickoutside'
}
]
});
this.dialogue.after('visibleChange', this.flagOwner, this);
this.flagOwner({attrName: 'visible', newVal: true});
} else {
if (this.dialogue.get('visible')) {
this.dialogue.hide();
}
this.dialogue.set('bodyContent', bodyContent);
this.dialogue.set('align', align);
this.dialogue.show();
}
return this.dialogue;
this.dialogue = menu;
menu.addClass('show');
this.owner.addClass(CSS.MENUSHOWN);
this.constrain(menuContent.set('aria-hidden', true));
return true;
},
/**
* Flags the owner appropriately when the visibility of the dialogue changes.
* @param {EventFacade} e
* Constrains the node to its the page width.
*
* @method constrain
* @param {Node} node
*/
flagOwner : function(e) {
if (this.owner && e.attrName === 'visible') {
if (e.newVal === true) {
this.owner.addClass(CSS.MENUSHOWN);
constrain : function(node) {
var x = node.getX(),
nodewidth = node.get('offsetWidth'),
winwidth = node.get('winWidth'),
newwidth = null,
newleft = null;
if (x < 0) {
x = 0;
newleft = 0;
} else if (x > winwidth) {
x = winwidth;
newleft = winwidth;
}
if (x + nodewidth > winwidth) {
if (nodewidth > winwidth) {
newleft = 0;
newwidth = winwidth;
} else {
this.owner.removeClass(CSS.MENUSHOWN);
this.owner = null;
newleft = winwidth - nodewidth;
}
}
if (newleft !== null) {
node.setX(newleft);
}
if (newwidth !== null) {
node.setStyle('width', newwidth.toString() + 'px');
}
}
};
Y.extend(ACTIONMENU, Y.Base, ACTIONMENU.prototype, {
NAME : 'moodle-core-actionmenu',
ATTRS : {
/**
* A selector to use to get the owner of the menu if there is one.
* @attribute owner
* @type String
*/
owner : {
value : null
}
}
});
@@ -206,4 +211,4 @@ M.core.actionmenu.init = M.core.actionmenu.init || function(params) {
};
}, '@VERSION@', {"requires": ["base", "event", "moodle-core-notification"]});
}, '@VERSION@', {"requires": ["base", "event"]});
+62 -57
View File
@@ -59,9 +59,9 @@ ACTIONMENU.prototype = {
Y.log('Initialising action menu manager', 'note', ACTIONMENU.NAME);
Y.all(SELECTOR.MENU).each(function() {
var menucontent = this.one(SELECTOR.MENUCONTENT);
menucontent.set('aria-hidden', true);
if (menucontent.hasChildNodes()) {
this.setAttribute('data-enhanced', '1');
this.setData('menucontent', menucontent);
}
});
BODY.delegate('click', this.toggleMenu, SELECTOR.MENU + ' ' + SELECTOR.TOGGLE, this);
@@ -74,7 +74,13 @@ ACTIONMENU.prototype = {
*/
hideMenu : function() {
if (this.dialogue) {
this.dialogue.hide();
this.dialogue.removeClass('show');
this.dialogue.one(SELECTOR.MENUCONTENT).set('aria-hidden', true);
this.dialogue = null;
}
if (this.owner) {
this.owner.removeClass(CSS.MENUSHOWN);
this.owner = null;
}
for (var i in this.events) {
if (this.events[i].detach) {
@@ -93,21 +99,27 @@ ACTIONMENU.prototype = {
// Stop all immediate propogation of the events we attach later will be
// triggered and the dialogue immediately hidden again.
e.halt(true);
this.showMenu(e.target.ancestor(SELECTOR.MENU), align = this.calculateAlign(e.target));
this.hideMenu();
this.showMenu(e.target.ancestor(SELECTOR.MENU));
// Close the menu if the user presses escape.
this.events.push(BODY.on('key', this.hideMenu, 'esc', this));
// Close the menu if the user clicks outside the menu.
this.events.push(BODY.on('click', this.hideIfOutside, this));
// Close the menu if the user focuses outside the menu.
this.events.push(BODY.delegate('focus', this.hideIfOutside, '*', this));
},
/**
* Calculates the alignment point for the menu.
* @param {Node} node
* @returns {{node: *, points: Array}}
* Hides the menu if the event happened outside the menu.
*
* @protected
* @method hideIfOutside
* @param {EventFacade} e
*/
calculateAlign : function(node) {
var points = [Y.WidgetPositionAlign.TR, Y.WidgetPositionAlign.BR];
if (BODY.hasClass('dir-rtl')) {
points = [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL];
hideIfOutside : function(e) {
if (!e.target.test('.secondary') && !e.target.ancestor('.secondary')) {
this.hideMenu();
}
return {node: node, points : points};
},
/**
@@ -116,67 +128,60 @@ ACTIONMENU.prototype = {
* @param Array align
* @returns {M.core.dialogue|dialogue}
*/
showMenu : function(menu, align) {
showMenu : function(menu) {
Y.log('Displaying action menu', 'note', ACTIONMENU.NAME);
var bodyContent = menu.getData('menucontent'),
ownerSelector = menu.getData('owner');
var ownerSelector = menu.getData('owner'),
menuContent = menu.one(SELECTOR.MENUCONTENT);
this.owner = (ownerSelector) ? menu.ancestor(ownerSelector) : null;
if (!this.dialogue) {
this.dialogue = new M.core.dialogue({
visible : false,
bodyContent : bodyContent,
align : align,
lightbox : false,
closeButton : false,
additionalBaseClass : 'action-menu-dialogue',
width : 'auto',
constrain : BODY,
hideOn : [
{
eventName: 'clickoutside'
}
]
});
this.dialogue.after('visibleChange', this.flagOwner, this);
this.flagOwner({attrName: 'visible', newVal: true});
} else {
if (this.dialogue.get('visible')) {
this.dialogue.hide();
}
this.dialogue.set('bodyContent', bodyContent);
this.dialogue.set('align', align);
this.dialogue.show();
}
return this.dialogue;
this.dialogue = menu;
menu.addClass('show');
this.owner.addClass(CSS.MENUSHOWN);
this.constrain(menuContent.set('aria-hidden', true));
return true;
},
/**
* Flags the owner appropriately when the visibility of the dialogue changes.
* @param {EventFacade} e
* Constrains the node to its the page width.
*
* @method constrain
* @param {Node} node
*/
flagOwner : function(e) {
if (this.owner && e.attrName === 'visible') {
if (e.newVal === true) {
this.owner.addClass(CSS.MENUSHOWN);
constrain : function(node) {
var x = node.getX(),
nodewidth = node.get('offsetWidth'),
winwidth = node.get('winWidth'),
newwidth = null,
newleft = null;
if (x < 0) {
x = 0;
newleft = 0;
} else if (x > winwidth) {
x = winwidth;
newleft = winwidth;
}
if (x + nodewidth > winwidth) {
if (nodewidth > winwidth) {
newleft = 0;
newwidth = winwidth;
} else {
this.owner.removeClass(CSS.MENUSHOWN);
this.owner = null;
newleft = winwidth - nodewidth;
}
}
if (newleft !== null) {
node.setX(newleft);
}
if (newwidth !== null) {
node.setStyle('width', newwidth.toString() + 'px');
}
}
};
Y.extend(ACTIONMENU, Y.Base, ACTIONMENU.prototype, {
NAME : 'moodle-core-actionmenu',
ATTRS : {
/**
* A selector to use to get the owner of the menu if there is one.
* @attribute owner
* @type String
*/
owner : {
value : null
}
}
});
+1 -2
View File
@@ -2,8 +2,7 @@
"moodle-core-actionmenu": {
"requires": [
"base",
"event",
"moodle-core-notification"
"event"
]
}
}
+24 -24
View File
@@ -1373,30 +1373,30 @@ div.badge .expireimage { width: 100px; height: 100px; left: 20px; top: 0px; }
.path-mod-lesson .centerpadded { padding: 5px; text-align: center; }
.moodle-actionmenu .iconsmall {vertical-align: top;margin:0 3px;}
.moodle-actionmenu,
.moodle-actionmenu .secondary {display: inline-block;}
.moodle-actionmenu .toggle-display,
.moodle-actionmenu .menu-action-text {display: none;}
.jsenabled .block .editing_move {display: none;}
.jsenabled .moodle-actionmenu [data-rel=menu-content] {display: none;margin-top: 4px;}
.moodle-actionmenu .toggle-display {display: none;padding-right: 4px;padding-left: 4px;}
.jsenabled .moodle-actionmenu .toggle-display {display: inline;opacity: 0.5;filter: alpha(opacity=50);}
.moodle-actionmenu[data-enhanced] .toggle-display {opacity: 1;filter: alpha(opacity=100);}
.statuses .actionlinktext {display: none;}
.action-menu-dialogue {min-width:300px;}
.action-menu-dialogue .moodle-dialogue-wrap {margin-top: 4px;margin-left: 4px;-webkit-border-radius: 4px;-moz-border-radius: 4px;border-radius: 4px;}
.action-menu-dialogue .moodle-dialogue .moodle-dialogue-bd {padding: 0;}
.action-menu-dialogue .moodle-dialogue-hd,
.action-menu-dialogue .moodle-dialogue-ft {display: none;}
.action-menu-dialogue a {display: block;padding: 2px 1em;color: #333333;}
.action-menu-dialogue a.hidden {display: none;}
.action-menu-dialogue .iconsmall {margin-right:8px;}
.action-menu-dialogue a:hover,
.action-menu-dialogue a:focus {color: #ffffff;background-color: #0088cc;}
.action-menu-dialogue 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;}
.action-menu-dialogue 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;}
.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[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;}
.action-menu-shown .moodle-actionmenu[data-enhanced] .toggle-display {background-color: #FFF;}
.block .moodle-actionmenu {text-align: right;}
.dir-rtl .block moodle-actionmenu {text-align: left;}
.dir-rtl .block moodle-actionmenu {text-align: left;}
.dir-rtl .action-menu-dialogue a {padding:2px 0.5em 2px 1em;}
.dir-rtl .action-menu-dialogue .iconsmall {margin-right:0;margin-left:8px;}
.dir-rtl .moodle-actionmenu .toggle-display {padding-left:0;padding-right:4px;}
.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;}
+2 -2
View File
@@ -28,8 +28,8 @@
.dir-rtl .course-content .section .activity .activityinstance { padding-right: 0; padding-left: 3em;}
.sitetopic .section .activity .commands,
.course-content .section .activity .commands { white-space: nowrap; display: inline; }
.sitetopic .section .activity .commands img,
.course-content .section .activity .commands img { vertical-align: baseline; padding: 0 2px; }
.section .activity .moodle-actionmenu .iconsmall {ertical-align: baseline;width:16px;height:16px;width:1rem;height:1rem;padding:0 0.5em 0.3em;}
.sitetopic .section li.activity,
.course-content .section li.activity {padding: .2em;}
.section .activity .activityinstance .groupinglabel { padding-left: .45em; }
@@ -20,6 +20,7 @@
padding: 3px 5px;
}
.block .header .block_action {
padding:4px;
float: right;
}
.block .header .commands {
+88 -99
View File
@@ -1911,121 +1911,110 @@ div.badge .expireimage {
margin: 0;
}
.jsenabled .block .editing_move {
display:none;
.moodle-actionmenu,
.moodle-actionmenu .secondary {
display: inline-block;
}
.jsenabled .moodle-actionmenu [data-rel=menu-content] {
display:none;
margin-top: 4px;
}
.moodle-actionmenu .toggle-display {
padding-left: 4px;
.moodle-actionmenu .toggle-display,
.moodle-actionmenu .menu-action-text {
display: none; /** Hidden by default, display none so that we don't take up space. **/
cursor:auto;
}
.jsenabled .moodle-actionmenu .toggle-display {
display: inline; /** JS is enabled, we'll be using it so return display to normal **/
.opacity(50);
.jsenabled {
.block .editing_move {
display:none;
}
.moodle-actionmenu {
display: block;
.secondary {
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);
}
.menu-action-text {
display:inline;
}
}
}
.moodle-actionmenu[data-enhanced] .toggle-display {
.opacity(100);
.moodle-actionmenu[data-enhanced].show {
position: relative;
.secondary {
position: absolute;
top: 100%;
right: 0;
left: auto;
background-color: #fff;
border: 1px solid #ccc;
z-index:1000;
.border-radius(5px);
.box-shadow(5px 5px 20px 0 #666);
a {
display: block;
color: @dropdownLinkColor;
padding:2px 1em 2px 0.5em;
&:hover,
&:focus {
color: @dropdownLinkColorHover;
background-color: @dropdownLinkBackgroundHover;
}
&:first-child {
.border-top-radius(4px);
}
&:last-child {
.border-bottom-radius(4px);
}
}
a.hidden {
display: none;
}
img {
vertical-align: middle;
}
.iconsmall {
margin-right:8px;
}
}
}
.action-menu-shown .moodle-actionmenu[data-enhanced] .toggle-display {
background-color: #FFF;
}
.moodle-actionmenu,
.moodle-actionmenu .secondary {
display: inline-block;
}
.jsenabled .moodle-actionmenu,
.jsenabled .moodle-actionmenu .secondary {
display: block;
}
.moodle-actionmenu .menu-action-text {
display:none;
}
.jsenabled .moodle-actionmenu[data-enhanced] .menu-action-text {
display:inline;
}
.block .moodle-actionmenu {
text-align: right;
}
.jsenabled #page .moodle-actionmenu .secondary {
display: none;
}
.action-menu-dialogue {
.moodle-dialogue-wrap {
margin-top:4px;
margin-left:4px;
.border-radius(4px);
}
.moodle-dialogue {
.moodle-dialogue-bd {
padding: 0;
}
}
.moodle-dialogue-hd,
.moodle-dialogue-ft {
display: none;
}
a {
display: block;
color: @dropdownLinkColor;
padding:2px 1em 2px 0.5em;
&:hover,
&:focus {
color: @dropdownLinkColorHover;
background-color: @dropdownLinkBackgroundHover;
}
&:first-child {
.border-top-radius(4px);
}
&:last-child {
.border-bottom-radius(4px);
}
}
a.hidden {
display: none;
}
img {
vertical-align: middle;
}
.iconsmall {
margin-right:8px;
}
}
.safari .action-menu-dialogue .moodle-dialogue {
/** Safari specific bug here **/
white-space: nowrap;
}
.dir-rtl {
.moodle-actionmenu[data-enhanced].show {
.secondary {
left: 0;
right: auto;
.iconsmall {
margin-right:0;
margin-left:8px;
}
}
}
.block .moodle-actionmenu {
text-align: left;
}
.action-menu-dialogue {
a {
padding:2px 0.5em 2px 1em;
}
.iconsmall {
margin-right:0;
margin-left:8px;
}
}
.moodle-actionmenu .toggle-display {
padding-left:0;
padding-right:4px;
text-align: right;
}
}
+1 -2
View File
@@ -596,8 +596,7 @@ span.editinstructions {
margin: 10px 0 20px;
}
.section .activity .moodle-actionmenu .iconsmall,
.section .activity .moodle-actionmenu .toggle-display {
.section .activity .moodle-actionmenu .iconsmall {
width:16px;
height:16px;
width:1rem;
File diff suppressed because one or more lines are too long
+13
View File
@@ -1,6 +1,19 @@
This files describes API changes in /theme/* themes,
information provided here is intended especially for theme designer.
=== 2.6 ===
Notes:
* A new component action_menu is now used to display editing icons for courses and blocks within a drop down. If you have a theme that doesn't
extend base, canvas, or clean then you will need to style for this new component within your theme.
Renderer changes:
* core_course_renderer::course_section_cm_edit_actions has two new optional arguments and now uses and action_menu component.
* core_course_renderer::course_section_cm has been altered to call core_course_renderer::course_section_cm_edit_actions with the two new arguments.
* core_renderer::block_controls has a new optional argument (the block id) and has been altered to use the new action_menu component.
* core_renderer::block_header has been altered to give core_renderer::block_controls the new second argument, the block id.
* core_renderer::action_link has a new argument, and optional icon that can be rendererd into the link.
=== 2.5.1 ===
Notes: