MDL-39814 frontend: improved display of activities and the menu
This commit is contained in:
+11
-11
@@ -1808,7 +1808,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
|
||||
new moodle_url($baseurl, array('update' => $mod->id)),
|
||||
$str->edittitle,
|
||||
null,
|
||||
array('class' => 'editing_title', 'title' => $str->edittitle),
|
||||
array('class' => 'editing_title', 'title' => $str->edittitle, 'data-action' => 'edittitle'),
|
||||
new pix_icon('t/editstring', $str->edittitle, 'moodle', array('class' => 'iconsmall visibleifjs', 'title' => ''))
|
||||
);
|
||||
}
|
||||
@@ -1831,7 +1831,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
|
||||
new moodle_url($baseurl, array('id' => $mod->id, 'indent' => '-1')),
|
||||
$str->moveleft,
|
||||
null,
|
||||
array('class' => 'editing_moveleft ' . $hiddenclass, 'title' => $str->moveleft),
|
||||
array('class' => 'editing_moveleft ' . $hiddenclass, 'title' => $str->moveleft, 'data-action' => 'moveleft'),
|
||||
new pix_icon($leftarrow, $str->moveleft, 'moodle', array('class' => 'iconsmall', 'title' => ''))
|
||||
);
|
||||
$hiddenclass = 'hidden';
|
||||
@@ -1842,7 +1842,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
|
||||
new moodle_url($baseurl, array('id' => $mod->id, 'indent' => '1')),
|
||||
$str->moveright,
|
||||
null,
|
||||
array('class' => 'editing_moveright ' . $hiddenclass, 'title' => $str->moveright),
|
||||
array('class' => 'editing_moveright ' . $hiddenclass, 'title' => $str->moveright, 'data-action' => 'moveright'),
|
||||
new pix_icon($rightarrow, $str->moveright, 'moodle', array('class' => 'iconsmall', 'title' => ''))
|
||||
);
|
||||
}
|
||||
@@ -1853,7 +1853,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
|
||||
new moodle_url($baseurl, array('copy' => $mod->id)),
|
||||
$str->move,
|
||||
null,
|
||||
array('class' => 'editing_move status', 'title' => $str->move),
|
||||
array('class' => 'editing_move status', 'title' => $str->move, 'data-action' => 'move'),
|
||||
new pix_icon('t/move', $str->move, 'moodle', array('class' => 'iconsmall', 'title' => ''))
|
||||
);
|
||||
}
|
||||
@@ -1864,7 +1864,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
|
||||
new moodle_url($baseurl, array('update' => $mod->id)),
|
||||
$str->update,
|
||||
null,
|
||||
array('class' => 'editing_update', 'title' => $str->update),
|
||||
array('class' => 'editing_update', 'title' => $str->update, 'data-action' => 'update'),
|
||||
new pix_icon('t/edit', $str->update, 'moodle', array('class' => 'iconsmall', 'title' => ''))
|
||||
);
|
||||
}
|
||||
@@ -1877,7 +1877,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
|
||||
new moodle_url($baseurl, array('duplicate' => $mod->id)),
|
||||
$str->duplicate,
|
||||
null,
|
||||
array('class' => 'editing_duplicate', 'title' => $str->duplicate),
|
||||
array('class' => 'editing_duplicate', 'title' => $str->duplicate, 'data-action' => 'duplicate'),
|
||||
new pix_icon('t/copy', $str->duplicate, 'moodle', array('class' => 'iconsmall', 'title' => ''))
|
||||
);
|
||||
}
|
||||
@@ -1888,7 +1888,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
|
||||
new moodle_url($baseurl, array('delete' => $mod->id)),
|
||||
$str->delete,
|
||||
null,
|
||||
array('class' => 'editing_delete', 'title' => $str->delete),
|
||||
array('class' => 'editing_delete', 'title' => $str->delete, 'data-action' => 'delete'),
|
||||
new pix_icon('t/delete', $str->delete, 'moodle', array('class' => 'iconsmall', 'title' => ''))
|
||||
);
|
||||
}
|
||||
@@ -1900,7 +1900,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
|
||||
new moodle_url($baseurl, array('hide' => $mod->id)),
|
||||
$str->hide,
|
||||
null,
|
||||
array('class' => 'editing_hide', 'title' => $str->hide),
|
||||
array('class' => 'editing_hide', 'title' => $str->hide, 'data-action' => 'hide'),
|
||||
new pix_icon('t/hide', $str->hide, 'moodle', array('class' => 'iconsmall', 'title' => ''))
|
||||
);
|
||||
$actions['hide']->add_class('status');
|
||||
@@ -1909,7 +1909,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
|
||||
new moodle_url($baseurl, array('show' => $mod->id)),
|
||||
$str->show,
|
||||
null,
|
||||
array('class' => 'editing_show', 'title' => $str->show),
|
||||
array('class' => 'editing_show', 'title' => $str->show, 'data-action' => 'show'),
|
||||
new pix_icon('t/show', $str->show, 'moodle', array('class' => 'iconsmall', 'title' => ''))
|
||||
);
|
||||
$actions['show']->add_class('status');
|
||||
@@ -1947,7 +1947,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
|
||||
new moodle_url($baseurl, array('id' => $mod->id, 'groupmode' => $groupmode)),
|
||||
$grouptitle,
|
||||
null,
|
||||
array('class' => 'editing_'. $actionname, 'title' => $grouptitle),
|
||||
array('class' => 'editing_'. $actionname, 'title' => $grouptitle, 'data-action' => $actionname, 'data-groupmode' => $groupmode),
|
||||
new pix_icon($groupimage, $grouptitle, 'moodle', array('class' => 'iconsmall', 'title' => ''))
|
||||
);
|
||||
} else {
|
||||
@@ -1962,7 +1962,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
|
||||
new moodle_url('/admin/roles/assign.php', array('contextid' => $modcontext->id)),
|
||||
$str->assign,
|
||||
null,
|
||||
array('class' => 'editing_assign', 'title' => $str->assign),
|
||||
array('class' => 'editing_assign', 'title' => $str->assign, 'data-action' => 'assignroles'),
|
||||
new pix_icon('t/assignroles', $str->assign, 'moodle', array('class' => 'iconsmall', 'title' => ''))
|
||||
);
|
||||
}
|
||||
|
||||
+34
-28
@@ -325,28 +325,40 @@ class core_course_renderer extends plugin_renderer_base {
|
||||
*
|
||||
* @see course_get_cm_edit_actions()
|
||||
*
|
||||
* @param array $actions array of action_link objects
|
||||
* @param action_link[] $actions Array of action_link objects
|
||||
* @param cm_info $mod The module we are displaying actions for.
|
||||
* @param array $displayoptions additional display options:
|
||||
* ownerselector => A JS/CSS selector that can be used to find an cm node.
|
||||
* If specified the owning node will be given the class 'action-menu-shown' when the action
|
||||
* menu is being displayed.
|
||||
* @return string
|
||||
*/
|
||||
public function course_section_cm_edit_actions($actions) {
|
||||
$this->page->requires->yui_module('moodle-core-actionmenu', 'M.core.actionmenu.init');
|
||||
$output = html_writer::start_tag('span', array('class' => 'actionmenu'));
|
||||
$output .= html_writer::start_tag('span', array('class' => 'statuses'));
|
||||
public function course_section_cm_edit_actions($actions, cm_info $mod = null, $displayoptions = array()) {
|
||||
if (empty($actions)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (isset($displayoptions['ownerselector'])) {
|
||||
$ownerselector = $displayoptions['ownerselector'];
|
||||
} else if ($mod) {
|
||||
$ownerselector = '#module-'.$mod->id;
|
||||
} else {
|
||||
debugging('You should upgrade your call to '.__FUNCTION__.' and provide $mod', DEBUG_DEVELOPER);
|
||||
$ownerselector = 'li.activity';
|
||||
}
|
||||
|
||||
$menu = new action_menu();
|
||||
$menu->set_owner_selector($ownerselector);
|
||||
foreach ($actions as $action) {
|
||||
$action->add_class('cm-edit-action');
|
||||
if ($action->has_class('status')) {
|
||||
$output .= $this->output->render($action);
|
||||
$menu->add_primary_action($action);
|
||||
} else {
|
||||
$menu->add_secondary_action($action);
|
||||
}
|
||||
}
|
||||
$output .= html_writer::end_tag('span');
|
||||
$output .= html_writer::start_tag('span', array('class' => 'actions'));
|
||||
foreach ($actions as $action) {
|
||||
if (!$action->has_class('status')) {
|
||||
$output .= $this->output->render($action);
|
||||
}
|
||||
}
|
||||
$output .= html_writer::end_tag('span');
|
||||
$output .= html_writer::end_tag('span');
|
||||
return $output;
|
||||
$menu->attributes['class'] .= ' section-cm-edit-actions commands';
|
||||
return $this->render($menu);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -868,7 +880,7 @@ class core_course_renderer extends plugin_renderer_base {
|
||||
return $output;
|
||||
}
|
||||
|
||||
$indentclasses = 'mod-indent clearfix';
|
||||
$indentclasses = 'mod-indent';
|
||||
if (!empty($mod->indent)) {
|
||||
$indentclasses .= ' mod-indent-'.$mod->indent;
|
||||
if ($mod->indent > 15) {
|
||||
@@ -901,11 +913,14 @@ class core_course_renderer extends plugin_renderer_base {
|
||||
$output .= $contentpart;
|
||||
}
|
||||
|
||||
// Display completion first - so it is the right most floated element (and will align vertically).
|
||||
if ($this->page->user_is_editing()) {
|
||||
$editactions = course_get_cm_edit_actions($mod, $mod->indent, $sectionreturn);
|
||||
$output .= ' '. $this->course_section_cm_edit_actions($editactions, $mod, $displayoptions);
|
||||
$output .= $mod->get_after_edit_icons();
|
||||
}
|
||||
|
||||
$output .= $this->course_section_cm_completion($course, $completioninfo, $mod, $displayoptions);
|
||||
|
||||
|
||||
// If there is content AND a link, then display the content here
|
||||
// (AFTER any icons). Otherwise it was displayed before
|
||||
if (!empty($url)) {
|
||||
@@ -915,15 +930,6 @@ class core_course_renderer extends plugin_renderer_base {
|
||||
// show availability info (if module is not available)
|
||||
$output .= $this->course_section_cm_availability($mod, $displayoptions);
|
||||
|
||||
// Now action icons (if editing).
|
||||
if ($this->page->user_is_editing()) {
|
||||
$editactions = course_get_cm_edit_actions($mod, $mod->indent, $sectionreturn);
|
||||
$output .= ' '. $this->course_section_cm_edit_actions($editactions);
|
||||
$output .= $mod->get_after_edit_icons();
|
||||
}
|
||||
|
||||
// Add a clear div so the container includes all floated elements.
|
||||
|
||||
$output .= html_writer::end_tag('div'); // $indentclasses
|
||||
return $output;
|
||||
}
|
||||
|
||||
Vendored
+2
-3
@@ -2,8 +2,7 @@ YUI.add('moodle-course-dragdrop', function(Y) {
|
||||
|
||||
var CSS = {
|
||||
ACTIVITY : 'activity',
|
||||
COMMANDSPAN : 'span.actionmenu',
|
||||
SPINNERCOMMANDSPAN : 'span.instancename',
|
||||
COMMANDSPAN : '.commands',
|
||||
CONTENT : 'content',
|
||||
COURSECONTENT : 'course-content',
|
||||
EDITINGMOVE : 'editing_move',
|
||||
@@ -352,7 +351,7 @@ YUI.add('moodle-course-dragdrop', function(Y) {
|
||||
var dropnode = e.drop.get('node');
|
||||
|
||||
// Add spinner if it not there
|
||||
var spinner = M.util.add_spinner(Y, dragnode.one(CSS.SPINNERCOMMANDSPAN));
|
||||
var spinner = M.util.add_spinner(Y, dragnode.one(CSS.COMMANDSPAN));
|
||||
|
||||
var params = {};
|
||||
|
||||
|
||||
Vendored
+428
-363
@@ -1,44 +1,47 @@
|
||||
YUI.add('moodle-course-toolboxes', function(Y) {
|
||||
WAITICON = {'pix':"i/loading_small",'component':'moodle'};
|
||||
// The CSS selectors we use
|
||||
|
||||
// The following properties contain common strings.
|
||||
// We separate them out here because when this JS is minified the content is less as
|
||||
// Variables get compacted to single/double characters and the full length of the string
|
||||
// exists only once.
|
||||
|
||||
// The CSS classes we use.
|
||||
var CSS = {
|
||||
ACTIVITYLI : 'li.activity',
|
||||
COMMANDSPAN : 'span.actionmenu',
|
||||
ACTIONPREFIX : 'span.actions',
|
||||
SPINNERCOMMANDSPAN : 'span.instancename',
|
||||
CONTENTAFTERLINK : 'div.contentafterlink',
|
||||
DELETE : 'a.editing_delete',
|
||||
ACTIVITYINSTANCE : 'activityinstance',
|
||||
AVAILABILITYINFODIV : 'div.availabilityinfo',
|
||||
CONDITIONALHIDDEN : 'conditionalhidden',
|
||||
DIMCLASS : 'dimmed',
|
||||
DIMMEDTEXT : 'dimmed_text',
|
||||
EDITTITLE : 'a.editing_title',
|
||||
EDITTITLECLASS : 'edittitle',
|
||||
GENERICICONCLASS : 'iconsmall',
|
||||
GROUPSNONE : 'a.editing_groupsnone',
|
||||
GROUPSSEPARATE : 'a.editing_groupsseparate',
|
||||
GROUPSVISIBLE : 'a.editing_groupsvisible',
|
||||
EDITINSTRUCTIONS : 'editinstructions',
|
||||
HIDE : 'hide',
|
||||
MODINDENTCOUNT : 'mod-indent-',
|
||||
MODINDENTHUGE : 'mod-indent-huge',
|
||||
MODULEIDPREFIX : 'module-',
|
||||
SECTIONHIDDENCLASS : 'hidden',
|
||||
SECTIONIDPREFIX : 'section-',
|
||||
SHOW : 'editing_show',
|
||||
TITLEEDITOR : 'titleeditor'
|
||||
},
|
||||
// The CSS selectors we use.
|
||||
SELECTOR = {
|
||||
ACTIONLINKTEXT : '.actionlinktext',
|
||||
ACTIVITYACTION : 'a.cm-edit-action[data-action]',
|
||||
ACTIVITYFORM : 'form.'+CSS.ACTIVITYINSTANCE,
|
||||
ACTIVITYICON : 'img.activityicon',
|
||||
ACTIVITYLI : 'li.activity',
|
||||
ACTIVITYTITLE : 'input[name=title]',
|
||||
COMMANDSPAN : '.commands',
|
||||
CONTENTAFTERLINK : 'div.contentafterlink',
|
||||
HIDE : 'a.editing_hide',
|
||||
HIGHLIGHT : 'a.editing_highlight',
|
||||
INSTANCENAME : 'span.instancename',
|
||||
LIGHTBOX : 'lightbox',
|
||||
MODINDENTCOUNT : 'mod-indent-',
|
||||
MODINDENTDIV : 'div.mod-indent',
|
||||
MODINDENTHUGE : 'mod-indent-huge',
|
||||
MODULEIDPREFIX : 'module-',
|
||||
MOVELEFT : 'a.editing_moveleft',
|
||||
MOVELEFTCLASS : 'editing_moveleft',
|
||||
MOVERIGHT : 'a.editing_moveright',
|
||||
PAGECONTENT : 'body',
|
||||
RIGHTSIDE : '.right',
|
||||
SECTIONHIDDENCLASS : 'hidden',
|
||||
SECTIONIDPREFIX : 'section-',
|
||||
PAGECONTENT : 'div#page-content',
|
||||
SECTIONLI : 'li.section',
|
||||
SHOW : 'a.editing_show',
|
||||
SHOWHIDE : 'a.editing_showhide',
|
||||
CONDITIONALHIDDEN : 'conditionalhidden',
|
||||
AVAILABILITYINFODIV : 'div.availabilityinfo',
|
||||
SHOWCLASS : 'editing_show',
|
||||
HIDECLASS : 'hide'
|
||||
};
|
||||
SHOW : 'a.'+CSS.SHOW,
|
||||
SHOWHIDE : 'a.editing_showhide'
|
||||
},
|
||||
BODY = Y.one(document.body);
|
||||
|
||||
/**
|
||||
* The toolbox classes
|
||||
@@ -52,98 +55,6 @@ YUI.add('moodle-course-toolboxes', function(Y) {
|
||||
}
|
||||
|
||||
Y.extend(TOOLBOX, Y.Base, {
|
||||
/**
|
||||
* Toggle the visibility and availability for the specified
|
||||
* resource show/hide button
|
||||
*/
|
||||
toggle_hide_resource_ui : function(button) {
|
||||
var element = this.get_activity_container(button);
|
||||
var hideicon = button.one('img');
|
||||
|
||||
var dimarea;
|
||||
var toggle_class;
|
||||
if (this.get_instance_name(element) == null) {
|
||||
toggle_class = CSS.DIMMEDTEXT;
|
||||
dimarea = element.all(CSS.MODINDENTDIV + ' > div').item(1);
|
||||
} else {
|
||||
toggle_class = CSS.DIMCLASS;
|
||||
dimarea = element.one('a');
|
||||
}
|
||||
|
||||
var status = '';
|
||||
var value;
|
||||
if (button.hasClass(CSS.SHOWCLASS)) {
|
||||
status = 'hide';
|
||||
value = 1;
|
||||
} else {
|
||||
status = 'show';
|
||||
value = 0;
|
||||
}
|
||||
// Update button info.
|
||||
var newstring = M.util.get_string(status, 'moodle');
|
||||
hideicon.setAttrs({
|
||||
'alt' : newstring,
|
||||
'src' : M.util.image_url('t/' + status)
|
||||
});
|
||||
button.set('title', newstring);
|
||||
button.set('className', 'editing_'+status);
|
||||
|
||||
// If activity is conditionally hidden, then don't toggle.
|
||||
if (!dimarea.hasClass(CSS.CONDITIONALHIDDEN)) {
|
||||
// Change the UI.
|
||||
dimarea.toggleClass(toggle_class);
|
||||
// We need to toggle dimming on the description too.
|
||||
element.all(CSS.CONTENTAFTERLINK).toggleClass(CSS.DIMMEDTEXT);
|
||||
}
|
||||
// Toggle availablity info for conditional activities.
|
||||
var availabilityinfo = element.one(CSS.AVAILABILITYINFODIV);
|
||||
|
||||
if (availabilityinfo) {
|
||||
availabilityinfo.toggleClass(CSS.HIDECLASS);
|
||||
}
|
||||
return value;
|
||||
},
|
||||
get_activity_action_link : function(node, selector) {
|
||||
// The node is either a direct descendant of the activity container,
|
||||
// or it is linked through the actionmenu.
|
||||
|
||||
Y.log('find activity container');
|
||||
var element = node.one(selector);
|
||||
|
||||
if (element) {
|
||||
Y.log('direct ancestor ' + element);
|
||||
return element;
|
||||
}
|
||||
|
||||
var actionmenulink = node.one('a.actionmenu');
|
||||
Y.log('get action menu link ' + actionmenulink);
|
||||
var overlay = actionmenulink.getData('actionmenu-menu');
|
||||
|
||||
element = overlay.get('boundingBox').one(selector);
|
||||
Y.log('get ancestor ' + element);
|
||||
return element;
|
||||
},
|
||||
|
||||
get_activity_container : function(node) {
|
||||
// The node is either a direct descendant of the activity container,
|
||||
// or it is linked through the actionmenu.
|
||||
|
||||
Y.log('find activity container');
|
||||
var element = node.ancestor(CSS.ACTIVITYLI);
|
||||
|
||||
if (element) {
|
||||
Y.log('direct ancestor ' + element);
|
||||
return element;
|
||||
}
|
||||
|
||||
var actionlink = node.ancestor('a');
|
||||
Y.log('get action link ' + actionlink);
|
||||
var actionmenulink = actionlink.getData('actionmenu-link');
|
||||
Y.log('get menu link ' + actionmenulink);
|
||||
element = actionmenulink.ancestor(CSS.ACTIVITYLI);
|
||||
Y.log('get ancestor ' + element);
|
||||
return element;
|
||||
},
|
||||
/**
|
||||
* Send a request using the REST API
|
||||
*
|
||||
@@ -222,8 +133,8 @@ YUI.add('moodle-course-toolboxes', function(Y) {
|
||||
* @return string|null Instance name
|
||||
*/
|
||||
get_instance_name : function(target) {
|
||||
if (target.one(CSS.INSTANCENAME)) {
|
||||
return target.one(CSS.INSTANCENAME).get('firstChild').get('data');
|
||||
if (target.one(SELECTOR.INSTANCENAME)) {
|
||||
return target.one(SELECTOR.INSTANCENAME).get('firstChild').get('data');
|
||||
}
|
||||
return null;
|
||||
},
|
||||
@@ -263,81 +174,157 @@ YUI.add('moodle-course-toolboxes', function(Y) {
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Resource and activity toolbox class.
|
||||
*
|
||||
* This class is responsible for managing AJAX interactions with activities and resources
|
||||
* when viewing a course in editing mode.
|
||||
*
|
||||
* @namespace M.course.toolbox
|
||||
* @class ResourceToolbox
|
||||
* @constructor
|
||||
*/
|
||||
var RESOURCETOOLBOX = function() {
|
||||
RESOURCETOOLBOX.superclass.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
Y.extend(RESOURCETOOLBOX, TOOLBOX, {
|
||||
// Variables
|
||||
/**
|
||||
* No groups are being used.
|
||||
* @static
|
||||
* @const GROUPS_NONE
|
||||
* @type Number
|
||||
*/
|
||||
GROUPS_NONE : 0,
|
||||
/**
|
||||
* Separate groups are being used.
|
||||
* @static
|
||||
* @const GROUPS_SEPARATE
|
||||
* @type Number
|
||||
*/
|
||||
GROUPS_SEPARATE : 1,
|
||||
/**
|
||||
* Visible groups are being used.
|
||||
* @static
|
||||
* @const GROUPS_VISIBLE
|
||||
* @type Number
|
||||
*/
|
||||
GROUPS_VISIBLE : 2,
|
||||
|
||||
/**
|
||||
* Events that were added when editing a title.
|
||||
* These should all be detached when editing is complete.
|
||||
* @property edittitleevents
|
||||
* @type {Event[]}
|
||||
* @protected
|
||||
*/
|
||||
edittitleevents : [],
|
||||
|
||||
/**
|
||||
* Initialize the resource toolbox
|
||||
*
|
||||
* Updates all span.commands with relevant handlers and other required changes
|
||||
* For each activity the commands are updated and a reference to the activity is attached.
|
||||
* This way it doesn't matter where the commands are going to called from they have a reference to the
|
||||
* activity that they relate to.
|
||||
* This is essential as some of the actions are displayed in an actionmenu which removes them from the
|
||||
* page flow.
|
||||
*
|
||||
* This function also creates a single event delegate to manage all AJAX actions for all activities on
|
||||
* the page.
|
||||
*
|
||||
* @method initializer
|
||||
*/
|
||||
initializer : function(config) {
|
||||
this.setup_for_resource();
|
||||
M.course.coursebase.register_module(this);
|
||||
|
||||
var prefix = CSS.ACTIVITYLI + ' ' + CSS.COMMANDSPAN + ' ';
|
||||
Y.delegate('click', this.edit_resource_title, CSS.PAGECONTENT, CSS.EDITTITLE, this);
|
||||
Y.delegate('click', this.move_left, CSS.PAGECONTENT, CSS.MOVELEFT, this);
|
||||
Y.delegate('click', this.move_right, CSS.PAGECONTENT, CSS.MOVERIGHT, this);
|
||||
Y.delegate('click', this.delete_resource, CSS.PAGECONTENT, prefix + CSS.DELETE, this);
|
||||
Y.delegate('click', this.toggle_hide_resource, CSS.PAGECONTENT, prefix + CSS.HIDE, this);
|
||||
Y.delegate('click', this.toggle_hide_resource, CSS.PAGECONTENT, prefix + CSS.SHOW, this);
|
||||
Y.delegate('click', this.toggle_groupmode, CSS.PAGECONTENT, prefix + CSS.GROUPSNONE, this);
|
||||
Y.delegate('click', this.toggle_groupmode, CSS.PAGECONTENT, prefix + CSS.GROUPSSEPARATE, this);
|
||||
Y.delegate('click', this.toggle_groupmode, CSS.PAGECONTENT, prefix + CSS.GROUPSVISIBLE, this);
|
||||
Y.all(SELECTOR.ACTIVITYLI).each(function(activity){
|
||||
activity.all(SELECTOR.COMMANDSPAN+ ' ' + SELECTOR.ACTIVITYACTION).each(function(){
|
||||
this.setData('activity', activity);
|
||||
});
|
||||
}, this);
|
||||
Y.delegate('click', this.handle_data_action, BODY, SELECTOR.ACTIVITYACTION, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Update any span.commands within the scope of the specified
|
||||
* selector with AJAX equivelants
|
||||
* Handles the delegation event. When this is fired someone has triggered an action.
|
||||
*
|
||||
* @param baseselector The selector to limit scope to
|
||||
* @return void
|
||||
* Note not all actions will result in an AJAX enhancement.
|
||||
*
|
||||
* @protected
|
||||
* @method handle_data_action
|
||||
* @param {EventFacade} ev The event that was triggered.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
setup_for_resource : function(baseselector) {
|
||||
if (!baseselector) {
|
||||
var baseselector = CSS.PAGECONTENT + ' ' + CSS.ACTIVITYLI;
|
||||
handle_data_action : function(ev) {
|
||||
// We need to get the anchor element that triggered this event.
|
||||
var node = ev.target;
|
||||
if (!node.test('a')) {
|
||||
node = node.ancestor(SELECTOR.ACTIVITYACTION);
|
||||
}
|
||||
|
||||
Y.all(baseselector).each(this._setup_for_resource, this);
|
||||
},
|
||||
_setup_for_resource : function(toolboxtarget) {
|
||||
toolboxtarget = Y.one(toolboxtarget);
|
||||
// From the anchor we can get both the activity (added during initialisation) and the action being
|
||||
// performed (added by the UI as a data attribute)
|
||||
var action = node.getData('action'),
|
||||
activity = node.getData('activity');
|
||||
if (!node.test('a') || !action || !activity) {
|
||||
// It wasn't a valid action node.
|
||||
return;
|
||||
}
|
||||
|
||||
// Set groupmode attribute for use by this.toggle_groupmode()
|
||||
var groups;
|
||||
groups = toolboxtarget.all(CSS.COMMANDSPAN + ' ' + CSS.GROUPSNONE);
|
||||
groups.setAttribute('groupmode', this.GROUPS_NONE);
|
||||
// Switch based upon the action and do the desired thing.
|
||||
switch (action) {
|
||||
case 'edittitle' :
|
||||
// The user wishes to edit the title of the event.
|
||||
this.edit_title(ev, node, activity, action);
|
||||
break;
|
||||
case 'moveleft' :
|
||||
case 'moveright' :
|
||||
// The user changing the indent of the activity.
|
||||
this.change_indent(ev, node, activity, action);
|
||||
break;
|
||||
case 'delete' :
|
||||
// The user is deleting the activity.
|
||||
this.delete_with_confirmation(ev, node, activity, action);
|
||||
break;
|
||||
case 'hide' :
|
||||
case 'show' :
|
||||
// The user is changing the visibility of the activity.
|
||||
this.change_visibility(ev, node, activity, action);
|
||||
break;
|
||||
case 'groupsseparate' :
|
||||
case 'groupsvisible' :
|
||||
case 'groupsnone' :
|
||||
// The user is changing the group mode.
|
||||
callback = 'change_groupmode';
|
||||
this.change_groupmode(ev, node, activity, action);
|
||||
break;
|
||||
case 'move' :
|
||||
case 'update' :
|
||||
case 'duplicate' :
|
||||
case 'assignroles' :
|
||||
default:
|
||||
// Nothing to do here!
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
groups = toolboxtarget.all(CSS.COMMANDSPAN + ' ' + CSS.GROUPSSEPARATE);
|
||||
groups.setAttribute('groupmode', this.GROUPS_SEPARATE);
|
||||
|
||||
groups = toolboxtarget.all(CSS.COMMANDSPAN + ' ' + CSS.GROUPSVISIBLE);
|
||||
groups.setAttribute('groupmode', this.GROUPS_VISIBLE);
|
||||
},
|
||||
move_left : function(e) {
|
||||
this.move_leftright(e, -1);
|
||||
},
|
||||
move_right : function(e) {
|
||||
this.move_leftright(e, 1);
|
||||
},
|
||||
move_leftright : function(e, direction) {
|
||||
/**
|
||||
* Change the indent of the activity or resource.
|
||||
*
|
||||
* @protected
|
||||
* @method change_indent
|
||||
* @param {EventFacade} ev The event that was fired.
|
||||
* @param {Node} button The button that triggered this action.
|
||||
* @param {Node} activity The activity node that this action will be performed on.
|
||||
* @param {String} action The action that has been requested. Will be 'moveleft' or 'moveright'.
|
||||
*/
|
||||
change_indent : function(ev, button, activity, action) {
|
||||
// Prevent the default button action
|
||||
e.preventDefault();
|
||||
ev.preventDefault();
|
||||
|
||||
// Get the element we're working on
|
||||
var element = this.get_activity_container(e.target);
|
||||
var direction = (action === 'moveleft') ? -1 : 1;
|
||||
|
||||
// And we need to determine the current and new indent level
|
||||
var indentdiv = element.one(CSS.MODINDENTDIV);
|
||||
var indentdiv = activity.one(SELECTOR.MODINDENTDIV);
|
||||
var indent = indentdiv.getAttribute('class').match(/mod-indent-(\d{1,})/);
|
||||
|
||||
if (indent) {
|
||||
@@ -355,17 +342,16 @@ YUI.add('moodle-course-toolboxes', function(Y) {
|
||||
'class' : 'resource',
|
||||
'field' : 'indent',
|
||||
'value' : newindent,
|
||||
'id' : this.get_element_id(element)
|
||||
'id' : this.get_element_id(activity)
|
||||
};
|
||||
var spinner = M.util.add_spinner(Y, element.one(CSS.SPINNERCOMMANDSPAN));
|
||||
var spinner = M.util.add_spinner(Y, activity.one(SELECTOR.COMMANDSPAN));
|
||||
this.send_request(data, spinner);
|
||||
|
||||
// Handle removal/addition of the moveleft button
|
||||
Y.log(element);
|
||||
if (newindent == 0) {
|
||||
this.get_activity_action_link(element, CSS.MOVELEFT).addClass('hidden');
|
||||
button.remove();
|
||||
} else if (newindent == 1 && oldindent == 0) {
|
||||
this.get_activity_action_link(element, CSS.MOVELEFT).removeClass('hidden');
|
||||
this.change_indent_add_left_button(button);
|
||||
}
|
||||
|
||||
// Handle massive indentation to match non-ajax display
|
||||
@@ -376,13 +362,23 @@ YUI.add('moodle-course-toolboxes', function(Y) {
|
||||
indentdiv.removeClass(CSS.MODINDENTHUGE);
|
||||
}
|
||||
},
|
||||
delete_resource : function(e) {
|
||||
|
||||
/**
|
||||
* Deletes the given activity or resource after confirmation.
|
||||
*
|
||||
* @protected
|
||||
* @method delete_with_confirmation
|
||||
* @param {EventFacade} ev The event that was fired.
|
||||
* @param {Node} button The button that triggered this action.
|
||||
* @param {Node} activity The activity node that this action will be performed on.
|
||||
* @return Boolean
|
||||
*/
|
||||
delete_with_confirmation : function(ev, button, activity) {
|
||||
// Prevent the default button action
|
||||
e.preventDefault();
|
||||
ev.preventDefault();
|
||||
|
||||
// Get the element we're working on
|
||||
var element = this.get_activity_container(e.target);
|
||||
|
||||
var element = activity
|
||||
|
||||
// Create confirm string (different if element has or does not have name)
|
||||
var confirmstring = '';
|
||||
@@ -409,23 +405,35 @@ YUI.add('moodle-course-toolboxes', function(Y) {
|
||||
'id' : this.get_element_id(element)
|
||||
};
|
||||
this.send_request(data);
|
||||
if (M.core.actionmenu && M.core.actionmenu.instance) {
|
||||
M.core.actionmenu.instance.hideMenu();
|
||||
}
|
||||
},
|
||||
toggle_hide_resource : function(e) {
|
||||
|
||||
/**
|
||||
* Changes the visibility of this activity or resource.
|
||||
*
|
||||
* @protected
|
||||
* @method change_visibility
|
||||
* @param {EventFacade} ev The event that was fired.
|
||||
* @param {Node} button The button that triggered this action.
|
||||
* @param {Node} activity The activity node that this action will be performed on.
|
||||
* @param {String} action The action that has been requested.
|
||||
* @return Boolean
|
||||
*/
|
||||
change_visibility : function(ev, button, activity, action) {
|
||||
// Prevent the default button action
|
||||
e.preventDefault();
|
||||
ev.preventDefault();
|
||||
|
||||
// Return early if the current section is hidden
|
||||
var section = e.target.ancestor(M.course.format.get_section_selector(Y));
|
||||
var section = activity.ancestor(M.course.format.get_section_selector(Y));
|
||||
if (section && section.hasClass(CSS.SECTIONHIDDENCLASS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the element we're working on
|
||||
var element = this.get_activity_container(e.target);
|
||||
|
||||
var button = e.target.ancestor('a', true);
|
||||
|
||||
var value = this.toggle_hide_resource_ui(button);
|
||||
var element = activity;
|
||||
var value = this.handle_resource_dim(button, activity, action);
|
||||
|
||||
// Send the request
|
||||
var data = {
|
||||
@@ -434,62 +442,107 @@ YUI.add('moodle-course-toolboxes', function(Y) {
|
||||
'value' : value,
|
||||
'id' : this.get_element_id(element)
|
||||
};
|
||||
var spinner = M.util.add_spinner(Y, element.one(CSS.SPINNERCOMMANDSPAN));
|
||||
var spinner = M.util.add_spinner(Y, element.one(SELECTOR.COMMANDSPAN));
|
||||
this.send_request(data, spinner);
|
||||
return false; // Need to return false to stop the delegate for the new state firing
|
||||
},
|
||||
toggle_groupmode : function(e) {
|
||||
// Prevent the default button action
|
||||
e.preventDefault();
|
||||
|
||||
// Get the element we're working on
|
||||
var element = this.get_activity_container(e.target);
|
||||
/**
|
||||
* Handles the UI aspect of dimming the activity or resource
|
||||
*
|
||||
* @protected
|
||||
* @method handle_resource_dim
|
||||
* @param {Node} button The button that triggered the action.
|
||||
* @param {Node} activity The activity node that this action will be performed on.
|
||||
* @param {String} status Whether the activity was shown or hidden.
|
||||
* @returns {number} 1 if we were changing to visible, 0 if we were hiding.
|
||||
*/
|
||||
handle_resource_dim : function(button, activity, status) {
|
||||
var toggleclass = CSS.DIMCLASS,
|
||||
dimarea = activity.one('a'),
|
||||
availabilityinfo = activity.one(CSS.AVAILABILITYINFODIV),
|
||||
newstatus = (status === 'hide') ? 'show' : 'hide',
|
||||
newstring = M.util.get_string(newstatus, 'moodle');
|
||||
|
||||
var button = e.target.ancestor('a', true);
|
||||
var icon = button.one('img');
|
||||
// Update button info.
|
||||
button.one('img').setAttrs({
|
||||
'alt' : newstring,
|
||||
'src' : M.util.image_url('t/' + newstatus)
|
||||
});
|
||||
button.set('title', newstring);
|
||||
button.replaceClass('editing_'+status, 'editing_'+newstatus)
|
||||
button.setData('action', newstatus);
|
||||
|
||||
// If activity is conditionally hidden, then don't toggle.
|
||||
if (this.get_instance_name(activity) == null) {
|
||||
toggleclass = CSS.DIMMEDTEXT;
|
||||
dimarea = activity.all(SELECTOR.MODINDENTDIV + ' > div').item(1);
|
||||
}
|
||||
if (!dimarea.hasClass(CSS.CONDITIONALHIDDEN)) {
|
||||
// Change the UI.
|
||||
dimarea.toggleClass(toggleclass);
|
||||
// We need to toggle dimming on the description too.
|
||||
activity.all(SELECTOR.CONTENTAFTERLINK).toggleClass(CSS.DIMMEDTEXT);
|
||||
}
|
||||
// Toggle availablity info for conditional activities.
|
||||
if (availabilityinfo) {
|
||||
availabilityinfo.toggleClass(CSS.HIDE);
|
||||
}
|
||||
return (status === 'hide') ? 0 : 1;
|
||||
},
|
||||
|
||||
/**
|
||||
* Changes the groupmode of the activity to the next groupmode in the sequence.
|
||||
*
|
||||
* @protected
|
||||
* @method change_groupmode
|
||||
* @param {EventFacade} ev The event that was fired.
|
||||
* @param {Node} button The button that triggered this action.
|
||||
* @param {Node} activity The activity node that this action will be performed on.
|
||||
* @param {String} action The action that has been requested.
|
||||
* @return Boolean
|
||||
*/
|
||||
change_groupmode : function(ev, button, activity, action) {
|
||||
// Prevent the default button action.
|
||||
ev.preventDefault();
|
||||
|
||||
// Current Mode
|
||||
var groupmode = button.getAttribute('groupmode');
|
||||
groupmode++;
|
||||
var oldgroupmode = button.getData('groupmode');
|
||||
var groupmode = parseInt(oldgroupmode, 10) + 1;
|
||||
if (groupmode > 2) {
|
||||
groupmode = 0;
|
||||
}
|
||||
button.setAttribute('groupmode', groupmode);
|
||||
|
||||
var newtitle = '';
|
||||
var iconsrc = '';
|
||||
switch (groupmode) {
|
||||
case this.GROUPS_NONE:
|
||||
newtitle = 'groupsnone';
|
||||
iconsrc = M.util.image_url('t/groupn');
|
||||
break;
|
||||
case this.GROUPS_SEPARATE:
|
||||
newtitle = 'groupsseparate';
|
||||
iconsrc = M.util.image_url('t/groups');
|
||||
break;
|
||||
case this.GROUPS_VISIBLE:
|
||||
newtitle = 'groupsvisible';
|
||||
iconsrc = M.util.image_url('t/groupv');
|
||||
break;
|
||||
if (groupmode === this.GROUPS_NONE) {
|
||||
newtitle = 'groupsnone';
|
||||
iconsrc = M.util.image_url('t/groupn', 'moodle');
|
||||
} else if (groupmode === this.GROUPS_SEPARATE) {
|
||||
newtitle = 'groupsseparate';
|
||||
iconsrc = M.util.image_url('t/groups', 'moodle');
|
||||
} else if (groupmode === this.GROUPS_VISIBLE) {
|
||||
newtitle = 'groupsvisible';
|
||||
iconsrc = M.util.image_url('t/groupv', 'moodle');
|
||||
}
|
||||
newtitle = M.util.get_string('clicktochangeinbrackets', 'moodle',
|
||||
M.util.get_string(newtitle, 'moodle'));
|
||||
var newtitlestr = M.util.get_string(newtitle, 'moodle'),
|
||||
newtitlestr = M.util.get_string('clicktochangeinbrackets', 'moodle', newtitlestr);
|
||||
|
||||
// Change the UI
|
||||
icon.setAttrs({
|
||||
'alt' : newtitle,
|
||||
button.one('img').setAttrs({
|
||||
'alt' : newtitlestr,
|
||||
'src' : iconsrc
|
||||
});
|
||||
button.setAttribute('title', newtitle);
|
||||
button.setAttribute('title', newtitlestr).setData('action', newtitle).setData('groupmode', groupmode);
|
||||
|
||||
// And send the request
|
||||
var data = {
|
||||
'class' : 'resource',
|
||||
'field' : 'groupmode',
|
||||
'value' : groupmode,
|
||||
'id' : this.get_element_id(element)
|
||||
'id' : this.get_element_id(activity)
|
||||
};
|
||||
var spinner = M.util.add_spinner(Y, element.one(CSS.SPINNERCOMMANDSPAN));
|
||||
var 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
|
||||
},
|
||||
@@ -497,176 +550,188 @@ YUI.add('moodle-course-toolboxes', function(Y) {
|
||||
* Add the moveleft button
|
||||
* This is required after moving left from an initial position of 0
|
||||
*
|
||||
* @param target The encapsulating <li> element
|
||||
* @protected
|
||||
* @method change_indent_add_left_button
|
||||
* @param {Node} moveright. The move right icon which should always be there.
|
||||
*/
|
||||
add_moveleft : function(target) {
|
||||
Y.log(target);
|
||||
var left_string = M.util.get_string('moveleft', 'moodle');
|
||||
var moveimage = 't/left'; // ltr mode
|
||||
if ( Y.one(document.body).hasClass('dir-rtl') ) {
|
||||
moveimage = 't/right';
|
||||
} else {
|
||||
moveimage = 't/left';
|
||||
change_indent_add_left_button : function(moveright) {
|
||||
var moveleft = moveright.cloneNode(true);
|
||||
var icon = (BODY.hasClass('dir-rtl')) ? 't/right' : 't/left';
|
||||
var str = M.util.get_string('moveleft', 'moodle');
|
||||
moveleft.setAttrs({
|
||||
'title' : str,
|
||||
'href' : moveright.getAttribute('href').replace('indent=1', 'indent=-1')
|
||||
});
|
||||
moveleft.setData('activity', moveright.getData('activity'));
|
||||
moveleft.setData('action', 'moveleft');
|
||||
moveleft.one('img').setAttrs({
|
||||
'alt' : str,
|
||||
'src' : M.util.image_url(icon, 'moodle')
|
||||
});
|
||||
if (moveleft.one(SELECTOR.ACTIONLINKTEXT)) {
|
||||
moveleft.one(SELECTOR.ACTIONLINKTEXT).setContent(str);
|
||||
}
|
||||
var newicon = Y.Node.create('<img />')
|
||||
.addClass(CSS.GENERICICONCLASS)
|
||||
.setAttrs({
|
||||
'src' : M.util.image_url(moveimage, 'moodle'),
|
||||
'alt' : left_string
|
||||
});
|
||||
var moveright = target.one(CSS.MOVERIGHT);
|
||||
var newlink = moveright.getAttribute('href').replace('indent=1', 'indent=-1');
|
||||
var anchor = new Y.Node.create('<a />')
|
||||
.setStyle('cursor', 'pointer')
|
||||
.addClass(CSS.MOVELEFTCLASS)
|
||||
.setAttribute('href', newlink)
|
||||
.setAttribute('title', left_string);
|
||||
anchor.appendChild(newicon);
|
||||
moveright.insert(anchor, 'before');
|
||||
moveright.insert(moveleft, 'before');
|
||||
},
|
||||
|
||||
/**
|
||||
* Edit the title for the resource
|
||||
*
|
||||
* @protected
|
||||
* @method edit_title
|
||||
* @param {EventFacade} ev The event that was fired.
|
||||
* @param {Node} button The button that triggered this action.
|
||||
* @param {Node} activity The activity node that this action will be performed on.
|
||||
* @param {String} action The action that has been requested.
|
||||
* @return Boolean
|
||||
*/
|
||||
edit_resource_title : function(e) {
|
||||
edit_title : function(ev, button, activity) {
|
||||
// Get the element we're working on
|
||||
var element = this.get_activity_container(e.target);
|
||||
var elementdiv = element.one('div');
|
||||
var instancename = element.one(CSS.INSTANCENAME);
|
||||
var currenttitle = instancename.get('firstChild');
|
||||
var oldtitle = currenttitle.get('data');
|
||||
var titletext = oldtitle;
|
||||
var editbutton = element.one('a.' + CSS.EDITTITLECLASS + ' img');
|
||||
var activityid = this.get_element_id(activity),
|
||||
instancename = activity.one(SELECTOR.INSTANCENAME),
|
||||
currenttitle = instancename.get('firstChild'),
|
||||
oldtitle = currenttitle.get('data'),
|
||||
titletext = oldtitle,
|
||||
thisevent,
|
||||
anchor = instancename.ancestor('a'), // Grab the anchor so that we can swap it with the edit form
|
||||
data = {
|
||||
'class' : 'resource',
|
||||
'field' : 'gettitle',
|
||||
'id' : activityid
|
||||
},
|
||||
response = this.send_request(data);
|
||||
|
||||
// Handle events for edit_resource_title
|
||||
var listenevents = [];
|
||||
var thisevent;
|
||||
|
||||
// Grab the anchor so that we can swap it with the edit form
|
||||
var anchor = instancename.ancestor('a');
|
||||
|
||||
var data = {
|
||||
'class' : 'resource',
|
||||
'field' : 'gettitle',
|
||||
'id' : this.get_element_id(element)
|
||||
};
|
||||
if (M.core.actionmenu && M.core.actionmenu.instance) {
|
||||
M.core.actionmenu.instance.hideMenu();
|
||||
}
|
||||
|
||||
// Try to retrieve the existing string from the server
|
||||
var response = this.send_request(data, editbutton);
|
||||
if (response.instancename) {
|
||||
titletext = response.instancename;
|
||||
}
|
||||
|
||||
// Create the editor and submit button
|
||||
var editor = Y.Node.create('<input />')
|
||||
.setAttrs({
|
||||
'name' : 'title',
|
||||
'value' : titletext,
|
||||
'autocomplete' : 'off',
|
||||
'aria-describedby' : 'id_editinstructions',
|
||||
'maxLength' : '255'
|
||||
})
|
||||
.addClass('titleeditor');
|
||||
var editform = Y.Node.create('<form />')
|
||||
.addClass('activityinstance')
|
||||
.setAttribute('action', '#');
|
||||
var editinstructions = Y.Node.create('<span />')
|
||||
.addClass('editinstructions')
|
||||
.setAttrs({'id' : 'id_editinstructions'})
|
||||
var editform = Y.Node.create('<form class="'+CSS.ACTIVITYINSTANCE+'" action="#" />');
|
||||
var editinstructions = Y.Node.create('<span class="'+CSS.EDITINSTRUCTIONS+'" id="id_editinstructions" />')
|
||||
.set('innerHTML', M.util.get_string('edittitleinstructions', 'moodle'));
|
||||
var activityicon = element.one('img.activityicon').cloneNode();
|
||||
var editor = Y.Node.create('<input name="title" type="text" class="'+CSS.TITLEEDITOR+'" />').setAttrs({
|
||||
'value' : titletext,
|
||||
'autocomplete' : 'off',
|
||||
'aria-describedby' : 'id_editinstructions',
|
||||
'maxLength' : '255'
|
||||
})
|
||||
|
||||
// Clear the existing content and put the editor in
|
||||
currenttitle.set('data', '');
|
||||
editform.appendChild(activityicon);
|
||||
editform.appendChild(activity.one(SELECTOR.ACTIVITYICON).cloneNode());
|
||||
editform.appendChild(editor);
|
||||
editform.setData('anchor', anchor);
|
||||
anchor.replace(editform);
|
||||
elementdiv.appendChild(editinstructions);
|
||||
e.preventDefault();
|
||||
activity.one('div').appendChild(editinstructions);
|
||||
ev.preventDefault();
|
||||
|
||||
// Focus and select the editor text
|
||||
editor.focus().select();
|
||||
|
||||
// Handle removal of the editor
|
||||
var clear_edittitle = function() {
|
||||
// Detach all listen events to prevent duplicate triggers
|
||||
var thisevent;
|
||||
while (thisevent = listenevents.shift()) {
|
||||
thisevent.detach();
|
||||
}
|
||||
|
||||
if (editinstructions) {
|
||||
// Convert back to anchor and remove instructions
|
||||
editform.replace(anchor);
|
||||
editinstructions.remove();
|
||||
editinstructions = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle cancellation of the editor
|
||||
var cancel_edittitle = function(e) {
|
||||
clear_edittitle();
|
||||
|
||||
// Set the title and anchor back to their previous settings
|
||||
currenttitle.set('data', oldtitle);
|
||||
};
|
||||
|
||||
// Cancel the edit if we lose focus or the escape key is pressed
|
||||
thisevent = editor.on('blur', cancel_edittitle);
|
||||
listenevents.push(thisevent);
|
||||
thisevent = Y.one('document').on('keydown', function(e) {
|
||||
if (e.keyCode === 27) {
|
||||
e.preventDefault();
|
||||
cancel_edittitle(e);
|
||||
}
|
||||
});
|
||||
listenevents.push(thisevent);
|
||||
thisevent = editor.on('blur', this.edit_title_cancel, this, activity, false);
|
||||
this.edittitleevents.push(thisevent);
|
||||
thisevent = editor.on('key', this.edit_title_cancel, 'esc', this, activity, true);
|
||||
this.edittitleevents.push(thisevent);
|
||||
|
||||
// Handle form submission
|
||||
thisevent = editform.on('submit', function(e) {
|
||||
// We don't actually want to submit anything
|
||||
e.preventDefault();
|
||||
|
||||
// Clear the edit title boxes
|
||||
clear_edittitle();
|
||||
|
||||
// We only accept strings which have valid content
|
||||
var newtitle = Y.Lang.trim(editor.get('value'));
|
||||
if (newtitle != null && newtitle != "" && newtitle != titletext) {
|
||||
var data = {
|
||||
'class' : 'resource',
|
||||
'field' : 'updatetitle',
|
||||
'title' : newtitle,
|
||||
'id' : this.get_element_id(element)
|
||||
};
|
||||
var response = this.send_request(data, editbutton);
|
||||
if (response.instancename) {
|
||||
currenttitle.set('data', response.instancename);
|
||||
}
|
||||
} else {
|
||||
// Invalid content. Set the title back to it's original contents
|
||||
currenttitle.set('data', oldtitle);
|
||||
}
|
||||
}, this);
|
||||
listenevents.push(thisevent);
|
||||
thisevent = editform.on('submit', this.edit_title_submit, this, activity, oldtitle);
|
||||
this.edittitleevents.push(thisevent);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the submit event when editing the activity or resources title.
|
||||
*
|
||||
* @protected
|
||||
* @method edit_title_submit
|
||||
* @param {EventFacade} ev The event that triggered this.
|
||||
* @param {Node} activity The activity whose title we are altering.
|
||||
* @param {String} originaltitle The original title the activity or resource had.
|
||||
*/
|
||||
edit_title_submit : function(ev, activity, originaltitle) {
|
||||
// We don't actually want to submit anything
|
||||
ev.preventDefault();
|
||||
|
||||
var newtitle = Y.Lang.trim(activity.one(SELECTOR.ACTIVITYFORM + ' ' + SELECTOR.ACTIVITYTITLE).get('value'));
|
||||
this.edit_title_clear(activity);
|
||||
var spinner = M.util.add_spinner(Y, activity.one(SELECTOR.INSTANCENAME));
|
||||
if (newtitle != null && newtitle != "" && newtitle != originaltitle) {
|
||||
var data = {
|
||||
'class' : 'resource',
|
||||
'field' : 'updatetitle',
|
||||
'title' : newtitle,
|
||||
'id' : this.get_element_id(activity)
|
||||
};
|
||||
var response = this.send_request(data, spinner);
|
||||
if (response.instancename) {
|
||||
activity.one(SELECTOR.INSTANCENAME).setContent(response.instancename);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the cancel event when editing the activity or resources title.
|
||||
*
|
||||
* @protected
|
||||
* @method edit_title_cancel
|
||||
* @param {EventFacade} ev The event that triggered this.
|
||||
* @param {Node} activity The activity whose title we are altering.
|
||||
* @param {Boolean} preventdefault If true we should prevent the default action from occuring.
|
||||
*/
|
||||
edit_title_cancel : function(ev, activity, preventdefault) {
|
||||
if (preventdefault) {
|
||||
ev.preventDefault();
|
||||
}
|
||||
this.edit_title_clear(activity);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles clearing the editing UI and returning things to the original state they were in.
|
||||
*
|
||||
* @protected
|
||||
* @method edit_title_clear
|
||||
* @param {Node} activity The activity whose title we were altering.
|
||||
*/
|
||||
edit_title_clear : function(activity) {
|
||||
// Detach all listen events to prevent duplicate triggers
|
||||
var thisevent;
|
||||
while (thisevent = this.edittitleevents.shift()) {
|
||||
thisevent.detach();
|
||||
}
|
||||
var editform = activity.one(SELECTOR.ACTIVITYFORM),
|
||||
instructions = activity.one('#id_editinstructions');
|
||||
if (editform) {
|
||||
editform.replace(editform.getData('anchor'));
|
||||
}
|
||||
if (instructions) {
|
||||
instructions.remove();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the visibility of the current resource (identified by the element)
|
||||
* to match the hidden parameter (this is not a toggle).
|
||||
* Only changes the visibility in the browser (no ajax update).
|
||||
*
|
||||
* @public This method is used by other modules.
|
||||
* @method set_visibility_resource_ui
|
||||
* @param args An object with 'element' being the A node containing the resource
|
||||
* and 'visible' being the state that the visiblity should be set to.
|
||||
* @return void
|
||||
* 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(CSS.SHOW);
|
||||
var buttonnode = element.one(SELECTOR.SHOW);
|
||||
var visible = (buttonnode === null);
|
||||
if (visible) {
|
||||
buttonnode = element.one(CSS.HIDE);
|
||||
buttonnode = element.one(SELECTOR.HIDE);
|
||||
}
|
||||
if (visible != shouldbevisible) {
|
||||
this.toggle_hide_resource_ui(buttonnode);
|
||||
this.change_visibility_ui(buttonnode);
|
||||
}
|
||||
}
|
||||
}, {
|
||||
@@ -696,9 +761,9 @@ YUI.add('moodle-course-toolboxes', function(Y) {
|
||||
M.course.coursebase.register_module(this);
|
||||
|
||||
// Section Highlighting
|
||||
Y.delegate('click', this.toggle_highlight, CSS.PAGECONTENT, CSS.SECTIONLI + ' ' + CSS.HIGHLIGHT, this);
|
||||
Y.delegate('click', this.toggle_highlight, SELECTOR.PAGECONTENT, SELECTOR.SECTIONLI + ' ' + SELECTOR.HIGHLIGHT, this);
|
||||
// Section Visibility
|
||||
Y.delegate('click', this.toggle_hide_section, CSS.PAGECONTENT, CSS.SECTIONLI + ' ' + CSS.SHOWHIDE, this);
|
||||
Y.delegate('click', this.toggle_hide_section, SELECTOR.PAGECONTENT, SELECTOR.SECTIONLI + ' ' + SELECTOR.SHOWHIDE, this);
|
||||
},
|
||||
/**
|
||||
* Update any section areas within the scope of the specified
|
||||
@@ -710,7 +775,7 @@ YUI.add('moodle-course-toolboxes', function(Y) {
|
||||
setup_for_section : function(baseselector) {
|
||||
// Left here for potential future use - not currently needed due to YUI delegation in initializer()
|
||||
/*if (!baseselector) {
|
||||
var baseselector = CSS.PAGECONTENT;
|
||||
var baseselector = SELECTOR.PAGECONTENT;
|
||||
}
|
||||
|
||||
Y.all(baseselector).each(this._setup_for_section, this);*/
|
||||
@@ -763,17 +828,17 @@ YUI.add('moodle-course-toolboxes', function(Y) {
|
||||
|
||||
var response = this.send_request(data, lightbox);
|
||||
|
||||
var activities = section.all(CSS.ACTIVITYLI);
|
||||
var activities = section.all(SELECTOR.ACTIVITYLI);
|
||||
activities.each(function(node) {
|
||||
if (node.one(CSS.SHOW)) {
|
||||
var button = node.one(CSS.SHOW);
|
||||
if (node.one(SELECTOR.SHOW)) {
|
||||
var button = node.one(SELECTOR.SHOW);
|
||||
} else {
|
||||
var button = node.one(CSS.HIDE);
|
||||
var button = node.one(SELECTOR.HIDE);
|
||||
}
|
||||
var activityid = this.get_element_id(node);
|
||||
|
||||
if (Y.Array.indexOf(response.resourcestotoggle, activityid) != -1) {
|
||||
this.toggle_hide_resource_ui(button);
|
||||
this.change_visibility_ui(button);
|
||||
}
|
||||
}, this);
|
||||
},
|
||||
@@ -792,16 +857,16 @@ YUI.add('moodle-course-toolboxes', function(Y) {
|
||||
|
||||
// Set the current highlighted item text
|
||||
var old_string = M.util.get_string('markthistopic', 'moodle');
|
||||
Y.one(CSS.PAGECONTENT)
|
||||
.all(M.course.format.get_section_selector(Y) + '.current ' + CSS.HIGHLIGHT)
|
||||
Y.one(SELECTOR.PAGECONTENT)
|
||||
.all(M.course.format.get_section_selector(Y) + '.current ' + SELECTOR.HIGHLIGHT)
|
||||
.set('title', old_string);
|
||||
Y.one(CSS.PAGECONTENT)
|
||||
.all(M.course.format.get_section_selector(Y) + '.current ' + CSS.HIGHLIGHT + ' img')
|
||||
Y.one(SELECTOR.PAGECONTENT)
|
||||
.all(M.course.format.get_section_selector(Y) + '.current ' + SELECTOR.HIGHLIGHT + ' img')
|
||||
.set('alt', old_string)
|
||||
.set('src', M.util.image_url('i/marker'));
|
||||
|
||||
// Remove the highlighting from all sections
|
||||
var allsections = Y.one(CSS.PAGECONTENT).all(M.course.format.get_section_selector(Y))
|
||||
var allsections = Y.one(SELECTOR.PAGECONTENT).all(M.course.format.get_section_selector(Y))
|
||||
.removeClass('current');
|
||||
|
||||
// Then add it if required to the selected section
|
||||
|
||||
+3
-22
@@ -1037,9 +1037,6 @@ class block_manager {
|
||||
|
||||
if ($this->page->user_can_edit_blocks()) {
|
||||
// Move icon.
|
||||
//$controls[] = array('url' => $actionurl . '&bui_moveid=' . $block->instance->id,
|
||||
// 'icon' => 't/move', 'caption' => get_string('moveblock', 'block', $blocktitle),
|
||||
// 'class' => 'editing_move status');
|
||||
$controls[] = new action_link(
|
||||
new moodle_url($actionurl, array('bui_moveid' => $block->instance->id)),
|
||||
get_string('moveblock', 'block', $blocktitle),
|
||||
@@ -1052,14 +1049,11 @@ class block_manager {
|
||||
|
||||
if ($this->page->user_can_edit_blocks() || $block->user_can_edit()) {
|
||||
// Edit config icon - always show - needed for positioning UI.
|
||||
//$controls[] = array('url' => $actionurl . '&bui_editid=' . $block->instance->id,
|
||||
// 'icon' => 't/edit', 'caption' => get_string('configureblock', 'block', $blocktitle),
|
||||
// 'class' => 'editing_edit');
|
||||
$controls[] = new action_link(
|
||||
new moodle_url($actionurl, array('bui_editid' => $block->instance->id)),
|
||||
get_string('configureblock', 'block', $blocktitle),
|
||||
null,
|
||||
array('class' => 'editing_edit', 'title' => get_string('configureblock', 'block', $blocktitle)),
|
||||
array('class' => 'editing_edit status', 'title' => get_string('configureblock', 'block', $blocktitle)),
|
||||
new pix_icon('t/edit', get_string('configureblock', 'block', $blocktitle), 'moodle', array('class' => 'iconsmall', 'title' => ''))
|
||||
);
|
||||
|
||||
@@ -1067,9 +1061,6 @@ class block_manager {
|
||||
|
||||
if ($this->user_can_delete_block($block)) {
|
||||
// Delete icon.
|
||||
//$controls[] = array('url' => $actionurl . '&bui_deleteid=' . $block->instance->id,
|
||||
//// 'icon' => 't/delete', 'caption' => get_string('deleteblock', 'block', $blocktitle),
|
||||
// 'class' => 'editing_delete');
|
||||
$controls[] = new action_link(
|
||||
new moodle_url($actionurl, array('bui_deleteid' => $block->instance->id)),
|
||||
get_string('deleteblock', 'block', $blocktitle),
|
||||
@@ -1084,25 +1075,19 @@ class block_manager {
|
||||
if ($block->instance->visible) {
|
||||
$controls[] = new action_link(
|
||||
new moodle_url($actionurl, array('bui_hideid' => $block->instance->id)),
|
||||
get_string('deleteblock', 'block', $blocktitle),
|
||||
get_string('hideblock', 'block', $blocktitle),
|
||||
null,
|
||||
array('class' => 'editing_hide status', 'title' => get_string('hideblock', 'block', $blocktitle)),
|
||||
new pix_icon('t/hide', get_string('hideblock', 'block', $blocktitle), 'moodle', array('class' => 'iconsmall', 'title' => ''))
|
||||
);
|
||||
//$controls[] = array('url' => $actionurl . '&bui_hideid=' . $block->instance->id,
|
||||
// 'icon' => 't/hide', 'caption' => get_string('hideblock', 'block', $blocktitle),
|
||||
// 'class' => 'editing_hide status');
|
||||
} else {
|
||||
$controls[] = new action_link(
|
||||
new moodle_url($actionurl, array('bui_showid' => $block->instance->id)),
|
||||
get_string('deleteblock', 'block', $blocktitle),
|
||||
get_string('showblock', 'block', $blocktitle),
|
||||
null,
|
||||
array('class' => 'editing_show status', 'title' => get_string('showblock', 'block', $blocktitle)),
|
||||
new pix_icon('t/show', get_string('showblock', 'block', $blocktitle), 'moodle', array('class' => 'iconsmall', 'title' => ''))
|
||||
);
|
||||
//$controls[] = array('url' => $actionurl . '&bui_showid=' . $block->instance->id,
|
||||
// 'icon' => 't/show', 'caption' => get_string('showblock', 'block', $blocktitle),
|
||||
// 'class' => 'editing_show status');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1123,10 +1108,6 @@ class block_manager {
|
||||
array('class' => 'editing_roles', 'title' => get_string('assignrolesinblock', 'block', $blocktitle)),
|
||||
new pix_icon('t/assignroles', get_string('assignrolesinblock', 'block', $blocktitle), 'moodle', array('class' => 'iconsmall', 'title' => ''))
|
||||
);
|
||||
//$controls[] = array('url' => $CFG->wwwroot . '/' . $CFG->admin .
|
||||
// '/roles/assign.php?contextid=' . $block->context->id . '&returnurl=' . urlencode($return),
|
||||
// 'icon' => 't/assignroles', 'caption' => get_string('assignrolesinblock', 'block', $blocktitle),
|
||||
// 'class' => 'editing_roles');
|
||||
}
|
||||
return $controls;
|
||||
}
|
||||
|
||||
+160
-35
@@ -2878,41 +2878,6 @@ class custom_menu extends custom_menu_item {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of action links/icons relating to a specific element in the page.
|
||||
*
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @package core
|
||||
*/
|
||||
class action_menu implements renderable {
|
||||
/** @var string unique id of the tab in this tree, it is used to find selected and/or inactive tabs */
|
||||
var $id;
|
||||
/** @var string title under the link, by default equals to text */
|
||||
var $title;
|
||||
/** @var pix_icon representing the icon to open the menu */
|
||||
var $icon;
|
||||
/** @var array of action_link objects representing a list of menu items */
|
||||
var $items;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $title title for the menu. Should include the name of the item this menu relates to.
|
||||
* @param string $icon pix_icon for the menu. Defaults to a menu icon.
|
||||
* @param array $items a list of items to put in the menu.
|
||||
*/
|
||||
public function __construct($title, $icon = '', $items = array()) {
|
||||
$this->id = html_writer::random_id('actionmenu');
|
||||
$this->icon = $icon;
|
||||
$this->title = $title;
|
||||
$this->items = $items;
|
||||
}
|
||||
|
||||
public function add(action_link $link) {
|
||||
array_push($this->items, $link);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores one tab
|
||||
*
|
||||
@@ -3064,3 +3029,163 @@ class tabtree extends tabobject {
|
||||
$this->set_level(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An action menu.
|
||||
*
|
||||
* This action menu component takes a series of primary and secondary actions.
|
||||
* The primary actions are displayed permanently and the secondary attributes are displayed within a drop
|
||||
* down menu.
|
||||
*
|
||||
* @package core
|
||||
* @category output
|
||||
* @copyright 2013 Sam Hemelryk
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class action_menu implements renderable {
|
||||
|
||||
/**
|
||||
* An array of primary actions. Please use {@see action_menu::add_primary_action()} to add actions.
|
||||
* @var array
|
||||
*/
|
||||
protected $primaryactions = array();
|
||||
|
||||
/**
|
||||
* An array of secondary actions. Please use {@see action_menu::add_secondary_action()} to add actions.
|
||||
* @var array
|
||||
*/
|
||||
protected $secondaryactions = array();
|
||||
|
||||
/**
|
||||
* An array of attributes added to the container of the action menu.
|
||||
* Initialised with defaults during construction.
|
||||
* @var array
|
||||
*/
|
||||
public $attributes = array();
|
||||
/**
|
||||
* An array of attributes added to the container of the primary actions.
|
||||
* Initialised with defaults during construction.
|
||||
* @var array
|
||||
*/
|
||||
public $attributesprimary = array();
|
||||
/**
|
||||
* An array of attributes added to the container of the secondary actions.
|
||||
* Initialised with defaults during construction.
|
||||
* @var array
|
||||
*/
|
||||
public $attributessecondary = array();
|
||||
|
||||
/**
|
||||
* If set to true only the icons for primary action_link objects will be displayed.
|
||||
* @var bool
|
||||
*/
|
||||
public $displayprimaryiconsonly = true;
|
||||
|
||||
/**
|
||||
* Constructs the action menu with the given items.
|
||||
*
|
||||
* @param array $primaryactions An array of primary actions.
|
||||
* @param array $secondaryactions An array of secondary actions.
|
||||
*/
|
||||
public function __construct(array $primaryactions = array(), array $secondaryactions = array()) {
|
||||
static $initialised = 0;
|
||||
$this->attributes = array(
|
||||
'id' => 'action-menu-'.$initialised,
|
||||
'class' => 'moodle-actionmenu',
|
||||
'data-enhance' => 'moodle-core-actionmenu'
|
||||
);
|
||||
$this->attributesprimary = array(
|
||||
'id' => 'action-menu-'.$initialised.'-primary',
|
||||
'class' => 'primary'
|
||||
);
|
||||
$this->attributessecondary = array(
|
||||
'id' => 'action-menu-'.$initialised.'-secondary',
|
||||
'class' => 'secondary',
|
||||
'data-rel' => 'menu-content',
|
||||
);
|
||||
foreach ($primaryactions as $action) {
|
||||
$this->add_primary_action($action);
|
||||
}
|
||||
foreach ($secondaryactions as $action) {
|
||||
$this->add_secondary_action($action);
|
||||
}
|
||||
// We've initialised!
|
||||
$initialised++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises JS required fore the action menu.
|
||||
* The JS is only required once as it manages all action menu's on the page.
|
||||
*
|
||||
* @param moodle_page $page
|
||||
*/
|
||||
public function initialise_js(moodle_page $page) {
|
||||
static $initialised = false;
|
||||
if (!$initialised) {
|
||||
$page->requires->yui_module('moodle-core-actionmenu', 'M.core.actionmenu.init');
|
||||
$initialised = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a primary action to the action menu.
|
||||
*
|
||||
* @param action_link|string $action
|
||||
*/
|
||||
public function add_primary_action($action) {
|
||||
$this->primaryactions[] = $action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a secondary action to the action menu.
|
||||
*
|
||||
* @param action_link|string $action
|
||||
*/
|
||||
public function add_secondary_action($action) {
|
||||
$this->secondaryactions[] = $action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the primary actions ready to be rendered.
|
||||
*
|
||||
* @param core_renderer $output The renderer to use for getting icons.
|
||||
* @return array
|
||||
*/
|
||||
public function get_primary_actions(core_renderer $output = null) {
|
||||
global $OUTPUT;
|
||||
if ($output === null) {
|
||||
$output = $OUTPUT;
|
||||
}
|
||||
$actions = array();
|
||||
foreach ($this->primaryactions as $action) {
|
||||
if ($this->displayprimaryiconsonly && $action instanceof action_link && $action->icon) {
|
||||
$action->text = null;
|
||||
}
|
||||
$actions[] = $action;
|
||||
}
|
||||
$attributes = array(
|
||||
'type' => 'image',
|
||||
'src' => $output->pix_url('t/contextmenu', 'moodle'),
|
||||
'alt' => get_string('actions', 'moodle'),
|
||||
'class' => 'toggle-display'
|
||||
);
|
||||
$actions[] = html_writer::empty_tag('input', $attributes);
|
||||
return $actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the secondary actions ready to be rendered.
|
||||
* @return array
|
||||
*/
|
||||
public function get_secondary_actions() {
|
||||
return $this->secondaryactions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the selector that should be used to find the owning node of this menu.
|
||||
* @param string $selector A CSS/YUI selector to identify the owner of the menu.
|
||||
*/
|
||||
public function set_owner_selector($selector) {
|
||||
$this->attributes['data-owner'] = $selector;
|
||||
}
|
||||
}
|
||||
|
||||
+43
-12
@@ -1029,26 +1029,53 @@ class core_renderer extends renderer_base {
|
||||
* Output the row of editing icons for a block, as defined by the controls array.
|
||||
*
|
||||
* @param array $controls an array like {@link block_contents::$controls}.
|
||||
* @param string $blockid The ID given to the block.
|
||||
* @return string HTML fragment.
|
||||
*/
|
||||
public function block_controls($actions) {
|
||||
$this->page->requires->yui_module('moodle-core-actionmenu', 'M.core.actionmenu.init');
|
||||
$output = html_writer::start_tag('span', array('class' => 'actionmenu'));
|
||||
$output .= html_writer::start_tag('span', array('class' => 'statuses'));
|
||||
public function block_controls($actions, $blockid = null) {
|
||||
if (empty($actions)) {
|
||||
return '';
|
||||
}
|
||||
$menu = new action_menu();
|
||||
if ($blockid !== null) {
|
||||
$menu->set_owner_selector('#'.$blockid);
|
||||
}
|
||||
foreach ($actions as $action) {
|
||||
if ($action->has_class('status')) {
|
||||
$menu->add_primary_action($action);
|
||||
} else {
|
||||
$menu->add_secondary_action($action);
|
||||
}
|
||||
}
|
||||
$menu->attributes['class'] .= ' block-control-actions commands';
|
||||
return $this->render($menu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders an action menu component.
|
||||
*
|
||||
* @param action_menu $menu
|
||||
* @return string HTML
|
||||
*/
|
||||
public function render_action_menu(action_menu $menu) {
|
||||
$menu->initialise_js($this->page);
|
||||
|
||||
$output = html_writer::start_tag('div', $menu->attributes);
|
||||
$output .= html_writer::start_tag('span', $menu->attributesprimary);
|
||||
foreach ($menu->get_primary_actions($this) as $action) {
|
||||
if ($action instanceof renderable) {
|
||||
$output .= $this->render($action);
|
||||
} else {
|
||||
$output .= $action;
|
||||
}
|
||||
}
|
||||
$output .= html_writer::end_tag('span');
|
||||
$output .= html_writer::start_tag('span', array('class' => 'actions'));
|
||||
foreach ($actions as $action) {
|
||||
if (!$action->has_class('status')) {
|
||||
$output .= $this->render($action);
|
||||
}
|
||||
$output .= html_writer::start_tag('div', $menu->attributessecondary);
|
||||
foreach ($menu->get_secondary_actions() as $action) {
|
||||
$output .= $this->render($action);
|
||||
}
|
||||
$output .= html_writer::end_tag('span');
|
||||
$output .= html_writer::end_tag('span');
|
||||
$output .= html_writer::end_tag('div');
|
||||
$output .= html_writer::end_tag('div');
|
||||
return $output;
|
||||
}
|
||||
|
||||
@@ -1138,7 +1165,11 @@ class core_renderer extends renderer_base {
|
||||
$title = html_writer::tag('h2', $bc->title, $attributes);
|
||||
}
|
||||
|
||||
$controlshtml = $this->block_controls($bc->controls);
|
||||
$blockid = null;
|
||||
if (isset($bc->attributes['id'])) {
|
||||
$blockid = $bc->attributes['id'];
|
||||
}
|
||||
$controlshtml = $this->block_controls($bc->controls, $blockid);
|
||||
|
||||
$output = '';
|
||||
if ($title || $controlshtml) {
|
||||
|
||||
@@ -6,16 +6,16 @@ YUI.add('moodle-core-actionmenu', function (Y, NAME) {
|
||||
* @module moodle-core-actionmenu
|
||||
*/
|
||||
|
||||
CSS = {
|
||||
ACTIONS : '.actions'
|
||||
};
|
||||
|
||||
RESOURCES = {
|
||||
MENUICON : {
|
||||
pix : 't/contextmenu',
|
||||
component : 'moodle'
|
||||
}
|
||||
};
|
||||
var BODY = Y.one(Y.config.doc.body),
|
||||
CSS = {
|
||||
MENUSHOWN : 'action-menu-shown'
|
||||
},
|
||||
SELECTOR = {
|
||||
MENU : '[data-enhance=moodle-core-actionmenu]',
|
||||
MENUCONTENT : '[data-rel=menu-content]',
|
||||
TOGGLE : '.toggle-display'
|
||||
},
|
||||
ACTIONMENU;
|
||||
|
||||
/**
|
||||
* Action menu support.
|
||||
@@ -27,109 +27,185 @@ RESOURCES = {
|
||||
* @constructor
|
||||
* @extends Y.Base
|
||||
*/
|
||||
var ACTIONMENU = function() {
|
||||
ACTIONMENU = function() {
|
||||
ACTIONMENU.superclass.constructor.apply(this, arguments);
|
||||
};
|
||||
ACTIONMENU.prototype = {
|
||||
|
||||
Y.extend(ACTIONMENU, Y.Base, {
|
||||
/**
|
||||
* The dialogue used for all action menu displays.
|
||||
* @property type
|
||||
* @type M.core.dialogue
|
||||
* @protected
|
||||
*/
|
||||
dialogue : null,
|
||||
|
||||
/**
|
||||
* An array of events attached during the display of the dialogue.
|
||||
* @property events
|
||||
* @type Object
|
||||
* @protected
|
||||
*/
|
||||
events : [],
|
||||
|
||||
/**
|
||||
* The node that owns the currently displayed menu.
|
||||
*/
|
||||
owner : null,
|
||||
|
||||
/**
|
||||
* Called during the initialisation process of the object.
|
||||
* @method initializer
|
||||
*/
|
||||
initializer : function() {
|
||||
var rightalignpoints = [Y.WidgetPositionAlign.TR, Y.WidgetPositionAlign.BR];
|
||||
var leftalignpoints = [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL];
|
||||
|
||||
Y.all(CSS.ACTIONS).each(function() {
|
||||
|
||||
// Prepend menu icon before the list.
|
||||
var imgnode = Y.Node.create('<img/>');
|
||||
var imgsrc = M.util.image_url(RESOURCES.MENUICON.pix, RESOURCES.MENUICON.component);
|
||||
var linknode = Y.Node.create('<a/>');
|
||||
var parentnode = this.get('parentNode');
|
||||
var alignpoints = rightalignpoints;
|
||||
var menux = 0;
|
||||
|
||||
if (!this.hasChildNodes()) {
|
||||
return this;
|
||||
}
|
||||
|
||||
linknode.setAttribute('href', '#');
|
||||
linknode.addClass('actionmenu');
|
||||
|
||||
imgnode.setAttribute('src', imgsrc);
|
||||
|
||||
linknode.appendChild(imgnode);
|
||||
parentnode.insertBefore(linknode, this);
|
||||
|
||||
menux = (parentnode.getX() + parseInt(parentnode.getComputedStyle('width'), 10));
|
||||
|
||||
if (menux < (this.get('winWidth') / 2)) {
|
||||
alignpoints = leftalignpoints;
|
||||
}
|
||||
|
||||
var overlay = new Y.Overlay({
|
||||
bodyContent : this,
|
||||
visible: false,
|
||||
align: {node: imgnode, points: alignpoints},
|
||||
zIndex: 10
|
||||
});
|
||||
|
||||
overlay.render();
|
||||
overlay.get('boundingBox').on('focusoutside', overlay.hide, overlay);
|
||||
|
||||
// Create bi-directional links between the menu and the open button.
|
||||
linknode.setData('actionmenu-menu', overlay);
|
||||
this.all('a').each(function () {
|
||||
this.setData('actionmenu-link', linknode);
|
||||
});
|
||||
return this;
|
||||
});
|
||||
|
||||
Y.one('body').delegate('click', this.toggleMenu, '.actionmenu');
|
||||
Y.one('body').on('key', this.hideAllMenus, 'esc', this);
|
||||
},
|
||||
|
||||
hideAllMenus : function() {
|
||||
// Hide all actionmenus.
|
||||
Y.all('.actionmenu').each(function() {
|
||||
var overlay = this.getData('actionmenu-menu');
|
||||
if (overlay) {
|
||||
overlay.hide();
|
||||
Y.log('Initialising action menu manager', 'note', ACTIONMENU.NAME);
|
||||
Y.all(SELECTOR.MENU).each(function() {
|
||||
var menucontent = this.one(SELECTOR.MENUCONTENT);
|
||||
if (menucontent.hasChildNodes()) {
|
||||
this.setAttribute('data-enhanced', '1');
|
||||
this.setData('menucontent', menucontent);
|
||||
}
|
||||
});
|
||||
BODY.delegate('click', this.toggleMenu, SELECTOR.MENU + ' ' + SELECTOR.TOGGLE, this);
|
||||
BODY.delegate('key', this.toggleMenu, 'enter,space', SELECTOR.MENU + ' ' + SELECTOR.TOGGLE, this);
|
||||
},
|
||||
|
||||
toggleMenu : function(e) {
|
||||
var overlay = this.getData('actionmenu-menu');
|
||||
if (typeof overlay !== "undefined") {
|
||||
if (overlay.get('visible')) {
|
||||
overlay.hide();
|
||||
} else {
|
||||
M.core.actionmenu.instance.hideAllMenus();
|
||||
overlay.show();
|
||||
}
|
||||
/**
|
||||
* Hides the menu if it is visible.
|
||||
* @method hideMenu
|
||||
*/
|
||||
hideMenu : function() {
|
||||
if (this.dialogue) {
|
||||
this.dialogue.hide();
|
||||
}
|
||||
e.preventDefault();
|
||||
}
|
||||
for (var i in this.events) {
|
||||
if (this.events[i].detach) {
|
||||
this.events[i].detach();
|
||||
}
|
||||
}
|
||||
this.events = [];
|
||||
},
|
||||
|
||||
}, {
|
||||
/**
|
||||
* Toggles the display of the menu.
|
||||
* @method toggleMenu
|
||||
* @param {EventFacade} e
|
||||
*/
|
||||
toggleMenu : function(e) {
|
||||
// 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.events.push(BODY.on('key', this.hideMenu, 'esc', this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Calculates the alignment point for the menu.
|
||||
* @param {Node} node
|
||||
* @returns {{node: *, points: Array}}
|
||||
*/
|
||||
calculateAlign : function(node) {
|
||||
var points = [Y.WidgetPositionAlign.TR, Y.WidgetPositionAlign.BR];
|
||||
if (BODY.hasClass('dir-rtl')) {
|
||||
points = [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL];
|
||||
}
|
||||
return {node: node, points : points};
|
||||
},
|
||||
|
||||
/**
|
||||
* Displays the menu with the given content and alignment.
|
||||
* @param {Node} bodyContent
|
||||
* @param Array align
|
||||
* @returns {M.core.dialogue|dialogue}
|
||||
*/
|
||||
showMenu : function(menu, align) {
|
||||
Y.log('Displaying action menu', 'note', ACTIONMENU.NAME);
|
||||
var bodyContent = menu.getData('menucontent'),
|
||||
ownerSelector = menu.getData('owner');
|
||||
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;
|
||||
},
|
||||
|
||||
/**
|
||||
* Flags the owner appropriately when the visibility of the dialogue changes.
|
||||
* @param {EventFacade} e
|
||||
*/
|
||||
flagOwner : function(e) {
|
||||
if (this.owner && e.attrName === 'visible') {
|
||||
if (e.newVal === true) {
|
||||
this.owner.addClass(CSS.MENUSHOWN);
|
||||
} else {
|
||||
this.owner.removeClass(CSS.MENUSHOWN);
|
||||
this.owner = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Y.extend(ACTIONMENU, Y.Base, ACTIONMENU.prototype, {
|
||||
NAME : 'moodle-core-actionmenu',
|
||||
ATTRS : { }
|
||||
ATTRS : {
|
||||
/**
|
||||
* A selector to use to get the owner of the menu if there is one.
|
||||
* @attribute owner
|
||||
* @type String
|
||||
*/
|
||||
owner : {
|
||||
value : null
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Core namespace.
|
||||
* @static
|
||||
* @class core
|
||||
*/
|
||||
M.core = M.core || {};
|
||||
|
||||
/**
|
||||
* Actionmenu namespace.
|
||||
* @namespace M.core
|
||||
* @class actionmenu
|
||||
* @static
|
||||
*/
|
||||
M.core.actionmenu = M.core.actionmenu || {};
|
||||
|
||||
/**
|
||||
* Init function - will only ever create one instance of the actionmenu class.
|
||||
* @method init
|
||||
* @static
|
||||
* @param {Object} params
|
||||
*/
|
||||
M.core.actionmenu.init = M.core.actionmenu.init || function(params) {
|
||||
M.core.actionmenu.instance = M.core.actionmenu.instance || new ACTIONMENU(params);
|
||||
};
|
||||
|
||||
|
||||
}, '@VERSION@', {"requires": ["base", "node", "overlay", "event"]});
|
||||
}, '@VERSION@', {"requires": ["base", "event", "moodle-core-notification"]});
|
||||
|
||||
@@ -1 +1 @@
|
||||
YUI.add("moodle-core-actionmenu",function(e,t){CSS={ACTIONS:".actions"},RESOURCES={MENUICON:{pix:"t/contextmenu",component:"moodle"}};var n=function(){n.superclass.constructor.apply(this,arguments)};e.extend(n,e.Base,{initializer:function(){var t=[e.WidgetPositionAlign.TR,e.WidgetPositionAlign.BR],n=[e.WidgetPositionAlign.TL,e.WidgetPositionAlign.BL];e.all(CSS.ACTIONS).each(function(){var r=e.Node.create("<img/>"),i=M.util.image_url(RESOURCES.MENUICON.pix,RESOURCES.MENUICON.component),s=e.Node.create("<a/>"),o=this.get("parentNode"),u=t,a=0;if(!this.hasChildNodes())return this;s.setAttribute("href","#"),s.addClass("actionmenu"),r.setAttribute("src",i),s.appendChild(r),o.insertBefore(s,this),a=o.getX()+parseInt(o.getComputedStyle("width"),10),a<this.get("winWidth")/2&&(u=n);var f=new e.Overlay({bodyContent:this,visible:!1,align:{node:r,points:u},zIndex:10});return f.render(),f.get("boundingBox").on("focusoutside",f.hide,f),s.setData("actionmenu-menu",f),this.all("a").each(function(){this.setData("actionmenu-link",s)}),this}),e.one("body").delegate("click",this.toggleMenu,".actionmenu"),e.one("body").on("key",this.hideAllMenus,"esc",this)},hideAllMenus:function(){e.all(".actionmenu").each(function(){var e=this.getData("actionmenu-menu");e&&e.hide()})},toggleMenu:function(e){var t=this.getData("actionmenu-menu");typeof t!="undefined"&&(t.get("visible")?t.hide():(M.core.actionmenu.instance.hideAllMenus(),t.show())),e.preventDefault()}},{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 n(e)}},"@VERSION@",{requires:["base","node","overlay","event"]});
|
||||
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"]});
|
||||
|
||||
+159
-85
@@ -6,16 +6,16 @@ YUI.add('moodle-core-actionmenu', function (Y, NAME) {
|
||||
* @module moodle-core-actionmenu
|
||||
*/
|
||||
|
||||
CSS = {
|
||||
ACTIONS : '.actions'
|
||||
};
|
||||
|
||||
RESOURCES = {
|
||||
MENUICON : {
|
||||
pix : 't/contextmenu',
|
||||
component : 'moodle'
|
||||
}
|
||||
};
|
||||
var BODY = Y.one(Y.config.doc.body),
|
||||
CSS = {
|
||||
MENUSHOWN : 'action-menu-shown'
|
||||
},
|
||||
SELECTOR = {
|
||||
MENU : '[data-enhance=moodle-core-actionmenu]',
|
||||
MENUCONTENT : '[data-rel=menu-content]',
|
||||
TOGGLE : '.toggle-display'
|
||||
},
|
||||
ACTIONMENU;
|
||||
|
||||
/**
|
||||
* Action menu support.
|
||||
@@ -27,109 +27,183 @@ RESOURCES = {
|
||||
* @constructor
|
||||
* @extends Y.Base
|
||||
*/
|
||||
var ACTIONMENU = function() {
|
||||
ACTIONMENU = function() {
|
||||
ACTIONMENU.superclass.constructor.apply(this, arguments);
|
||||
};
|
||||
ACTIONMENU.prototype = {
|
||||
|
||||
Y.extend(ACTIONMENU, Y.Base, {
|
||||
/**
|
||||
* The dialogue used for all action menu displays.
|
||||
* @property type
|
||||
* @type M.core.dialogue
|
||||
* @protected
|
||||
*/
|
||||
dialogue : null,
|
||||
|
||||
/**
|
||||
* An array of events attached during the display of the dialogue.
|
||||
* @property events
|
||||
* @type Object
|
||||
* @protected
|
||||
*/
|
||||
events : [],
|
||||
|
||||
/**
|
||||
* The node that owns the currently displayed menu.
|
||||
*/
|
||||
owner : null,
|
||||
|
||||
/**
|
||||
* Called during the initialisation process of the object.
|
||||
* @method initializer
|
||||
*/
|
||||
initializer : function() {
|
||||
var rightalignpoints = [Y.WidgetPositionAlign.TR, Y.WidgetPositionAlign.BR];
|
||||
var leftalignpoints = [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL];
|
||||
|
||||
Y.all(CSS.ACTIONS).each(function() {
|
||||
|
||||
// Prepend menu icon before the list.
|
||||
var imgnode = Y.Node.create('<img/>');
|
||||
var imgsrc = M.util.image_url(RESOURCES.MENUICON.pix, RESOURCES.MENUICON.component);
|
||||
var linknode = Y.Node.create('<a/>');
|
||||
var parentnode = this.get('parentNode');
|
||||
var alignpoints = rightalignpoints;
|
||||
var menux = 0;
|
||||
|
||||
if (!this.hasChildNodes()) {
|
||||
return this;
|
||||
}
|
||||
|
||||
linknode.setAttribute('href', '#');
|
||||
linknode.addClass('actionmenu');
|
||||
|
||||
imgnode.setAttribute('src', imgsrc);
|
||||
|
||||
linknode.appendChild(imgnode);
|
||||
parentnode.insertBefore(linknode, this);
|
||||
|
||||
menux = (parentnode.getX() + parseInt(parentnode.getComputedStyle('width'), 10));
|
||||
|
||||
if (menux < (this.get('winWidth') / 2)) {
|
||||
alignpoints = leftalignpoints;
|
||||
}
|
||||
|
||||
var overlay = new Y.Overlay({
|
||||
bodyContent : this,
|
||||
visible: false,
|
||||
align: {node: imgnode, points: alignpoints},
|
||||
zIndex: 10
|
||||
});
|
||||
|
||||
overlay.render();
|
||||
overlay.get('boundingBox').on('focusoutside', overlay.hide, overlay);
|
||||
|
||||
// Create bi-directional links between the menu and the open button.
|
||||
linknode.setData('actionmenu-menu', overlay);
|
||||
this.all('a').each(function () {
|
||||
this.setData('actionmenu-link', linknode);
|
||||
});
|
||||
return this;
|
||||
});
|
||||
|
||||
Y.one('body').delegate('click', this.toggleMenu, '.actionmenu');
|
||||
Y.one('body').on('key', this.hideAllMenus, 'esc', this);
|
||||
},
|
||||
|
||||
hideAllMenus : function() {
|
||||
// Hide all actionmenus.
|
||||
Y.all('.actionmenu').each(function() {
|
||||
var overlay = this.getData('actionmenu-menu');
|
||||
if (overlay) {
|
||||
overlay.hide();
|
||||
Y.all(SELECTOR.MENU).each(function() {
|
||||
var menucontent = this.one(SELECTOR.MENUCONTENT);
|
||||
if (menucontent.hasChildNodes()) {
|
||||
this.setAttribute('data-enhanced', '1');
|
||||
this.setData('menucontent', menucontent);
|
||||
}
|
||||
});
|
||||
BODY.delegate('click', this.toggleMenu, SELECTOR.MENU + ' ' + SELECTOR.TOGGLE, this);
|
||||
BODY.delegate('key', this.toggleMenu, 'enter,space', SELECTOR.MENU + ' ' + SELECTOR.TOGGLE, this);
|
||||
},
|
||||
|
||||
toggleMenu : function(e) {
|
||||
var overlay = this.getData('actionmenu-menu');
|
||||
if (typeof overlay !== "undefined") {
|
||||
if (overlay.get('visible')) {
|
||||
overlay.hide();
|
||||
} else {
|
||||
M.core.actionmenu.instance.hideAllMenus();
|
||||
overlay.show();
|
||||
}
|
||||
/**
|
||||
* Hides the menu if it is visible.
|
||||
* @method hideMenu
|
||||
*/
|
||||
hideMenu : function() {
|
||||
if (this.dialogue) {
|
||||
this.dialogue.hide();
|
||||
}
|
||||
e.preventDefault();
|
||||
}
|
||||
for (var i in this.events) {
|
||||
if (this.events[i].detach) {
|
||||
this.events[i].detach();
|
||||
}
|
||||
}
|
||||
this.events = [];
|
||||
},
|
||||
|
||||
}, {
|
||||
/**
|
||||
* Toggles the display of the menu.
|
||||
* @method toggleMenu
|
||||
* @param {EventFacade} e
|
||||
*/
|
||||
toggleMenu : function(e) {
|
||||
// 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.events.push(BODY.on('key', this.hideMenu, 'esc', this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Calculates the alignment point for the menu.
|
||||
* @param {Node} node
|
||||
* @returns {{node: *, points: Array}}
|
||||
*/
|
||||
calculateAlign : function(node) {
|
||||
var points = [Y.WidgetPositionAlign.TR, Y.WidgetPositionAlign.BR];
|
||||
if (BODY.hasClass('dir-rtl')) {
|
||||
points = [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL];
|
||||
}
|
||||
return {node: node, points : points};
|
||||
},
|
||||
|
||||
/**
|
||||
* Displays the menu with the given content and alignment.
|
||||
* @param {Node} bodyContent
|
||||
* @param Array align
|
||||
* @returns {M.core.dialogue|dialogue}
|
||||
*/
|
||||
showMenu : function(menu, align) {
|
||||
var bodyContent = menu.getData('menucontent'),
|
||||
ownerSelector = menu.getData('owner');
|
||||
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;
|
||||
},
|
||||
|
||||
/**
|
||||
* Flags the owner appropriately when the visibility of the dialogue changes.
|
||||
* @param {EventFacade} e
|
||||
*/
|
||||
flagOwner : function(e) {
|
||||
if (this.owner && e.attrName === 'visible') {
|
||||
if (e.newVal === true) {
|
||||
this.owner.addClass(CSS.MENUSHOWN);
|
||||
} else {
|
||||
this.owner.removeClass(CSS.MENUSHOWN);
|
||||
this.owner = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Y.extend(ACTIONMENU, Y.Base, ACTIONMENU.prototype, {
|
||||
NAME : 'moodle-core-actionmenu',
|
||||
ATTRS : { }
|
||||
ATTRS : {
|
||||
/**
|
||||
* A selector to use to get the owner of the menu if there is one.
|
||||
* @attribute owner
|
||||
* @type String
|
||||
*/
|
||||
owner : {
|
||||
value : null
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Core namespace.
|
||||
* @static
|
||||
* @class core
|
||||
*/
|
||||
M.core = M.core || {};
|
||||
|
||||
/**
|
||||
* Actionmenu namespace.
|
||||
* @namespace M.core
|
||||
* @class actionmenu
|
||||
* @static
|
||||
*/
|
||||
M.core.actionmenu = M.core.actionmenu || {};
|
||||
|
||||
/**
|
||||
* Init function - will only ever create one instance of the actionmenu class.
|
||||
* @method init
|
||||
* @static
|
||||
* @param {Object} params
|
||||
*/
|
||||
M.core.actionmenu.init = M.core.actionmenu.init || function(params) {
|
||||
M.core.actionmenu.instance = M.core.actionmenu.instance || new ACTIONMENU(params);
|
||||
};
|
||||
|
||||
|
||||
}, '@VERSION@', {"requires": ["base", "node", "overlay", "event"]});
|
||||
}, '@VERSION@', {"requires": ["base", "event", "moodle-core-notification"]});
|
||||
|
||||
+9
@@ -57,6 +57,11 @@ DIALOGUE = function(config) {
|
||||
.append(Y.Node.create('<div class="'+CSS.BODY+' yui3-widget-bd"></div>'))
|
||||
.append(Y.Node.create('<div class="'+CSS.FOOTER+' yui3-widget-ft"></div>')));
|
||||
Y.one(document.body).append(config.notificationBase);
|
||||
|
||||
if (config.additionalBaseClass) {
|
||||
config.notificationBase.addClass(config.additionalBaseClass);
|
||||
}
|
||||
|
||||
config.srcNode = '#'+id;
|
||||
config.width = config.width || '400px';
|
||||
config.visible = config.visible || false;
|
||||
@@ -64,6 +69,10 @@ DIALOGUE = function(config) {
|
||||
config.centered = false;
|
||||
config.COUNT = COUNT;
|
||||
|
||||
if (config.width === 'auto') {
|
||||
delete config.width;
|
||||
}
|
||||
|
||||
// lightbox param to keep the stable versions API.
|
||||
if (config.lightbox !== false) {
|
||||
config.modal = true;
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
YUI.add("moodle-core-notification-dialogue",function(e,t){var n,r,i,s,o,u,a,f;n="moodle-dialogue",r="notificationBase",i=0,s="yesLabel",o="noLabel",u="title",a="question",f={BASE:"moodle-dialogue-base",WRAP:"moodle-dialogue-wrap",HEADER:"moodle-dialogue-hd",BODY:"moodle-dialogue-bd",CONTENT:"moodle-dialogue-content",FOOTER:"moodle-dialogue-ft",HIDDEN:"hidden",LIGHTBOX:"moodle-dialogue-lightbox"},M.core=M.core||{};var l="Moodle dialogue",c;c=function(t){i++;var n="moodle-dialogue-"+i;t.notificationBase=e.Node.create('<div class="'+f.BASE+'">').append(e.Node.create('<div id="'+n+'" role="dialog" aria-labelledby="'+n+'-header-text" class="'+f.WRAP+'"></div>').append(e.Node.create('<div class="'+f.HEADER+' yui3-widget-hd"></div>')).append(e.Node.create('<div class="'+f.BODY+' yui3-widget-bd"></div>')).append(e.Node.create('<div class="'+f.FOOTER+' yui3-widget-ft"></div>'))),e.one(document.body).append(t.notificationBase),t.srcNode="#"+n,t.width=t.width||"400px",t.visible=t.visible||!1,t.center=t.centered||!0,t.centered=!1,t.COUNT=i,t.lightbox!==!1&&(t.modal=!0),delete t.lightbox,t.closeButton===!1?t.buttons=null:t.buttons=[{section:e.WidgetStdMod.HEADER,classNames:"closebutton",action:function(){this.hide()}}],c.superclass.constructor.apply(this,[t]),t.closeButton!==!1&&this.get("buttons").header[0].setAttribute("title",this.get("closeButtonTitle"))},e.extend(c,e.Panel,{initializer:function(){this.after("visibleChange",this.visibilityChanged,this),this.render(),this.show(),this.set("COUNT",i),this.get("boundingBox").setStyle("zIndex",null)},visibilityChanged:function(t){var n;t.attrName==="visible"&&(this.get("maskNode").addClass(f.LIGHTBOX),this.get("center")&&!t.prevVal&&t.newVal&&this.centerDialogue(),this.get("draggable")&&(n="#"+this.get("id")+" ."+f.HEADER,this.plug(e.Plugin.Drag,{handles:[n]}),e.one(n).setStyle("cursor","move")))},centerDialogue:function(){var t=this.get("boundingBox"),r=t.hasClass(n+"-hidden"),i,s;r&&t.setStyle("top","-1000px").removeClass(n+"-hidden"),i=Math.max(Math.round((t.get("winWidth")-t.get("offsetWidth"))/2),15),s=Math.max(Math.round((t.get("winHeight")-t.get("offsetHeight"))/2),15)+e.one(window).get("scrollTop"),r&&t.addClass(n+"-hidden"),t.setStyle("left",i).setStyle("top",s)}},{NAME:l,CSS_PREFIX:n,ATTRS:{notificationBase:{},lightbox:{validator:e.Lang.isBoolean,value:!0},closeButton:{validator:e.Lang.isBoolean,value:!0},closeButtonTitle:{validator:e.Lang.isString,value:"Close"},center:{validator:e.Lang.isBoolean,value:!0},draggable:{validator:e.Lang.isBoolean,value:!1},COUNT:{value:0}}}),M.core.dialogue=c},"@VERSION@",{requires:["base","node","panel","event-key","dd-plugin"]});
|
||||
YUI.add("moodle-core-notification-dialogue",function(e,t){var n,r,i,s,o,u,a,f;n="moodle-dialogue",r="notificationBase",i=0,s="yesLabel",o="noLabel",u="title",a="question",f={BASE:"moodle-dialogue-base",WRAP:"moodle-dialogue-wrap",HEADER:"moodle-dialogue-hd",BODY:"moodle-dialogue-bd",CONTENT:"moodle-dialogue-content",FOOTER:"moodle-dialogue-ft",HIDDEN:"hidden",LIGHTBOX:"moodle-dialogue-lightbox"},M.core=M.core||{};var l="Moodle dialogue",c;c=function(t){i++;var n="moodle-dialogue-"+i;t.notificationBase=e.Node.create('<div class="'+f.BASE+'">').append(e.Node.create('<div id="'+n+'" role="dialog" aria-labelledby="'+n+'-header-text" class="'+f.WRAP+'"></div>').append(e.Node.create('<div class="'+f.HEADER+' yui3-widget-hd"></div>')).append(e.Node.create('<div class="'+f.BODY+' yui3-widget-bd"></div>')).append(e.Node.create('<div class="'+f.FOOTER+' yui3-widget-ft"></div>'))),e.one(document.body).append(t.notificationBase),t.additionalBaseClass&&t.notificationBase.addClass(t.additionalBaseClass),t.srcNode="#"+n,t.width=t.width||"400px",t.visible=t.visible||!1,t.center=t.centered||!0,t.centered=!1,t.COUNT=i,t.width==="auto"&&delete t.width,t.lightbox!==!1&&(t.modal=!0),delete t.lightbox,t.closeButton===!1?t.buttons=null:t.buttons=[{section:e.WidgetStdMod.HEADER,classNames:"closebutton",action:function(){this.hide()}}],c.superclass.constructor.apply(this,[t]),t.closeButton!==!1&&this.get("buttons").header[0].setAttribute("title",this.get("closeButtonTitle"))},e.extend(c,e.Panel,{initializer:function(){this.after("visibleChange",this.visibilityChanged,this),this.render(),this.show(),this.set("COUNT",i),this.get("boundingBox").setStyle("zIndex",null)},visibilityChanged:function(t){var n;t.attrName==="visible"&&(this.get("maskNode").addClass(f.LIGHTBOX),this.get("center")&&!t.prevVal&&t.newVal&&this.centerDialogue(),this.get("draggable")&&(n="#"+this.get("id")+" ."+f.HEADER,this.plug(e.Plugin.Drag,{handles:[n]}),e.one(n).setStyle("cursor","move")))},centerDialogue:function(){var t=this.get("boundingBox"),r=t.hasClass(n+"-hidden"),i,s;r&&t.setStyle("top","-1000px").removeClass(n+"-hidden"),i=Math.max(Math.round((t.get("winWidth")-t.get("offsetWidth"))/2),15),s=Math.max(Math.round((t.get("winHeight")-t.get("offsetHeight"))/2),15)+e.one(window).get("scrollTop"),r&&t.addClass(n+"-hidden"),t.setStyle("left",i).setStyle("top",s)}},{NAME:l,CSS_PREFIX:n,ATTRS:{notificationBase:{},lightbox:{validator:e.Lang.isBoolean,value:!0},closeButton:{validator:e.Lang.isBoolean,value:!0},closeButtonTitle:{validator:e.Lang.isString,value:"Close"},center:{validator:e.Lang.isBoolean,value:!0},draggable:{validator:e.Lang.isBoolean,value:!1},COUNT:{value:0}}}),M.core.dialogue=c},"@VERSION@",{requires:["base","node","panel","event-key","dd-plugin"]});
|
||||
|
||||
+9
@@ -57,6 +57,11 @@ DIALOGUE = function(config) {
|
||||
.append(Y.Node.create('<div class="'+CSS.BODY+' yui3-widget-bd"></div>'))
|
||||
.append(Y.Node.create('<div class="'+CSS.FOOTER+' yui3-widget-ft"></div>')));
|
||||
Y.one(document.body).append(config.notificationBase);
|
||||
|
||||
if (config.additionalBaseClass) {
|
||||
config.notificationBase.addClass(config.additionalBaseClass);
|
||||
}
|
||||
|
||||
config.srcNode = '#'+id;
|
||||
config.width = config.width || '400px';
|
||||
config.visible = config.visible || false;
|
||||
@@ -64,6 +69,10 @@ DIALOGUE = function(config) {
|
||||
config.centered = false;
|
||||
config.COUNT = COUNT;
|
||||
|
||||
if (config.width === 'auto') {
|
||||
delete config.width;
|
||||
}
|
||||
|
||||
// lightbox param to keep the stable versions API.
|
||||
if (config.lightbox !== false) {
|
||||
config.modal = true;
|
||||
|
||||
+160
-84
@@ -4,16 +4,16 @@
|
||||
* @module moodle-core-actionmenu
|
||||
*/
|
||||
|
||||
CSS = {
|
||||
ACTIONS : '.actions'
|
||||
};
|
||||
|
||||
RESOURCES = {
|
||||
MENUICON : {
|
||||
pix : 't/contextmenu',
|
||||
component : 'moodle'
|
||||
}
|
||||
};
|
||||
var BODY = Y.one(Y.config.doc.body),
|
||||
CSS = {
|
||||
MENUSHOWN : 'action-menu-shown'
|
||||
},
|
||||
SELECTOR = {
|
||||
MENU : '[data-enhance=moodle-core-actionmenu]',
|
||||
MENUCONTENT : '[data-rel=menu-content]',
|
||||
TOGGLE : '.toggle-display'
|
||||
},
|
||||
ACTIONMENU;
|
||||
|
||||
/**
|
||||
* Action menu support.
|
||||
@@ -25,105 +25,181 @@ RESOURCES = {
|
||||
* @constructor
|
||||
* @extends Y.Base
|
||||
*/
|
||||
var ACTIONMENU = function() {
|
||||
ACTIONMENU = function() {
|
||||
ACTIONMENU.superclass.constructor.apply(this, arguments);
|
||||
};
|
||||
ACTIONMENU.prototype = {
|
||||
|
||||
Y.extend(ACTIONMENU, Y.Base, {
|
||||
/**
|
||||
* The dialogue used for all action menu displays.
|
||||
* @property type
|
||||
* @type M.core.dialogue
|
||||
* @protected
|
||||
*/
|
||||
dialogue : null,
|
||||
|
||||
/**
|
||||
* An array of events attached during the display of the dialogue.
|
||||
* @property events
|
||||
* @type Object
|
||||
* @protected
|
||||
*/
|
||||
events : [],
|
||||
|
||||
/**
|
||||
* The node that owns the currently displayed menu.
|
||||
*/
|
||||
owner : null,
|
||||
|
||||
/**
|
||||
* Called during the initialisation process of the object.
|
||||
* @method initializer
|
||||
*/
|
||||
initializer : function() {
|
||||
var rightalignpoints = [Y.WidgetPositionAlign.TR, Y.WidgetPositionAlign.BR];
|
||||
var leftalignpoints = [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL];
|
||||
|
||||
Y.all(CSS.ACTIONS).each(function() {
|
||||
|
||||
// Prepend menu icon before the list.
|
||||
var imgnode = Y.Node.create('<img/>');
|
||||
var imgsrc = M.util.image_url(RESOURCES.MENUICON.pix, RESOURCES.MENUICON.component);
|
||||
var linknode = Y.Node.create('<a/>');
|
||||
var parentnode = this.get('parentNode');
|
||||
var alignpoints = rightalignpoints;
|
||||
var menux = 0;
|
||||
|
||||
if (!this.hasChildNodes()) {
|
||||
return this;
|
||||
}
|
||||
|
||||
linknode.setAttribute('href', '#');
|
||||
linknode.addClass('actionmenu');
|
||||
|
||||
imgnode.setAttribute('src', imgsrc);
|
||||
|
||||
linknode.appendChild(imgnode);
|
||||
parentnode.insertBefore(linknode, this);
|
||||
|
||||
menux = (parentnode.getX() + parseInt(parentnode.getComputedStyle('width'), 10));
|
||||
|
||||
if (menux < (this.get('winWidth') / 2)) {
|
||||
alignpoints = leftalignpoints;
|
||||
}
|
||||
|
||||
var overlay = new Y.Overlay({
|
||||
bodyContent : this,
|
||||
visible: false,
|
||||
align: {node: imgnode, points: alignpoints},
|
||||
zIndex: 10
|
||||
});
|
||||
|
||||
overlay.render();
|
||||
overlay.get('boundingBox').on('focusoutside', overlay.hide, overlay);
|
||||
|
||||
// Create bi-directional links between the menu and the open button.
|
||||
linknode.setData('actionmenu-menu', overlay);
|
||||
this.all('a').each(function () {
|
||||
this.setData('actionmenu-link', linknode);
|
||||
});
|
||||
return this;
|
||||
});
|
||||
|
||||
Y.one('body').delegate('click', this.toggleMenu, '.actionmenu');
|
||||
Y.one('body').on('key', this.hideAllMenus, 'esc', this);
|
||||
},
|
||||
|
||||
hideAllMenus : function() {
|
||||
// Hide all actionmenus.
|
||||
Y.all('.actionmenu').each(function() {
|
||||
var overlay = this.getData('actionmenu-menu');
|
||||
if (overlay) {
|
||||
overlay.hide();
|
||||
Y.log('Initialising action menu manager', 'note', ACTIONMENU.NAME);
|
||||
Y.all(SELECTOR.MENU).each(function() {
|
||||
var menucontent = this.one(SELECTOR.MENUCONTENT);
|
||||
if (menucontent.hasChildNodes()) {
|
||||
this.setAttribute('data-enhanced', '1');
|
||||
this.setData('menucontent', menucontent);
|
||||
}
|
||||
});
|
||||
BODY.delegate('click', this.toggleMenu, SELECTOR.MENU + ' ' + SELECTOR.TOGGLE, this);
|
||||
BODY.delegate('key', this.toggleMenu, 'enter,space', SELECTOR.MENU + ' ' + SELECTOR.TOGGLE, this);
|
||||
},
|
||||
|
||||
toggleMenu : function(e) {
|
||||
var overlay = this.getData('actionmenu-menu');
|
||||
if (typeof overlay !== "undefined") {
|
||||
if (overlay.get('visible')) {
|
||||
overlay.hide();
|
||||
} else {
|
||||
M.core.actionmenu.instance.hideAllMenus();
|
||||
overlay.show();
|
||||
}
|
||||
/**
|
||||
* Hides the menu if it is visible.
|
||||
* @method hideMenu
|
||||
*/
|
||||
hideMenu : function() {
|
||||
if (this.dialogue) {
|
||||
this.dialogue.hide();
|
||||
}
|
||||
e.preventDefault();
|
||||
}
|
||||
for (var i in this.events) {
|
||||
if (this.events[i].detach) {
|
||||
this.events[i].detach();
|
||||
}
|
||||
}
|
||||
this.events = [];
|
||||
},
|
||||
|
||||
}, {
|
||||
/**
|
||||
* Toggles the display of the menu.
|
||||
* @method toggleMenu
|
||||
* @param {EventFacade} e
|
||||
*/
|
||||
toggleMenu : function(e) {
|
||||
// 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.events.push(BODY.on('key', this.hideMenu, 'esc', this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Calculates the alignment point for the menu.
|
||||
* @param {Node} node
|
||||
* @returns {{node: *, points: Array}}
|
||||
*/
|
||||
calculateAlign : function(node) {
|
||||
var points = [Y.WidgetPositionAlign.TR, Y.WidgetPositionAlign.BR];
|
||||
if (BODY.hasClass('dir-rtl')) {
|
||||
points = [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL];
|
||||
}
|
||||
return {node: node, points : points};
|
||||
},
|
||||
|
||||
/**
|
||||
* Displays the menu with the given content and alignment.
|
||||
* @param {Node} menu
|
||||
* @param Array align
|
||||
* @returns {M.core.dialogue|dialogue}
|
||||
*/
|
||||
showMenu : function(menu, align) {
|
||||
Y.log('Displaying action menu', 'note', ACTIONMENU.NAME);
|
||||
var bodyContent = menu.getData('menucontent'),
|
||||
ownerSelector = menu.getData('owner');
|
||||
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;
|
||||
},
|
||||
|
||||
/**
|
||||
* Flags the owner appropriately when the visibility of the dialogue changes.
|
||||
* @param {EventFacade} e
|
||||
*/
|
||||
flagOwner : function(e) {
|
||||
if (this.owner && e.attrName === 'visible') {
|
||||
if (e.newVal === true) {
|
||||
this.owner.addClass(CSS.MENUSHOWN);
|
||||
} else {
|
||||
this.owner.removeClass(CSS.MENUSHOWN);
|
||||
this.owner = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Y.extend(ACTIONMENU, Y.Base, ACTIONMENU.prototype, {
|
||||
NAME : 'moodle-core-actionmenu',
|
||||
ATTRS : { }
|
||||
ATTRS : {
|
||||
/**
|
||||
* A selector to use to get the owner of the menu if there is one.
|
||||
* @attribute owner
|
||||
* @type String
|
||||
*/
|
||||
owner : {
|
||||
value : null
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Core namespace.
|
||||
* @static
|
||||
* @class core
|
||||
*/
|
||||
M.core = M.core || {};
|
||||
|
||||
/**
|
||||
* Actionmenu namespace.
|
||||
* @namespace M.core
|
||||
* @class actionmenu
|
||||
* @static
|
||||
*/
|
||||
M.core.actionmenu = M.core.actionmenu || {};
|
||||
|
||||
/**
|
||||
* Init function - will only ever create one instance of the actionmenu class.
|
||||
* @method init
|
||||
* @static
|
||||
* @param {Object} params
|
||||
*/
|
||||
M.core.actionmenu.init = M.core.actionmenu.init || function(params) {
|
||||
M.core.actionmenu.instance = M.core.actionmenu.instance || new ACTIONMENU(params);
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
"moodle-core-actionmenu": {
|
||||
"requires": [
|
||||
"base",
|
||||
"node",
|
||||
"overlay",
|
||||
"event"
|
||||
"event",
|
||||
"moodle-core-notification"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
+9
@@ -26,6 +26,11 @@ DIALOGUE = function(config) {
|
||||
.append(Y.Node.create('<div class="'+CSS.BODY+' yui3-widget-bd"></div>'))
|
||||
.append(Y.Node.create('<div class="'+CSS.FOOTER+' yui3-widget-ft"></div>')));
|
||||
Y.one(document.body).append(config.notificationBase);
|
||||
|
||||
if (config.additionalBaseClass) {
|
||||
config.notificationBase.addClass(config.additionalBaseClass);
|
||||
}
|
||||
|
||||
config.srcNode = '#'+id;
|
||||
config.width = config.width || '400px';
|
||||
config.visible = config.visible || false;
|
||||
@@ -33,6 +38,10 @@ DIALOGUE = function(config) {
|
||||
config.centered = false;
|
||||
config.COUNT = COUNT;
|
||||
|
||||
if (config.width === 'auto') {
|
||||
delete config.width;
|
||||
}
|
||||
|
||||
// lightbox param to keep the stable versions API.
|
||||
if (config.lightbox !== false) {
|
||||
config.modal = true;
|
||||
|
||||
@@ -1372,3 +1372,31 @@ 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;}
|
||||
|
||||
.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;}
|
||||
.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;}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
.block_adminblock .content,
|
||||
.block .footer {
|
||||
display: block;
|
||||
padding: 3px 15px;
|
||||
padding: 3px 5px;
|
||||
}
|
||||
.block .header .block_action {
|
||||
float: right;
|
||||
|
||||
@@ -1911,65 +1911,121 @@ div.badge .expireimage {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.jsenabled .actions {
|
||||
visibility: hidden;
|
||||
.jsenabled .block .editing_move {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.jsenabled .moodle-actionmenu [data-rel=menu-content] {
|
||||
display:none;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
a.actionmenu {
|
||||
.moodle-actionmenu .toggle-display {
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
|
||||
/*
|
||||
padding-right: 16px;
|
||||
background-image:url([[pix:t/expanded]]);
|
||||
background-position:100% 30%;
|
||||
background-repeat:no-repeat;
|
||||
*/
|
||||
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);
|
||||
}
|
||||
.moodle-actionmenu[data-enhanced] .toggle-display {
|
||||
.opacity(100);
|
||||
}
|
||||
|
||||
.yui3-overlay .actions {
|
||||
visibility: inherit;
|
||||
background-color: @dropdownBackground;
|
||||
border: 1px solid @dropdownBorder;
|
||||
.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;
|
||||
padding: 4px;
|
||||
.border-radius(4px);
|
||||
}
|
||||
|
||||
.autocompletion,
|
||||
a.status .iconsmall {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
.moodle-actionmenu .actionlinktext {
|
||||
display:none;
|
||||
}
|
||||
.statuses .actionlinktext {
|
||||
display: none;
|
||||
.jsenabled .moodle-actionmenu[data-enhanced] .actionlinktext {
|
||||
display:inline;
|
||||
}
|
||||
|
||||
.yui3-overlay .actions a {
|
||||
display: block;
|
||||
color: @dropdownLinkColor;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
}
|
||||
.yui3-overlay .actions a.hidden {
|
||||
display: none;
|
||||
}
|
||||
.yui3-overlay .actions img {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.yui3-overlay .actions a:hover,
|
||||
.yui3-overlay .actions a:focus
|
||||
{
|
||||
color: @dropdownLinkColorHover;
|
||||
background-color: @dropdownLinkBackgroundHover;
|
||||
}
|
||||
|
||||
.block span.actionmenu {
|
||||
display: block;
|
||||
.block .moodle-actionmenu {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.dir-rtl .block span.actionmenu {
|
||||
text-align: left;
|
||||
.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 {
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,8 @@
|
||||
.section .activity .contentafterlink p {
|
||||
margin: .5em 0;
|
||||
}
|
||||
.editing .section .activity:hover {
|
||||
.editing .section .activity:hover,
|
||||
.editing .section .activity.action-menu-shown {
|
||||
background-color: @grayLighter;
|
||||
}
|
||||
.course-content .current {
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user