summaryrefslogtreecommitdiff
path: root/modules/menu
diff options
context:
space:
mode:
authorAngie Byron <webchick@24967.no-reply.drupal.org>2009-11-06 03:17:59 +0000
committerAngie Byron <webchick@24967.no-reply.drupal.org>2009-11-06 03:17:59 +0000
commitad3dde00924063853e54b2d966ed8d91a1e640ab (patch)
tree17d1e2d82f3c0b563380b25439650c8faa279cc3 /modules/menu
parenteeccad8c4bb260d5563ad66757da3a561528bedf (diff)
downloadbrdo-ad3dde00924063853e54b2d966ed8d91a1e640ab.tar.gz
brdo-ad3dde00924063853e54b2d966ed8d91a1e640ab.tar.bz2
#322703 by BarisW, sun, Shai, and dman: Use on/off checkbox to enable and prepopulate node's menu item.
Diffstat (limited to 'modules/menu')
-rw-r--r--modules/menu/menu.js63
-rw-r--r--modules/menu/menu.module151
-rw-r--r--modules/menu/menu.test85
3 files changed, 215 insertions, 84 deletions
diff --git a/modules/menu/menu.js b/modules/menu/menu.js
index 2d4c714c4..f5415099d 100644
--- a/modules/menu/menu.js
+++ b/modules/menu/menu.js
@@ -4,27 +4,58 @@
Drupal.behaviors.menuFieldsetSummaries = {
attach: function (context) {
- $('fieldset#edit-menu', context).setSummary(function (context) {
- return Drupal.checkPlain($('#edit-menu-link-title', context).val()) || Drupal.t('Not in menu');
+ $('fieldset.menu-link-form', context).setSummary(function (context) {
+ if ($('#edit-menu-enabled', context).attr('checked')) {
+ return Drupal.checkPlain($('#edit-menu-link-title', context).val());
+ }
+ else {
+ return Drupal.t('Not in menu');
+ }
});
}
};
-Drupal.behaviors.menuDisplayForm = {
- attach: function () {
- $('fieldset#edit-menu .form-item:first').before('<div class="form-item form-type-checkbox form-item-menu-create"><label for="edit-menu-create" class="option"><input type="checkbox" class="form-checkbox" id="edit-menu-create" name="menu[create]"/> ' + Drupal.t('Create a menu item.') + '</label></div>');
- $('fieldset#edit-menu .form-item:gt(0)').hide();
- $('#edit-menu-create').change(function () {
- if($(this).is(':checked')){
- $('fieldset#edit-menu .form-item:gt(0)').show();
- $('#edit-menu-link-title').val(Drupal.checkPlain($('#edit-title').val())).change();
- }else{
- $('fieldset#edit-menu .form-item:gt(0)').hide();
- $('#edit-menu-link-title').val('').change();
- }
+/**
+ * Automatically fill in a menu link title, if possible.
+ */
+Drupal.behaviors.menuLinkAutomaticTitle = {
+ attach: function (context) {
+ // Try to find menu settings widget elements as well as a 'title' field in
+ // the form, but play nicely with user permissions and form alterations.
+ var $checkbox = $('fieldset.menu-link-form #edit-menu-enabled', context);
+ var $link_title = $('#menu-wrapper #edit-menu-link-title', context);
+ var $title = $('#menu-wrapper', context).closest('form').find('#title-wrapper input.form-text');
+ // Bail out if we do not have all required fields.
+ if (!($checkbox.length && $link_title.length && $title.length)) {
+ return;
+ }
+ // If there is a link title already, mark it as overridden. The user expects
+ // that toggling the checkbox twice will take over the node's title.
+ if ($checkbox.attr('checked') && $link_title.val().length) {
+ $link_title.data('menuLinkAutomaticTitleOveridden', true);
+ }
+ // Whenever the value is changed manually, disable this behavior.
+ $link_title.keyup(function () {
+ $link_title.data('menuLinkAutomaticTitleOveridden', true);
+ });
+ // Global trigger on checkbox (do not fill-in a value when disabled).
+ $checkbox.change(function () {
+ if ($checkbox.attr('checked')) {
+ if (!$link_title.data('menuLinkAutomaticTitleOveridden')) {
+ $link_title.val($title.val());
+ }
+ }
+ else {
+ $link_title.val('');
+ $link_title.removeData('menuLinkAutomaticTitleOveridden');
+ }
+ $checkbox.closest('fieldset.vertical-tabs-pane').trigger('summaryUpdated');
});
- $('#edit-menu-link-title').keyup(function () {
- $('#edit-menu-create').attr('checked', $(this).val());
+ // Take over any title change.
+ $title.keyup(function () {
+ if (!$link_title.data('menuLinkAutomaticTitleOveridden') && $checkbox.attr('checked')) {
+ $link_title.val($title.val());
+ }
});
}
};
diff --git a/modules/menu/menu.module b/modules/menu/menu.module
index 961026e43..89cb5de48 100644
--- a/modules/menu/menu.module
+++ b/modules/menu/menu.module
@@ -300,6 +300,9 @@ function menu_delete($menu) {
* @return
* An array of menu link titles keyed on the a string containing the menu name
* and mlid. The list excludes the given item and its children.
+ *
+ * @todo This has to be turned into a #process form element callback. The
+ * 'menu_override_parent_selector' variable is entirely superfluous.
*/
function menu_parent_options($menus, $item) {
// The menu_links table can be practically any size and we need a way to
@@ -449,40 +452,35 @@ function menu_block_view_alter(&$data, $block) {
* Implement hook_node_insert().
*/
function menu_node_insert(stdClass $node) {
- if (isset($node->menu)) {
- $item = &$node->menu;
- if (!empty($item['delete'])) {
- menu_link_delete($item['mlid']);
- }
- elseif (trim($item['link_title'])) {
- $item['link_title'] = trim($item['link_title']);
- $item['link_path'] = "node/$node->nid";
- if (!$item['customized']) {
- $item['options']['attributes']['title'] = trim($node->title[FIELD_LANGUAGE_NONE][0]['value']);
- }
- if (!menu_link_save($item)) {
- drupal_set_message(t('There was an error saving the menu link.'), 'error');
- }
- }
- }
+ menu_node_save($node);
}
/**
* Implement hook_node_update().
*/
function menu_node_update(stdClass $node) {
+ menu_node_save($node);
+}
+
+/**
+ * Helper for hook_node_insert() and hook_node_update().
+ */
+function menu_node_save(stdClass $node) {
if (isset($node->menu)) {
- $item = &$node->menu;
- if (!empty($item['delete'])) {
- menu_link_delete($item['mlid']);
+ $link = &$node->menu;
+ if (empty($link['enabled'])) {
+ if (!empty($link['mlid'])) {
+ menu_link_delete($link['mlid']);
+ }
}
- elseif (trim($item['link_title'])) {
- $item['link_title'] = trim($item['link_title']);
- $item['link_path'] = "node/$node->nid";
- if (!$item['customized']) {
- $item['options']['attributes']['title'] = trim($node->title[FIELD_LANGUAGE_NONE][0]['value']);
+ elseif (trim($link['link_title'])) {
+ $link['link_title'] = trim($link['link_title']);
+ $link['link_path'] = "node/$node->nid";
+ // If not already set, use the node's title as link title attribute.
+ if (empty($link['options']['attributes']['title']) && !$link['customized']) {
+ $link['options']['attributes']['title'] = trim($node->title[FIELD_LANGUAGE_NONE][0]['value']);
}
- if (!menu_link_save($item)) {
+ if (!menu_link_save($link)) {
drupal_set_message(t('There was an error saving the menu link.'), 'error');
}
}
@@ -525,7 +523,19 @@ function menu_node_prepare(stdClass $node) {
}
}
// Set default values.
- $node->menu = $item + array('link_title' => '', 'mlid' => 0, 'plid' => 0, 'menu_name' => $menu_name, 'weight' => 0, 'options' => array(), 'module' => 'menu', 'expanded' => 0, 'hidden' => 0, 'has_children' => 0, 'customized' => 0);
+ $node->menu = $item + array(
+ 'link_title' => '',
+ 'mlid' => 0,
+ 'plid' => 0,
+ 'menu_name' => $menu_name,
+ 'weight' => 0,
+ 'options' => array(),
+ 'module' => 'menu',
+ 'expanded' => 0,
+ 'hidden' => 0,
+ 'has_children' => 0,
+ 'customized' => 0,
+ );
}
// Find the depth limit for the parent select.
if (!isset($node->menu['parent_depth_limit'])) {
@@ -546,81 +556,92 @@ function _menu_parent_depth_limit($item) {
function menu_form_alter(&$form, $form_state, $form_id) {
if (!empty($form['#node_edit_form'])) {
// Generate a list of possible parents.
+ // @todo This must be handled in a #process handler.
$type = $form['#node']->type;
$options = menu_parent_options(menu_get_menus(), $type);
- if (count($options) == 0) {
- // No possible parent menu items found so there is no need to display the
- // menu options.
+ // If no possible parent menu items were found, there is nothing to display.
+ if (empty($options)) {
return;
}
-
- // Note - doing this to make sure the delete checkbox stays in the form.
- $form['#cache'] = TRUE;
+ $link = $form['#node']->menu;
+ $form['#submit'][] = 'menu_node_form_submit';
$form['menu'] = array(
'#type' => 'fieldset',
'#title' => t('Menu settings'),
'#access' => user_access('administer menu'),
'#collapsible' => TRUE,
- '#collapsed' => FALSE,
+ '#collapsed' => !$link['link_title'],
'#group' => 'additional_settings',
'#attached' => array(
'js' => array(drupal_get_path('module', 'menu') . '/menu.js'),
),
'#tree' => TRUE,
'#weight' => -2,
- '#attributes' => array('class' => array('menu-item-form')),
+ '#attributes' => array('class' => array('menu-link-form')),
+ );
+ $form['menu']['enabled'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Provide a menu link'),
+ '#default_value' => (int) (bool) $link['mlid'],
+ );
+ $form['menu']['link'] = array(
+ '#type' => 'container',
+ '#parents' => array('menu'),
+ '#states' => array(
+ 'invisible' => array(
+ 'input[name="menu[enabled]"]' => array('checked' => FALSE),
+ ),
+ ),
);
- $item = $form['#node']->menu;
-
- if ($item['mlid']) {
- // There is an existing link.
- $form['menu']['delete'] = array(
- '#type' => 'checkbox',
- '#title' => t('Delete this menu item.'),
- );
- }
- if (!$item['link_title']) {
- $form['menu']['#collapsed'] = TRUE;
- }
+ // Populate the element with the link data.
foreach (array('mlid', 'module', 'hidden', 'has_children', 'customized', 'options', 'expanded', 'hidden', 'parent_depth_limit') as $key) {
- $form['menu'][$key] = array('#type' => 'value', '#value' => $item[$key]);
+ $form['menu']['link'][$key] = array('#type' => 'value', '#value' => $link[$key]);
}
- $form['menu']['#item'] = $item;
- $form['menu']['link_title'] = array('#type' => 'textfield',
+ $form['menu']['link']['link_title'] = array(
+ '#type' => 'textfield',
'#title' => t('Menu link title'),
- '#default_value' => $item['link_title'],
- '#description' => t('The link text corresponding to this item that should appear in the menu. Leave blank if you do not wish to add this post to the menu.'),
- '#required' => FALSE,
+ '#default_value' => $link['link_title'],
);
- $default = ($item['mlid'] ? $item['menu_name'] . ':' . $item['plid'] : variable_get('menu_parent_' . $type, 'main-menu:0'));
+ $default = ($link['mlid'] ? $link['menu_name'] . ':' . $link['plid'] : variable_get('menu_parent_' . $type, 'main-menu:0'));
+ // @todo This will fail with the new selective menus per content type.
if (!isset($options[$default])) {
$default = 'navigation:0';
}
- $form['menu']['parent'] = array(
+ $form['menu']['link']['parent'] = array(
'#type' => 'select',
'#title' => t('Parent item'),
'#default_value' => $default,
'#options' => $options,
- '#description' => t('The maximum depth for an item and all its children is fixed at !maxdepth. Some menu items may not be available as parents if selecting them would exceed this limit.', array('!maxdepth' => MENU_MAX_DEPTH)),
- '#attributes' => array('class' => array('menu-title-select')),
+ '#attributes' => array('class' => array('menu-parent-select')),
);
- $form['#submit'][] = 'menu_node_form_submit';
-
- $form['menu']['weight'] = array(
+ $form['menu']['link']['weight'] = array(
'#type' => 'weight',
'#title' => t('Weight'),
'#delta' => 50,
- '#default_value' => $item['weight'],
- '#description' => t('Optional. In the menu, the heavier items will sink and the lighter items will be positioned nearer the top.'),
+ '#default_value' => $link['weight'],
+ '#description' => t('Menu links with smaller weights are displayed before links with larger weights.'),
);
}
}
/**
+ * Submit handler for node form.
+ *
+ * @see menu_form_alter()
+ */
+function menu_node_form_submit($form, &$form_state) {
+ // Decompose the selected menu parent option into 'menu_name' and 'plid', if
+ // the form used the default parent selection widget.
+ if (!empty($form_state['values']['menu']['parent'])) {
+ list($form_state['values']['menu']['menu_name'], $form_state['values']['menu']['plid']) = explode(':', $form_state['values']['menu']['parent']);
+ }
+}
+
+/**
* Implement hook_form_FORM_ID_alter() for the node type form.
* Adds menu options to the node type form.
*/
@@ -647,6 +668,7 @@ function menu_form_node_type_form_alter(&$form, $form_state) {
// To avoid an 'illegal option' error after saving the form we have to load
// all available menu items.
// Otherwise it is not possible to dynamically add options to the list.
+ // @todo Convert menu_parent_options() into a #process callback.
$options = menu_parent_options(menu_get_menus(), array('mlid' => 0));
$form['menu']['menu_parent'] = array(
'#type' => 'select',
@@ -666,13 +688,6 @@ function menu_form_node_type_form_alter(&$form, $form_state) {
}
/**
- * Decompose the selected menu parent option into the menu_name and plid.
- */
-function menu_node_form_submit($form, &$form_state) {
- list($form_state['values']['menu']['menu_name'], $form_state['values']['menu']['plid']) = explode(':', $form_state['values']['menu']['parent']);
-}
-
-/**
* Return an associative array of the custom menus names.
*
* @param $all
diff --git a/modules/menu/menu.test b/modules/menu/menu.test
index 38a44539c..9eab7ee13 100644
--- a/modules/menu/menu.test
+++ b/modules/menu/menu.test
@@ -511,3 +511,88 @@ class MenuTestCase extends DrupalWebTestCase {
}
}
}
+
+/**
+ * Test menu settings for nodes.
+ */
+class MenuNodeTestCase extends DrupalWebTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'Menu settings for nodes',
+ 'description' => 'Add, edit, and delete a node with menu link.',
+ 'group' => 'Menu',
+ );
+ }
+
+ function setUp() {
+ parent::setUp('menu');
+
+ $this->admin_user = $this->drupalCreateUser(array(
+ 'access administration pages',
+ 'administer content types',
+ 'administer menu',
+ 'create page content',
+ 'edit any page content',
+ 'delete any page content',
+ ));
+ $this->drupalLogin($this->admin_user);
+ }
+
+ /**
+ * Test creating, editing, deleting menu links via node form widget.
+ */
+ function testMenuNodeFormWidget() {
+ // Enable Navigation menu as available menu.
+ $edit = array(
+ 'menu_options[navigation]' => 1,
+ );
+ $this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
+ // Change default parent item to Navigation menu, so we can assert more
+ // easily.
+ $edit = array(
+ 'menu_parent' => 'navigation:0',
+ );
+ $this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
+
+ // Create a node.
+ $node_title = $this->randomName();
+ $edit = array(
+ 'title[zxx][0][value]' => $node_title,
+ 'body[zxx][0][value]' => $this->randomString(),
+ );
+ $this->drupalPost('node/add/page', $edit, t('Save'));
+ $node = $this->drupalGetNodeByTitle($node_title);
+ // Assert that there is no link for the node.
+ $this->drupalGet('');
+ $this->assertNoLink($node_title);
+
+ // Edit the node, enable the menu link setting, but skip the link title.
+ $edit = array(
+ 'menu[enabled]' => 1,
+ );
+ $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+ // Assert that there is no link for the node.
+ $this->drupalGet('');
+ $this->assertNoLink($node_title);
+
+ // Edit the node and create a menu link.
+ $edit = array(
+ 'menu[enabled]' => 1,
+ 'menu[link_title]' => $node_title,
+ );
+ $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+ // Assert that the link exists.
+ $this->drupalGet('');
+ $this->assertLink($node_title);
+
+ // Edit the node and remove the menu link.
+ $edit = array(
+ 'menu[enabled]' => FALSE,
+ );
+ $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+ // Assert that there is no link for the node.
+ $this->drupalGet('');
+ $this->assertNoLink($node_title);
+ }
+}
+