From 21f792d835f898e0fd23768e0d8238c4acf92073 Mon Sep 17 00:00:00 2001 From: Beat Date: Wed, 10 Jul 2013 02:01:34 +0100 Subject: [PATCH 01/13] [JUX2] Front-end modules and menu editing: part 1: Cleanup admin area --- .../components/com_modules/controller.php | 20 +++-------- libraries/legacy/controller/form.php | 33 ------------------- 2 files changed, 5 insertions(+), 48 deletions(-) diff --git a/administrator/components/com_modules/controller.php b/administrator/components/com_modules/controller.php index d00fa1466fd31..f95a52585f9d2 100644 --- a/administrator/components/com_modules/controller.php +++ b/administrator/components/com_modules/controller.php @@ -21,10 +21,11 @@ class ModulesController extends JControllerLegacy /** * Method to display a view. * - * @param boolean If true, the view output will be cached - * @param array An array of safe url parameters and their variable types, for valid values see {@link JFilterInput::clean()}. + * @param boolean $cachable If true, the view output will be cached + * @param array|boolean $urlparams An array of safe url parameters and their variable types, for valid values see {@link JFilterInput::clean()} + . * - * @return JController This object to support chaining. + * @return JController This object to support chaining. * @since 1.5 */ public function display($cachable = false, $urlparams = false) @@ -38,17 +39,6 @@ public function display($cachable = false, $urlparams = false) $layout = $this->input->get('layout', 'default'); $id = $this->input->getInt('id'); - // Check for edit form. - if ($view == 'module' && $layout == 'edit' && !$this->checkEditId('com_modules.edit.module', $id)) - { - // Somehow the person just went to the form - we don't allow that. - $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id)); - $this->setMessage($this->getError(), 'error'); - $this->setRedirect(JRoute::_('index.php?option=com_modules&view=modules', false)); - - return false; - } - - parent::display(); + return parent::display(); } } diff --git a/libraries/legacy/controller/form.php b/libraries/legacy/controller/form.php index ca2d211792430..4d421ee74db77 100644 --- a/libraries/legacy/controller/form.php +++ b/libraries/legacy/controller/form.php @@ -311,23 +311,6 @@ public function cancel($key = null) // Attempt to check-in the current record. if ($recordId) { - // Check we are holding the id in the edit list. - if (!$this->checkEditId($context, $recordId)) - { - // Somehow the person just went to the form - we don't allow that. - $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $recordId)); - $this->setMessage($this->getError(), 'error'); - - $this->setRedirect( - JRoute::_( - 'index.php?option=' . $this->option . '&view=' . $this->view_list - . $this->getRedirectToListAppend(), false - ) - ); - - return false; - } - if ($checkin) { if ($model->checkin($recordId) === false) @@ -650,22 +633,6 @@ public function save($key = null, $urlVar = null) $recordId = $this->input->getInt($urlVar); - if (!$this->checkEditId($context, $recordId)) - { - // Somehow the person just went to the form and tried to save it. We don't allow that. - $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $recordId)); - $this->setMessage($this->getError(), 'error'); - - $this->setRedirect( - JRoute::_( - 'index.php?option=' . $this->option . '&view=' . $this->view_list - . $this->getRedirectToListAppend(), false - ) - ); - - return false; - } - // Populate the row id from the session. $data[$key] = $recordId; From 2a63ef899074f294a2651e4e89ec6149585fb9f1 Mon Sep 17 00:00:00 2001 From: Beat Date: Wed, 10 Jul 2013 00:58:34 +0100 Subject: [PATCH 02/13] [JUX2] Front-end modules and menu editing: part 2: Add Front-end Modules editing (first version) --- .../language/en-GB/en-GB.lib_joomla.ini | 2 + language/en-GB/en-GB.lib_joomla.ini | 2 + .../joomla/document/html/renderer/modules.php | 38 ++++++++++++++++++- media/system/css/frontediting.css | 18 +++++++++ media/system/js/frontediting.js | 28 ++++++++++++++ 5 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 media/system/css/frontediting.css create mode 100644 media/system/js/frontediting.js diff --git a/administrator/language/en-GB/en-GB.lib_joomla.ini b/administrator/language/en-GB/en-GB.lib_joomla.ini index 9551ff0442f5a..c4ab4231b9e60 100644 --- a/administrator/language/en-GB/en-GB.lib_joomla.ini +++ b/administrator/language/en-GB/en-GB.lib_joomla.ini @@ -380,6 +380,8 @@ JLIB_HTML_DATE_RELATIVE_WEEKS="%s weeks ago" JLIB_HTML_DATE_RELATIVE_WEEKS_1="%s week ago" JLIB_HTML_DATE_RELATIVE_WEEKS_0="%s weeks ago" JLIB_HTML_EDITOR_CANNOT_LOAD="Cannot load the editor" +JLIB_HTML_EDIT_MODULE="Edit Module" +JLIB_HTML_EDIT_MODULE_IN_POSITION="Position: %s" JLIB_HTML_END="End" JLIB_HTML_ERROR_FUNCTION_NOT_SUPPORTED="Function not supported." JLIB_HTML_ERROR_NOTFOUNDINFILE="%s: :%s not found in file." diff --git a/language/en-GB/en-GB.lib_joomla.ini b/language/en-GB/en-GB.lib_joomla.ini index f1e55cdf82148..29cf87d70f069 100644 --- a/language/en-GB/en-GB.lib_joomla.ini +++ b/language/en-GB/en-GB.lib_joomla.ini @@ -379,6 +379,8 @@ JLIB_HTML_DATE_RELATIVE_WEEKS="%s weeks ago" JLIB_HTML_DATE_RELATIVE_WEEKS_1="%s week ago" JLIB_HTML_DATE_RELATIVE_WEEKS_0="%s weeks ago" JLIB_HTML_EDITOR_CANNOT_LOAD="Cannot load the editor" +JLIB_HTML_EDIT_MODULE="Edit Module" +JLIB_HTML_EDIT_MODULE_IN_POSITION="Position: %s" JLIB_HTML_END="End" JLIB_HTML_ERROR_FUNCTION_NOT_SUPPORTED="Function not supported." JLIB_HTML_ERROR_NOTFOUNDINFILE="%s: :%s not found in file." diff --git a/libraries/joomla/document/html/renderer/modules.php b/libraries/joomla/document/html/renderer/modules.php index 47d29207419fe..686ef0e792cd2 100644 --- a/libraries/joomla/document/html/renderer/modules.php +++ b/libraries/joomla/document/html/renderer/modules.php @@ -31,12 +31,48 @@ class JDocumentRendererModules extends JDocumentRenderer */ public function render($position, $params = array(), $content = null) { + static $jsNotOut =true; + + $app = JFactory::getApplication(); + $renderer = $this->_doc->loadRenderer('module'); $buffer = ''; foreach (JModuleHelper::getModules($position) as $mod) { - $buffer .= $renderer->render($mod, $params, $content); + $moduleHtml = trim($renderer->render($mod, $params, $content)); + + if (!$moduleHtml) + { + continue; + } + + + if ($app->isAdmin() + || !JFactory::getUser()->authorise('core.manage', 'com_modules') + || preg_match('/<(?:div|span|nav|ul) [^>]*class="[^"]* jmoddiv"/', $moduleHtml)) + { + // Module isn't enclosing in a div with class or handles already module edit button: + $buffer .= $moduleHtml; + continue; + } + + // Add css class jmoddiv and data attributes for module-editing URL and for the tooltip: + $editUrl = JURI::base() . 'administrator/' . 'index.php?option=com_modules&view=module&layout=edit&id=' . (int) $mod->id; + + $buffer .= preg_replace('/^(<(?:div|span|nav|ul) [^>]*class="[^"]*)"/', + '\\1 jmoddiv" data-jmodediturl="' . $editUrl . '" data-jmodtip="' . sprintf(JHtml::tooltipText('JLIB_HTML_EDIT_MODULE', 'JLIB_HTML_EDIT_MODULE_IN_POSITION'), htmlspecialchars($position)) . '"', $moduleHtml); + + if ($jsNotOut) + { + // Load once booststrap tooltip and add stylesheet and javascript to head: + $jsNotOut = false; + JHtml::_('bootstrap.tooltip'); + + JFactory::getDocument()->addStyleSheet('media/system/css/frontediting.css') + ->addScript('media/system/js/frontediting.js'); + } + } return $buffer; } diff --git a/media/system/css/frontediting.css b/media/system/css/frontediting.css new file mode 100644 index 0000000000000..3cb24a5c32c96 --- /dev/null +++ b/media/system/css/frontediting.css @@ -0,0 +1,18 @@ +/** + * @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +.jmoddiv.jmodinside { + position: relative; + top: 0; + left: 0; +} +.jmoddiv.jmodinside .btn.jmodedit +{ + z-index: 5000; + display: block; + position: absolute; + top: 0; + right: 0; +} diff --git a/media/system/js/frontediting.js b/media/system/js/frontediting.js new file mode 100644 index 0000000000000..58b82bbec8a6b --- /dev/null +++ b/media/system/js/frontediting.js @@ -0,0 +1,28 @@ +/** + * @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +/** + * JavaScript behavior to allow shift select in administrator grids + * + */ +(function($) { + + $(document).ready(function (){ + $('.jmoddiv').on({ + click: function(){ + $(this).toggleClass("jmodactive"); + }, + mouseenter: function(){ + var moduleEditUrl = $(this).data('jmodediturl'); + var moduleTip = $(this).data('jmodtip'); + $(this).addClass("jmodinside").prepend('' + + '').children(":first").attr('href', moduleEditUrl).attr('title', moduleTip).tooltip({"container": false}); + }, + mouseleave: function(){ + $(this).removeClass("jmodinside").find('.btn.jmodedit').remove(); + }}); + }); + +})(jQuery); From 874b687a8be1a4e77df1cf23b67df153b3f00639 Mon Sep 17 00:00:00 2001 From: Beat Date: Sat, 13 Jul 2013 17:02:48 +0200 Subject: [PATCH 03/13] [JUX2] Front-end modules and menu editing: part 3: Add Front-end Modules editing (final version) --- .../components/com_menus/controller.php | 26 +--- .../components/com_menus/controllers/item.php | 10 -- .../components/com_menus/controllers/menu.php | 10 -- .../language/en-GB/en-GB.lib_joomla.ini | 6 +- language/en-GB/en-GB.lib_joomla.ini | 6 +- .../joomla/document/html/renderer/modules.php | 15 +- media/system/css/frontediting.css | 14 +- media/system/js/frontediting.js | 140 ++++++++++++++++-- 8 files changed, 163 insertions(+), 64 deletions(-) diff --git a/administrator/components/com_menus/controller.php b/administrator/components/com_menus/controller.php index 04e53ceda7669..28881f565b6e8 100644 --- a/administrator/components/com_menus/controller.php +++ b/administrator/components/com_menus/controller.php @@ -21,10 +21,10 @@ class MenusController extends JControllerLegacy /** * Method to display a view. * - * @param boolean If true, the view output will be cached - * @param array An array of safe url parameters and their variable types, for valid values see {@link JFilterInput::clean()}. + * @param boolean $cachable If true, the view output will be cached + * @param array|boolean $urlparams An array of safe url parameters and their variable types, for valid values see {@link JFilterInput::clean()}. * - * @return JController This object to support chaining. + * @return JController This object to support chaining. * @since 1.5 */ public function display($cachable = false, $urlparams = false) @@ -35,26 +35,6 @@ public function display($cachable = false, $urlparams = false) $layout = $this->input->get('layout', 'default'); $id = $this->input->getInt('id'); - // Check for edit form. - if ($view == 'menu' && $layout == 'edit' && !$this->checkEditId('com_menus.edit.menu', $id)) { - - // Somehow the person just went to the form - we don't allow that. - $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id)); - $this->setMessage($this->getError(), 'error'); - $this->setRedirect(JRoute::_('index.php?option=com_menus&view=menus', false)); - - return false; - } - elseif ($view == 'item' && $layout == 'edit' && !$this->checkEditId('com_menus.edit.item', $id)) { - - // Somehow the person just went to the form - we don't allow that. - $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id)); - $this->setMessage($this->getError(), 'error'); - $this->setRedirect(JRoute::_('index.php?option=com_menus&view=items', false)); - - return false; - } - parent::display(); return $this; diff --git a/administrator/components/com_menus/controllers/item.php b/administrator/components/com_menus/controllers/item.php index ab6d670ec23dc..c8bdbc1ceaf10 100644 --- a/administrator/components/com_menus/controllers/item.php +++ b/administrator/components/com_menus/controllers/item.php @@ -138,16 +138,6 @@ public function save($key = null, $urlVar = null) $context = 'com_menus.edit.item'; $recordId = $this->input->getInt('id'); - if (!$this->checkEditId($context, $recordId)) - { - // Somehow the person just went to the form and saved it - we don't allow that. - $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $recordId)); - $this->setMessage($this->getError(), 'error'); - $this->setRedirect(JRoute::_('index.php?option=com_menus&view=items' . $this->getRedirectToListAppend(), false)); - - return false; - } - // Populate the row id from the session. $data['id'] = $recordId; diff --git a/administrator/components/com_menus/controllers/menu.php b/administrator/components/com_menus/controllers/menu.php index f0849f8dd7e91..a4146c437a722 100644 --- a/administrator/components/com_menus/controllers/menu.php +++ b/administrator/components/com_menus/controllers/menu.php @@ -48,16 +48,6 @@ public function save($key = null, $urlVar = null) $task = $this->getTask(); $recordId = $this->input->getInt('id'); - if (!$this->checkEditId($context, $recordId)) - { - // Somehow the person just went to the form and saved it - we don't allow that. - $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $recordId)); - $this->setMessage($this->getError(), 'error'); - $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_list.$this->getRedirectToListAppend(), false)); - - return false; - } - // Make sure we are not trying to modify an administrator menu. if (isset($data['client_id']) && $data['client_id'] == 1){ JError::raiseNotice(0, JText::_('COM_MENUS_MENU_TYPE_NOT_ALLOWED')); diff --git a/administrator/language/en-GB/en-GB.lib_joomla.ini b/administrator/language/en-GB/en-GB.lib_joomla.ini index c4ab4231b9e60..6cf7b1156e42e 100644 --- a/administrator/language/en-GB/en-GB.lib_joomla.ini +++ b/administrator/language/en-GB/en-GB.lib_joomla.ini @@ -379,6 +379,10 @@ JLIB_HTML_DATE_RELATIVE_MINUTES_0="%s minutes ago" JLIB_HTML_DATE_RELATIVE_WEEKS="%s weeks ago" JLIB_HTML_DATE_RELATIVE_WEEKS_1="%s week ago" JLIB_HTML_DATE_RELATIVE_WEEKS_0="%s weeks ago" +JLIB_HTML_EDIT_MENU_ITEM="Edit menu item" +JLIB_HTML_EDIT_MENU_ITEM_ID="Item id: %s" +JLIB_HTML_EDIT_MODULE="Edit module" +JLIB_HTML_EDIT_MODULE_IN_POSITION="Position: %s" JLIB_HTML_EDITOR_CANNOT_LOAD="Cannot load the editor" JLIB_HTML_EDIT_MODULE="Edit Module" JLIB_HTML_EDIT_MODULE_IN_POSITION="Position: %s" @@ -457,8 +461,8 @@ JLIB_INSTALLER_ABORT_MOD_UNKNOWN_CLIENT="Module %1$s: Unknown client type [%2$s] JLIB_INSTALLER_ABORT_NOINSTALLPATH="Install path does not exist" JLIB_INSTALLER_ABORT_NOUPDATEPATH="Update path does not exist" JLIB_INSTALLER_ABORT_PACK_INSTALL_COPY_SETUP="Package Install: Could not copy setup file." -JLIB_INSTALLER_ABORT_PACK_INSTALL_CREATE_DIRECTORY="Package Install: Failed to create directory:%s " JLIB_INSTALLER_ABORT_PACKAGE_INSTALL_MANIFEST="Installation failed: Could not copy PHP manifest file." +JLIB_INSTALLER_ABORT_PACK_INSTALL_CREATE_DIRECTORY="Package Install: Failed to create directory:%s " JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION="Package %1$s: There was an error installing an extension: %2$s" JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_FILES="Package %s: There were no files to install!" JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_PACK="Package %s: No package file specified" diff --git a/language/en-GB/en-GB.lib_joomla.ini b/language/en-GB/en-GB.lib_joomla.ini index 29cf87d70f069..b5e1496048265 100644 --- a/language/en-GB/en-GB.lib_joomla.ini +++ b/language/en-GB/en-GB.lib_joomla.ini @@ -378,9 +378,11 @@ JLIB_HTML_DATE_RELATIVE_MINUTES_0="%s minutes ago" JLIB_HTML_DATE_RELATIVE_WEEKS="%s weeks ago" JLIB_HTML_DATE_RELATIVE_WEEKS_1="%s week ago" JLIB_HTML_DATE_RELATIVE_WEEKS_0="%s weeks ago" -JLIB_HTML_EDITOR_CANNOT_LOAD="Cannot load the editor" -JLIB_HTML_EDIT_MODULE="Edit Module" +JLIB_HTML_EDIT_MENU_ITEM="Edit menu item" +JLIB_HTML_EDIT_MENU_ITEM_ID="Item id: %s" +JLIB_HTML_EDIT_MODULE="Edit module" JLIB_HTML_EDIT_MODULE_IN_POSITION="Position: %s" +JLIB_HTML_EDITOR_CANNOT_LOAD="Cannot load the editor" JLIB_HTML_END="End" JLIB_HTML_ERROR_FUNCTION_NOT_SUPPORTED="Function not supported." JLIB_HTML_ERROR_NOTFOUNDINFILE="%s: :%s not found in file." diff --git a/libraries/joomla/document/html/renderer/modules.php b/libraries/joomla/document/html/renderer/modules.php index 686ef0e792cd2..3875647a16240 100644 --- a/libraries/joomla/document/html/renderer/modules.php +++ b/libraries/joomla/document/html/renderer/modules.php @@ -38,6 +38,8 @@ public function render($position, $params = array(), $content = null) $renderer = $this->_doc->loadRenderer('module'); $buffer = ''; + $cannotEditFrontend = $app->isAdmin() || !JFactory::getUser()->authorise('core.manage', 'com_modules'); + foreach (JModuleHelper::getModules($position) as $mod) { $moduleHtml = trim($renderer->render($mod, $params, $content)); @@ -47,9 +49,7 @@ public function render($position, $params = array(), $content = null) continue; } - - if ($app->isAdmin() - || !JFactory::getUser()->authorise('core.manage', 'com_modules') + if ($cannotEditFrontend || preg_match('/<(?:div|span|nav|ul) [^>]*class="[^"]* jmoddiv"/', $moduleHtml)) { // Module isn't enclosing in a div with class or handles already module edit button: @@ -60,14 +60,21 @@ public function render($position, $params = array(), $content = null) // Add css class jmoddiv and data attributes for module-editing URL and for the tooltip: $editUrl = JURI::base() . 'administrator/' . 'index.php?option=com_modules&view=module&layout=edit&id=' . (int) $mod->id; + // Add class, editing URL and tooltip, and if module of type menu, also the tooltip for editing the menu item: $buffer .= preg_replace('/^(<(?:div|span|nav|ul) [^>]*class="[^"]*)"/', - '\\1 jmoddiv" data-jmodediturl="' . $editUrl . '" data-jmodtip="' . sprintf(JHtml::tooltipText('JLIB_HTML_EDIT_MODULE', 'JLIB_HTML_EDIT_MODULE_IN_POSITION'), htmlspecialchars($position)) . '"', $moduleHtml); + '\\1 jmoddiv" data-jmodediturl="' . $editUrl. '"' + . ' data-jmodtip="' + . JHtml::tooltipText(JText::_('JLIB_HTML_EDIT_MODULE'), htmlspecialchars($mod->title) . '
' . sprintf(JText::_('JLIB_HTML_EDIT_MODULE_IN_POSITION'), htmlspecialchars($position)), 0) + . '"' + . ($mod->module == 'mod_menu' ? '" data-jmenuedittip="' . JHtml::tooltipText('JLIB_HTML_EDIT_MENU_ITEM', 'JLIB_HTML_EDIT_MENU_ITEM_ID') . '"' : ''), + $moduleHtml); if ($jsNotOut) { // Load once booststrap tooltip and add stylesheet and javascript to head: $jsNotOut = false; JHtml::_('bootstrap.tooltip'); + JHtml::_('bootstrap.popover'); JFactory::getDocument()->addStyleSheet('media/system/css/frontediting.css') ->addScript('media/system/js/frontediting.js'); diff --git a/media/system/css/frontediting.css b/media/system/css/frontediting.css index 3cb24a5c32c96..e2bd561766a00 100644 --- a/media/system/css/frontediting.css +++ b/media/system/css/frontediting.css @@ -3,16 +3,26 @@ * @license GNU General Public License version 2 or later; see LICENSE.txt */ +/* Module edit in front-end */ + .jmoddiv.jmodinside { position: relative; top: 0; left: 0; } -.jmoddiv.jmodinside .btn.jmodedit +.btn.jmodedit { - z-index: 5000; + z-index: 1001; display: block; position: absolute; top: 0; right: 0; } + +/* Menu edit in front-end */ + +.btn.jfedit-menu +{ + z-index: 1002; + display: block; +} diff --git a/media/system/js/frontediting.js b/media/system/js/frontediting.js index 58b82bbec8a6b..98d5e73f25faa 100644 --- a/media/system/js/frontediting.js +++ b/media/system/js/frontediting.js @@ -4,25 +4,141 @@ */ /** - * JavaScript behavior to allow shift select in administrator grids + * JavaScript behavior to add front-end hover edit icons with tooltips for modules and menu items. * */ (function($) { - $(document).ready(function (){ + $.fn.extend({ + /** + * This jQuery custom method makes the elements absolute, and with true argument moves them to end of body to avoid CSS inheritence + * + * @param rebase boolean + * @returns {jQuery} + */ + jEditMakeAbsolute: function(rebase) { + + return this.each(function() { + + var el = $(this); + var pos; + + if (rebase) { + pos = el.offset(); + } else { + pos = el.position(); + } + + el.css({ position: "absolute", + marginLeft: 0, marginTop: 0, + top: pos.top, left: pos.left, + width: el.width(), height: el.height() + }); + + if (rebase) { + el.detach().appendTo("body"); + } + }); + + } + }); + + $(document).ready(function () { + + // Modules edit icons: + $('.jmoddiv').on({ - click: function(){ - $(this).toggleClass("jmodactive"); - }, - mouseenter: function(){ + mouseenter: function() { + + // Get module editing URL and tooltip for module edit: var moduleEditUrl = $(this).data('jmodediturl'); var moduleTip = $(this).data('jmodtip'); - $(this).addClass("jmodinside").prepend('' - + '').children(":first").attr('href', moduleEditUrl).attr('title', moduleTip).tooltip({"container": false}); + + // Stop timeout on previous tooltip and remove it: + $('body>.btn.jmodedit').clearQueue().tooltip('destroy').remove(); + + // Add editing button with tooltip: + $(this).addClass('jmodinside') + .prepend('') + .children(":first").attr('href', moduleEditUrl).attr('title', moduleTip) + .tooltip({"container": false}) + .jEditMakeAbsolute(true); + // This class was needed for positioning the icon before making it absolute at bottom of body: We can now remove it: + $(this).removeClass('jmodinside'); + + $('.btn.jmodedit') + .on({ + mouseenter: function() { + // Stop delayed removal programmed by mouseleave of .jmoddiv or of this one: + $(this).clearQueue(); + }, + mouseleave: function() { + // Delay remove editing button if not hovering it: + $(this).delay(500).queue(function(next) { + $(this).tooltip('destroy').remove(); + next(); + }); + } + }); }, - mouseleave: function(){ - $(this).removeClass("jmodinside").find('.btn.jmodedit').remove(); - }}); - }); + mouseleave: function() { + + // Delay remove editing button if not hovering it: + $('body>.btn.jmodedit').delay(500).queue(function(next) { + $(this).tooltip('destroy').remove(); + next(); + }); + } + }); + + // Menu items edit icons: + + var activePopover = null; + + $('.jmoddiv .nav li,.jmoddiv.nav li,.jmoddiv .nav .nav-child li,.jmoddiv.nav .nav-child li').on({ + mouseenter: function() { + + // Get menu ItemId from the item-nnn class of the li element of the menu: + var itemids = /\bitem-(\d+)\b/.exec($(this).attr('class')); + if (typeof itemids[1] == 'string') { + // Find module editing URL from enclosing module: + var enclosingModuleDiv = $(this).closest('.jmoddiv'); + var moduleEditUrl = enclosingModuleDiv.data('jmodediturl'); + // Transform module editing URL into Menu Item editing url: + var menuitemEditUrl = moduleEditUrl.replace(/\/index.php\?option=com_modules&view=module([^\d]+)\d+$/, '/index.php?option=com_menus&view=item$1' + itemids[1]); + } + + // Get tooltip for menu items from enclosing module + var menuEditTip = enclosingModuleDiv.data('jmenuedittip').replace('%s', itemids[1]); + + var content = $('
'); + content.children('a.jfedit-menu').prop('href', menuitemEditUrl).prop('title', menuEditTip); + + if (activePopover) { + $(activePopover).popover('hide'); + } + $(this).popover({html:true, content:content.html(), container:'body', trigger:'manual', animation:false}).popover('show'); + activePopover = this; + + $('body>div.popover') + .on({ + mouseenter: function() { + if (activePopover) { + $(activePopover).clearQueue(); + } + }, + mouseleave: function() { + if (activePopover) { + $(activePopover).popover('hide'); + } + } + }) + .find('a.jfedit-menu').tooltip({"container": false}); + }, + mouseleave: function() { + $(this).delay(1500).queue(function(next) { $(this).popover('hide'); next() }); + } + }); + }); })(jQuery); From 6ad383fa488c17fee1b2b2c5ad02ea08ea1f6027 Mon Sep 17 00:00:00 2001 From: Beat Date: Thu, 3 Oct 2013 00:38:44 +0200 Subject: [PATCH 04/13] [JUX2] Front-end modules editing: Removed menus-editing and moved to JLayout the editing code --- .../components/com_menus/controller.php | 26 +++++++- .../components/com_menus/controllers/item.php | 10 ++++ .../components/com_menus/controllers/menu.php | 10 ++++ .../language/en-GB/en-GB.lib_joomla.ini | 4 +- layouts/joomla/edit/frontediting_modules.php | 60 +++++++++++++++++++ .../joomla/document/html/renderer/modules.php | 45 +------------- media/system/css/frontediting.css | 8 --- media/system/js/frontediting.js | 49 --------------- 8 files changed, 106 insertions(+), 106 deletions(-) create mode 100644 layouts/joomla/edit/frontediting_modules.php diff --git a/administrator/components/com_menus/controller.php b/administrator/components/com_menus/controller.php index 28881f565b6e8..04e53ceda7669 100644 --- a/administrator/components/com_menus/controller.php +++ b/administrator/components/com_menus/controller.php @@ -21,10 +21,10 @@ class MenusController extends JControllerLegacy /** * Method to display a view. * - * @param boolean $cachable If true, the view output will be cached - * @param array|boolean $urlparams An array of safe url parameters and their variable types, for valid values see {@link JFilterInput::clean()}. + * @param boolean If true, the view output will be cached + * @param array An array of safe url parameters and their variable types, for valid values see {@link JFilterInput::clean()}. * - * @return JController This object to support chaining. + * @return JController This object to support chaining. * @since 1.5 */ public function display($cachable = false, $urlparams = false) @@ -35,6 +35,26 @@ public function display($cachable = false, $urlparams = false) $layout = $this->input->get('layout', 'default'); $id = $this->input->getInt('id'); + // Check for edit form. + if ($view == 'menu' && $layout == 'edit' && !$this->checkEditId('com_menus.edit.menu', $id)) { + + // Somehow the person just went to the form - we don't allow that. + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id)); + $this->setMessage($this->getError(), 'error'); + $this->setRedirect(JRoute::_('index.php?option=com_menus&view=menus', false)); + + return false; + } + elseif ($view == 'item' && $layout == 'edit' && !$this->checkEditId('com_menus.edit.item', $id)) { + + // Somehow the person just went to the form - we don't allow that. + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id)); + $this->setMessage($this->getError(), 'error'); + $this->setRedirect(JRoute::_('index.php?option=com_menus&view=items', false)); + + return false; + } + parent::display(); return $this; diff --git a/administrator/components/com_menus/controllers/item.php b/administrator/components/com_menus/controllers/item.php index e7bf9a752abd1..391bc6344d896 100644 --- a/administrator/components/com_menus/controllers/item.php +++ b/administrator/components/com_menus/controllers/item.php @@ -138,6 +138,16 @@ public function save($key = null, $urlVar = null) $context = 'com_menus.edit.item'; $recordId = $this->input->getInt('id'); + if (!$this->checkEditId($context, $recordId)) + { + // Somehow the person just went to the form and saved it - we don't allow that. + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $recordId)); + $this->setMessage($this->getError(), 'error'); + $this->setRedirect(JRoute::_('index.php?option=com_menus&view=items' . $this->getRedirectToListAppend(), false)); + + return false; + } + // Populate the row id from the session. $data['id'] = $recordId; diff --git a/administrator/components/com_menus/controllers/menu.php b/administrator/components/com_menus/controllers/menu.php index a4146c437a722..f0849f8dd7e91 100644 --- a/administrator/components/com_menus/controllers/menu.php +++ b/administrator/components/com_menus/controllers/menu.php @@ -48,6 +48,16 @@ public function save($key = null, $urlVar = null) $task = $this->getTask(); $recordId = $this->input->getInt('id'); + if (!$this->checkEditId($context, $recordId)) + { + // Somehow the person just went to the form and saved it - we don't allow that. + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $recordId)); + $this->setMessage($this->getError(), 'error'); + $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_list.$this->getRedirectToListAppend(), false)); + + return false; + } + // Make sure we are not trying to modify an administrator menu. if (isset($data['client_id']) && $data['client_id'] == 1){ JError::raiseNotice(0, JText::_('COM_MENUS_MENU_TYPE_NOT_ALLOWED')); diff --git a/administrator/language/en-GB/en-GB.lib_joomla.ini b/administrator/language/en-GB/en-GB.lib_joomla.ini index 6cf7b1156e42e..1db617d580de7 100644 --- a/administrator/language/en-GB/en-GB.lib_joomla.ini +++ b/administrator/language/en-GB/en-GB.lib_joomla.ini @@ -384,8 +384,6 @@ JLIB_HTML_EDIT_MENU_ITEM_ID="Item id: %s" JLIB_HTML_EDIT_MODULE="Edit module" JLIB_HTML_EDIT_MODULE_IN_POSITION="Position: %s" JLIB_HTML_EDITOR_CANNOT_LOAD="Cannot load the editor" -JLIB_HTML_EDIT_MODULE="Edit Module" -JLIB_HTML_EDIT_MODULE_IN_POSITION="Position: %s" JLIB_HTML_END="End" JLIB_HTML_ERROR_FUNCTION_NOT_SUPPORTED="Function not supported." JLIB_HTML_ERROR_NOTFOUNDINFILE="%s: :%s not found in file." @@ -461,8 +459,8 @@ JLIB_INSTALLER_ABORT_MOD_UNKNOWN_CLIENT="Module %1$s: Unknown client type [%2$s] JLIB_INSTALLER_ABORT_NOINSTALLPATH="Install path does not exist" JLIB_INSTALLER_ABORT_NOUPDATEPATH="Update path does not exist" JLIB_INSTALLER_ABORT_PACK_INSTALL_COPY_SETUP="Package Install: Could not copy setup file." -JLIB_INSTALLER_ABORT_PACKAGE_INSTALL_MANIFEST="Installation failed: Could not copy PHP manifest file." JLIB_INSTALLER_ABORT_PACK_INSTALL_CREATE_DIRECTORY="Package Install: Failed to create directory:%s " +JLIB_INSTALLER_ABORT_PACKAGE_INSTALL_MANIFEST="Installation failed: Could not copy PHP manifest file." JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION="Package %1$s: There was an error installing an extension: %2$s" JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_FILES="Package %s: There were no files to install!" JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_PACK="Package %s: No package file specified" diff --git a/layouts/joomla/edit/frontediting_modules.php b/layouts/joomla/edit/frontediting_modules.php new file mode 100644 index 0000000000000..4643bb8097b48 --- /dev/null +++ b/layouts/joomla/edit/frontediting_modules.php @@ -0,0 +1,60 @@ +isAdmin() || !JFactory::getUser()->authorise('core.manage', 'com_modules'); + + +if (!$moduleHtml) +{ + return; +} + +if ($cannotEditFrontend + || preg_match('/<(?:div|span|nav|ul) [^>]*class="[^"]* jmoddiv"/', $moduleHtml)) +{ + // Module isn't enclosing in a div with class or handles already module edit button: + return; +} + +// Add css class jmoddiv and data attributes for module-editing URL and for the tooltip: +$editUrl = JURI::base() . 'administrator/' . 'index.php?option=com_modules&view=module&layout=edit&id=' . (int) $mod->id; + +// Add class, editing URL and tooltip, and if module of type menu, also the tooltip for editing the menu item: +$moduleHtml = preg_replace('/^(<(?:div|span|nav|ul) [^>]*class="[^"]*)"/', + '\\1 jmoddiv" data-jmodediturl="' . $editUrl. '"' + . ' data-jmodtip="' + . JHtml::tooltipText(JText::_('JLIB_HTML_EDIT_MODULE'), htmlspecialchars($mod->title) . '
' . sprintf(JText::_('JLIB_HTML_EDIT_MODULE_IN_POSITION'), htmlspecialchars($position)), 0) + . '"' + . ($mod->module == 'mod_menu' ? '" data-jmenuedittip="' . JHtml::tooltipText('JLIB_HTML_EDIT_MENU_ITEM', 'JLIB_HTML_EDIT_MENU_ITEM_ID') . '"' : ''), + $moduleHtml); + +if ($jsNotOut) +{ + // Load once booststrap tooltip and add stylesheet and javascript to head: + $jsNotOut = false; + JHtml::_('bootstrap.tooltip'); + JHtml::_('bootstrap.popover'); + + JFactory::getDocument()->addStyleSheet('media/system/css/frontediting.css') + ->addScript('media/system/js/frontediting.js'); +} + +?> diff --git a/libraries/joomla/document/html/renderer/modules.php b/libraries/joomla/document/html/renderer/modules.php index 3875647a16240..38bca50c186af 100644 --- a/libraries/joomla/document/html/renderer/modules.php +++ b/libraries/joomla/document/html/renderer/modules.php @@ -31,55 +31,14 @@ class JDocumentRendererModules extends JDocumentRenderer */ public function render($position, $params = array(), $content = null) { - static $jsNotOut =true; - - $app = JFactory::getApplication(); - $renderer = $this->_doc->loadRenderer('module'); $buffer = ''; - $cannotEditFrontend = $app->isAdmin() || !JFactory::getUser()->authorise('core.manage', 'com_modules'); - foreach (JModuleHelper::getModules($position) as $mod) { $moduleHtml = trim($renderer->render($mod, $params, $content)); - - if (!$moduleHtml) - { - continue; - } - - if ($cannotEditFrontend - || preg_match('/<(?:div|span|nav|ul) [^>]*class="[^"]* jmoddiv"/', $moduleHtml)) - { - // Module isn't enclosing in a div with class or handles already module edit button: - $buffer .= $moduleHtml; - continue; - } - - // Add css class jmoddiv and data attributes for module-editing URL and for the tooltip: - $editUrl = JURI::base() . 'administrator/' . 'index.php?option=com_modules&view=module&layout=edit&id=' . (int) $mod->id; - - // Add class, editing URL and tooltip, and if module of type menu, also the tooltip for editing the menu item: - $buffer .= preg_replace('/^(<(?:div|span|nav|ul) [^>]*class="[^"]*)"/', - '\\1 jmoddiv" data-jmodediturl="' . $editUrl. '"' - . ' data-jmodtip="' - . JHtml::tooltipText(JText::_('JLIB_HTML_EDIT_MODULE'), htmlspecialchars($mod->title) . '
' . sprintf(JText::_('JLIB_HTML_EDIT_MODULE_IN_POSITION'), htmlspecialchars($position)), 0) - . '"' - . ($mod->module == 'mod_menu' ? '" data-jmenuedittip="' . JHtml::tooltipText('JLIB_HTML_EDIT_MENU_ITEM', 'JLIB_HTML_EDIT_MENU_ITEM_ID') . '"' : ''), - $moduleHtml); - - if ($jsNotOut) - { - // Load once booststrap tooltip and add stylesheet and javascript to head: - $jsNotOut = false; - JHtml::_('bootstrap.tooltip'); - JHtml::_('bootstrap.popover'); - - JFactory::getDocument()->addStyleSheet('media/system/css/frontediting.css') - ->addScript('media/system/js/frontediting.js'); - } - + JLayoutHelper::render('joomla.edit.frontediting_modules', array('moduleHtml' => &$moduleHtml, 'module' => $mod, 'position' => $position)); + $buffer .= $moduleHtml; } return $buffer; } diff --git a/media/system/css/frontediting.css b/media/system/css/frontediting.css index e2bd561766a00..9a771bf3b4836 100644 --- a/media/system/css/frontediting.css +++ b/media/system/css/frontediting.css @@ -18,11 +18,3 @@ top: 0; right: 0; } - -/* Menu edit in front-end */ - -.btn.jfedit-menu -{ - z-index: 1002; - display: block; -} diff --git a/media/system/js/frontediting.js b/media/system/js/frontediting.js index 98d5e73f25faa..3aff94d60659b 100644 --- a/media/system/js/frontediting.js +++ b/media/system/js/frontediting.js @@ -91,54 +91,5 @@ } }); - // Menu items edit icons: - - var activePopover = null; - - $('.jmoddiv .nav li,.jmoddiv.nav li,.jmoddiv .nav .nav-child li,.jmoddiv.nav .nav-child li').on({ - mouseenter: function() { - - // Get menu ItemId from the item-nnn class of the li element of the menu: - var itemids = /\bitem-(\d+)\b/.exec($(this).attr('class')); - if (typeof itemids[1] == 'string') { - // Find module editing URL from enclosing module: - var enclosingModuleDiv = $(this).closest('.jmoddiv'); - var moduleEditUrl = enclosingModuleDiv.data('jmodediturl'); - // Transform module editing URL into Menu Item editing url: - var menuitemEditUrl = moduleEditUrl.replace(/\/index.php\?option=com_modules&view=module([^\d]+)\d+$/, '/index.php?option=com_menus&view=item$1' + itemids[1]); - - } - - // Get tooltip for menu items from enclosing module - var menuEditTip = enclosingModuleDiv.data('jmenuedittip').replace('%s', itemids[1]); - - var content = $('
'); - content.children('a.jfedit-menu').prop('href', menuitemEditUrl).prop('title', menuEditTip); - - if (activePopover) { - $(activePopover).popover('hide'); - } - $(this).popover({html:true, content:content.html(), container:'body', trigger:'manual', animation:false}).popover('show'); - activePopover = this; - - $('body>div.popover') - .on({ - mouseenter: function() { - if (activePopover) { - $(activePopover).clearQueue(); - } - }, - mouseleave: function() { - if (activePopover) { - $(activePopover).popover('hide'); - } - } - }) - .find('a.jfedit-menu').tooltip({"container": false}); - }, - mouseleave: function() { - $(this).delay(1500).queue(function(next) { $(this).popover('hide'); next() }); - } - }); }); })(jQuery); From 24761ff8cc17a0851f61ca7e069cee71c8e531f6 Mon Sep 17 00:00:00 2001 From: Beat Date: Thu, 3 Oct 2013 17:11:27 +0200 Subject: [PATCH 05/13] [JUX2] Front-end modules editing: Commented out menus-editing, alowing for plugins to do it --- .../components/com_menus/controller.php | 26 ++------- .../components/com_menus/controllers/item.php | 10 ---- .../components/com_menus/controllers/menu.php | 10 ---- .../joomla/document/html/renderer/modules.php | 2 + media/system/css/frontediting.css | 8 +++ media/system/js/frontediting.js | 54 +++++++++++++++++++ 6 files changed, 67 insertions(+), 43 deletions(-) diff --git a/administrator/components/com_menus/controller.php b/administrator/components/com_menus/controller.php index 04e53ceda7669..28881f565b6e8 100644 --- a/administrator/components/com_menus/controller.php +++ b/administrator/components/com_menus/controller.php @@ -21,10 +21,10 @@ class MenusController extends JControllerLegacy /** * Method to display a view. * - * @param boolean If true, the view output will be cached - * @param array An array of safe url parameters and their variable types, for valid values see {@link JFilterInput::clean()}. + * @param boolean $cachable If true, the view output will be cached + * @param array|boolean $urlparams An array of safe url parameters and their variable types, for valid values see {@link JFilterInput::clean()}. * - * @return JController This object to support chaining. + * @return JController This object to support chaining. * @since 1.5 */ public function display($cachable = false, $urlparams = false) @@ -35,26 +35,6 @@ public function display($cachable = false, $urlparams = false) $layout = $this->input->get('layout', 'default'); $id = $this->input->getInt('id'); - // Check for edit form. - if ($view == 'menu' && $layout == 'edit' && !$this->checkEditId('com_menus.edit.menu', $id)) { - - // Somehow the person just went to the form - we don't allow that. - $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id)); - $this->setMessage($this->getError(), 'error'); - $this->setRedirect(JRoute::_('index.php?option=com_menus&view=menus', false)); - - return false; - } - elseif ($view == 'item' && $layout == 'edit' && !$this->checkEditId('com_menus.edit.item', $id)) { - - // Somehow the person just went to the form - we don't allow that. - $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id)); - $this->setMessage($this->getError(), 'error'); - $this->setRedirect(JRoute::_('index.php?option=com_menus&view=items', false)); - - return false; - } - parent::display(); return $this; diff --git a/administrator/components/com_menus/controllers/item.php b/administrator/components/com_menus/controllers/item.php index 391bc6344d896..e7bf9a752abd1 100644 --- a/administrator/components/com_menus/controllers/item.php +++ b/administrator/components/com_menus/controllers/item.php @@ -138,16 +138,6 @@ public function save($key = null, $urlVar = null) $context = 'com_menus.edit.item'; $recordId = $this->input->getInt('id'); - if (!$this->checkEditId($context, $recordId)) - { - // Somehow the person just went to the form and saved it - we don't allow that. - $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $recordId)); - $this->setMessage($this->getError(), 'error'); - $this->setRedirect(JRoute::_('index.php?option=com_menus&view=items' . $this->getRedirectToListAppend(), false)); - - return false; - } - // Populate the row id from the session. $data['id'] = $recordId; diff --git a/administrator/components/com_menus/controllers/menu.php b/administrator/components/com_menus/controllers/menu.php index f0849f8dd7e91..a4146c437a722 100644 --- a/administrator/components/com_menus/controllers/menu.php +++ b/administrator/components/com_menus/controllers/menu.php @@ -48,16 +48,6 @@ public function save($key = null, $urlVar = null) $task = $this->getTask(); $recordId = $this->input->getInt('id'); - if (!$this->checkEditId($context, $recordId)) - { - // Somehow the person just went to the form and saved it - we don't allow that. - $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $recordId)); - $this->setMessage($this->getError(), 'error'); - $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_list.$this->getRedirectToListAppend(), false)); - - return false; - } - // Make sure we are not trying to modify an administrator menu. if (isset($data['client_id']) && $data['client_id'] == 1){ JError::raiseNotice(0, JText::_('COM_MENUS_MENU_TYPE_NOT_ALLOWED')); diff --git a/libraries/joomla/document/html/renderer/modules.php b/libraries/joomla/document/html/renderer/modules.php index 38bca50c186af..4d7ff246063c9 100644 --- a/libraries/joomla/document/html/renderer/modules.php +++ b/libraries/joomla/document/html/renderer/modules.php @@ -37,7 +37,9 @@ public function render($position, $params = array(), $content = null) foreach (JModuleHelper::getModules($position) as $mod) { $moduleHtml = trim($renderer->render($mod, $params, $content)); + JLayoutHelper::render('joomla.edit.frontediting_modules', array('moduleHtml' => &$moduleHtml, 'module' => $mod, 'position' => $position)); + $buffer .= $moduleHtml; } return $buffer; diff --git a/media/system/css/frontediting.css b/media/system/css/frontediting.css index 9a771bf3b4836..e2bd561766a00 100644 --- a/media/system/css/frontediting.css +++ b/media/system/css/frontediting.css @@ -18,3 +18,11 @@ top: 0; right: 0; } + +/* Menu edit in front-end */ + +.btn.jfedit-menu +{ + z-index: 1002; + display: block; +} diff --git a/media/system/js/frontediting.js b/media/system/js/frontediting.js index 3aff94d60659b..e48883efe1e50 100644 --- a/media/system/js/frontediting.js +++ b/media/system/js/frontediting.js @@ -91,5 +91,59 @@ } }); +/* Uncomment for front-end menu edits: + + // Menu items edit icons: + + var activePopover = null; + + $('.jmoddiv .nav li,.jmoddiv.nav li,.jmoddiv .nav .nav-child li,.jmoddiv.nav .nav-child li').on({ + mouseenter: function() { + + // Get menu ItemId from the item-nnn class of the li element of the menu: + var itemids = /\bitem-(\d+)\b/.exec($(this).attr('class')); + if (typeof itemids[1] == 'string') { + // Find module editing URL from enclosing module: + var enclosingModuleDiv = $(this).closest('.jmoddiv'); + var moduleEditUrl = enclosingModuleDiv.data('jmodediturl'); + // Transform module editing URL into Menu Item editing url: + var menuitemEditUrl = moduleEditUrl.replace(/\/index.php\?option=com_modules&view=module([^\d]+)\d+$/, '/index.php?option=com_menus&view=item$1' + itemids[1]); + + } + + // Get tooltip for menu items from enclosing module + var menuEditTip = enclosingModuleDiv.data('jmenuedittip').replace('%s', itemids[1]); + + var content = $('
'); + content.children('a.jfedit-menu').prop('href', menuitemEditUrl).prop('title', menuEditTip); + + if (activePopover) { + $(activePopover).popover('hide'); + } + $(this).popover({html:true, content:content.html(), container:'body', trigger:'manual', animation:false}).popover('show'); + activePopover = this; + + $('body>div.popover') + .on({ + mouseenter: function() { + if (activePopover) { + $(activePopover).clearQueue(); + } + }, + mouseleave: function() { + if (activePopover) { + $(activePopover).popover('hide'); + } + } + }) + .find('a.jfedit-menu').tooltip({"container": false}); + }, + mouseleave: function() { + $(this).delay(1500).queue(function(next) { $(this).popover('hide'); next() }); + } + }); + +*/ + }); })(jQuery); From 666b573b4c830fec3854736c3b6ca5c3a0b9bbbd Mon Sep 17 00:00:00 2001 From: Beat Date: Thu, 3 Oct 2013 18:19:19 +0200 Subject: [PATCH 06/13] [JUX2] Front-end modules editing: Fixed RTL positions to be right, fixed invisible tooltips at borders of window, fixed accessibility --- media/system/css/frontediting.css | 5 +++ media/system/js/frontediting.js | 71 ++++++++++++++++++++++++++++--- 2 files changed, 69 insertions(+), 7 deletions(-) diff --git a/media/system/css/frontediting.css b/media/system/css/frontediting.css index e2bd561766a00..938361ffe3597 100644 --- a/media/system/css/frontediting.css +++ b/media/system/css/frontediting.css @@ -18,6 +18,11 @@ top: 0; right: 0; } +html[dir=rtl] .btn.jmodedit +{ + right: auto; + left: 0; +} /* Menu edit in front-end */ diff --git a/media/system/js/frontediting.js b/media/system/js/frontediting.js index e48883efe1e50..e42db4062f9bb 100644 --- a/media/system/js/frontediting.js +++ b/media/system/js/frontediting.js @@ -45,6 +45,63 @@ $(document).ready(function () { + // Tooltip maximal dimensions for intelligent placement: + var actualWidth = 200; + var actualHeight = 100; + // Tooltip smart tooltip placement function: + var tooltipPlacer = function(tip, element) { + var $element, above, below, boundBottom, boundLeft, boundRight, boundTop, elementAbove, elementBelow, elementLeft, elementRight, isWithinBounds, left, pos, right; + isWithinBounds = function(elementPosition) { + return boundTop < elementPosition.top && boundLeft < elementPosition.left && boundRight > (elementPosition.left + actualWidth) && boundBottom > (elementPosition.top + actualHeight); + }; + $element = $(element); + pos = $.extend({}, $element.offset(), { + width: element.offsetWidth, + height: element.offsetHeight + }); + boundTop = $(document).scrollTop(); + boundLeft = $(document).scrollLeft(); + boundRight = boundLeft + $(window).width(); + boundBottom = boundTop + $(window).height(); + elementAbove = { + top: pos.top - actualHeight, + left: pos.left + pos.width / 2 - actualWidth / 2 + }; + elementBelow = { + top: pos.top + pos.height, + left: pos.left + pos.width / 2 - actualWidth / 2 + }; + elementLeft = { + top: pos.top + pos.height / 2 - actualHeight / 2, + left: pos.left - actualWidth + }; + elementRight = { + top: pos.top + pos.height / 2 - actualHeight / 2, + left: pos.left + pos.width + }; + above = isWithinBounds(elementAbove); + below = isWithinBounds(elementBelow); + left = isWithinBounds(elementLeft); + right = isWithinBounds(elementRight); + if (above) { + return "top"; + } else { + if (below) { + return "bottom"; + } else { + if (left) { + return "left"; + } else { + if (right) { + return "right"; + } else { + return "right"; + } + } + } + } + }; + // Modules edit icons: $('.jmoddiv').on({ @@ -59,9 +116,9 @@ // Add editing button with tooltip: $(this).addClass('jmodinside') - .prepend('') + .prepend('') .children(":first").attr('href', moduleEditUrl).attr('title', moduleTip) - .tooltip({"container": false}) + .tooltip({"container": false, placement: tooltipPlacer}) .jEditMakeAbsolute(true); // This class was needed for positioning the icon before making it absolute at bottom of body: We can now remove it: $(this).removeClass('jmodinside'); @@ -91,7 +148,7 @@ } }); -/* Uncomment for front-end menu edits: +/* Uncomment for front-end menu edits: * // Menu items edit icons: @@ -114,13 +171,13 @@ // Get tooltip for menu items from enclosing module var menuEditTip = enclosingModuleDiv.data('jmenuedittip').replace('%s', itemids[1]); - var content = $('
'); + var content = $('
'); content.children('a.jfedit-menu').prop('href', menuitemEditUrl).prop('title', menuEditTip); if (activePopover) { $(activePopover).popover('hide'); } - $(this).popover({html:true, content:content.html(), container:'body', trigger:'manual', animation:false}).popover('show'); + $(this).popover({html:true, content:content.html(), container:'body', trigger:'manual', animation:false, placement: $('html').attr('dir')=='rtl' ? 'left' : 'right'}).popover('show'); activePopover = this; $('body>div.popover') @@ -136,14 +193,14 @@ } } }) - .find('a.jfedit-menu').tooltip({"container": false}); + .find('a.jfedit-menu').tooltip({"container": false, placement: 'bottom'}); }, mouseleave: function() { $(this).delay(1500).queue(function(next) { $(this).popover('hide'); next() }); } }); -*/ +/* End of commented Edit menu */ }); })(jQuery); From eb6ad80938704f62fdbd551a2e3d6e326687ed2c Mon Sep 17 00:00:00 2001 From: Beat Date: Fri, 4 Oct 2013 22:43:13 +0200 Subject: [PATCH 07/13] [JUX2] Front-end modules editing: Moved ACL one level up and improved it, added setting for modules edit (on by default) and menu edits (off by default), prepared for modules ACL --- .../com_config/models/forms/application.xml | 13 +++++++ .../language/en-GB/en-GB.com_config.ini | 5 +++ layouts/joomla/edit/frontediting_modules.php | 38 ++++++++----------- .../joomla/document/html/renderer/modules.php | 15 +++++++- media/system/js/frontediting.js | 5 --- 5 files changed, 46 insertions(+), 30 deletions(-) diff --git a/administrator/components/com_config/models/forms/application.xml b/administrator/components/com_config/models/forms/application.xml index 5c8fcf4b8d0a8..a8b6e87254118 100644 --- a/administrator/components/com_config/models/forms/application.xml +++ b/administrator/components/com_config/models/forms/application.xml @@ -614,6 +614,19 @@ label="COM_CONFIG_FIELD_OFFLINE_IMAGE_LABEL" description="COM_CONFIG_FIELD_OFFLINE_IMAGE_DESC" /> + + + + + + + isAdmin() || !JFactory::getUser()->authorise('core.manage', 'com_modules'); - - -if (!$moduleHtml) -{ - return; -} - -if ($cannotEditFrontend - || preg_match('/<(?:div|span|nav|ul) [^>]*class="[^"]* jmoddiv"/', $moduleHtml)) +if (preg_match('/<(?:div|span|nav|ul|ol|h\d) [^>]*class="[^"]* jmoddiv"/', $moduleHtml)) { - // Module isn't enclosing in a div with class or handles already module edit button: + // Module has already module edit button: return; } // Add css class jmoddiv and data attributes for module-editing URL and for the tooltip: -$editUrl = JURI::base() . 'administrator/' . 'index.php?option=com_modules&view=module&layout=edit&id=' . (int) $mod->id; +$editUrl = JURI::base() . 'administrator/index.php?option=com_modules&view=module&layout=edit&id=' . (int) $mod->id; // Add class, editing URL and tooltip, and if module of type menu, also the tooltip for editing the menu item: -$moduleHtml = preg_replace('/^(<(?:div|span|nav|ul) [^>]*class="[^"]*)"/', +$count = 0; +$moduleHtml = preg_replace('/^(<(?:div|span|nav|ul|ol|h\d) [^>]*class="[^"]*)"/', '\\1 jmoddiv" data-jmodediturl="' . $editUrl. '"' . ' data-jmodtip="' . JHtml::tooltipText(JText::_('JLIB_HTML_EDIT_MODULE'), htmlspecialchars($mod->title) . '
' . sprintf(JText::_('JLIB_HTML_EDIT_MODULE_IN_POSITION'), htmlspecialchars($position)), 0) . '"' - . ($mod->module == 'mod_menu' ? '" data-jmenuedittip="' . JHtml::tooltipText('JLIB_HTML_EDIT_MENU_ITEM', 'JLIB_HTML_EDIT_MENU_ITEM_ID') . '"' : ''), - $moduleHtml); + . ($menusEditing && $mod->module == 'mod_menu' ? '" data-jmenuedittip="' . JHtml::tooltipText('JLIB_HTML_EDIT_MENU_ITEM', 'JLIB_HTML_EDIT_MENU_ITEM_ID') . '"' : ''), + $moduleHtml, 1, $count); + +static $jsOut = false; -if ($jsNotOut) +if ($count && !$jsOut) { // Load once booststrap tooltip and add stylesheet and javascript to head: - $jsNotOut = false; + $jsOut = true; JHtml::_('bootstrap.tooltip'); JHtml::_('bootstrap.popover'); diff --git a/libraries/joomla/document/html/renderer/modules.php b/libraries/joomla/document/html/renderer/modules.php index 4d7ff246063c9..6db5be3a552d6 100644 --- a/libraries/joomla/document/html/renderer/modules.php +++ b/libraries/joomla/document/html/renderer/modules.php @@ -34,12 +34,23 @@ public function render($position, $params = array(), $content = null) $renderer = $this->_doc->loadRenderer('module'); $buffer = ''; + $app = JFactory::getApplication(); + $frontediting = $app->get('frontediting', 1); + $user = JFactory::getUser(); + + $canEdit = $user->id && $frontediting && !($app->isAdmin() && $frontediting < 2) && $user->authorise('core.edit', 'com_modules'); + $menusEditing = ($frontediting == 2) && $user->authorise('core.edit', 'com_menus'); + foreach (JModuleHelper::getModules($position) as $mod) { $moduleHtml = trim($renderer->render($mod, $params, $content)); - JLayoutHelper::render('joomla.edit.frontediting_modules', array('moduleHtml' => &$moduleHtml, 'module' => $mod, 'position' => $position)); - + if ($canEdit && $moduleHtml != '') + // Once FR http://joomlacode.org/gf/project/joomla/tracker/?action=TrackerItemEdit&tracker_item_id=28638&start=200 && PR https://github.com/joomla/joomla-cms/pull/1930/files are merged: + // + && $user->authorise('core.edit', 'com_modules.module.' . $mod->id) + { + JLayoutHelper::render('joomla.edit.frontediting_modules', array('moduleHtml' => &$moduleHtml, 'module' => $mod, 'position' => $position, 'menusediting' => $menusEditing)); + } $buffer .= $moduleHtml; } return $buffer; diff --git a/media/system/js/frontediting.js b/media/system/js/frontediting.js index e42db4062f9bb..a2c67e5720964 100644 --- a/media/system/js/frontediting.js +++ b/media/system/js/frontediting.js @@ -148,8 +148,6 @@ } }); -/* Uncomment for front-end menu edits: * - // Menu items edit icons: var activePopover = null; @@ -199,8 +197,5 @@ $(this).delay(1500).queue(function(next) { $(this).popover('hide'); next() }); } }); - -/* End of commented Edit menu */ - }); })(jQuery); From 089783d7d31a902ed71f866fefd4eb890934fffe Mon Sep 17 00:00:00 2001 From: Beat Date: Fri, 4 Oct 2013 23:10:06 +0200 Subject: [PATCH 08/13] [JUX2] Front-end modules editing: Fixed PHPCS warnings and added the modules ACL of FR #28638 --- layouts/joomla/edit/frontediting_modules.php | 34 +++++++++++++------ .../joomla/document/html/renderer/modules.php | 9 ++--- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/layouts/joomla/edit/frontediting_modules.php b/layouts/joomla/edit/frontediting_modules.php index d45b20a2811a6..bd8e6731acd02 100644 --- a/layouts/joomla/edit/frontediting_modules.php +++ b/layouts/joomla/edit/frontediting_modules.php @@ -12,9 +12,9 @@ // JLayout for standard handling of the edit modules: $moduleHtml =& $displayData['moduleHtml']; -$mod = $displayData['module']; -$position = $displayData['position']; -$menusEditing = $displayData['menusediting']; +$mod = $displayData['module']; +$position = $displayData['position']; +$menusEditing = $displayData['menusediting']; if (preg_match('/<(?:div|span|nav|ul|ol|h\d) [^>]*class="[^"]* jmoddiv"/', $moduleHtml)) @@ -28,13 +28,27 @@ // Add class, editing URL and tooltip, and if module of type menu, also the tooltip for editing the menu item: $count = 0; -$moduleHtml = preg_replace('/^(<(?:div|span|nav|ul|ol|h\d) [^>]*class="[^"]*)"/', - '\\1 jmoddiv" data-jmodediturl="' . $editUrl. '"' - . ' data-jmodtip="' - . JHtml::tooltipText(JText::_('JLIB_HTML_EDIT_MODULE'), htmlspecialchars($mod->title) . '
' . sprintf(JText::_('JLIB_HTML_EDIT_MODULE_IN_POSITION'), htmlspecialchars($position)), 0) +$moduleHtml = preg_replace( + // Replace first tag of module with a class + '/^(\s*<(?:div|span|nav|ul|ol|h\d) [^>]*class="[^"]*)"/', + // By itself, adding class jmoddiv and data attributes for the url and tooltip: + '\\1 jmoddiv" data-jmodediturl="' . $editUrl . '" data-jmodtip="' + . JHtml::tooltipText( + JText::_('JLIB_HTML_EDIT_MODULE'), + htmlspecialchars($mod->title) . '
' . sprintf(JText::_('JLIB_HTML_EDIT_MODULE_IN_POSITION'), htmlspecialchars($position)), + 0 + ) . '"' - . ($menusEditing && $mod->module == 'mod_menu' ? '" data-jmenuedittip="' . JHtml::tooltipText('JLIB_HTML_EDIT_MENU_ITEM', 'JLIB_HTML_EDIT_MENU_ITEM_ID') . '"' : ''), - $moduleHtml, 1, $count); + // And if menu editing is enabled and allowed and it's a menu module, add data attributes for menu editing: + . ($menusEditing && $mod->module == 'mod_menu' ? + '" data-jmenuedittip="' . JHtml::tooltipText('JLIB_HTML_EDIT_MENU_ITEM', 'JLIB_HTML_EDIT_MENU_ITEM_ID') . '"' + : + '' + ), + $moduleHtml, + 1, + $count +); static $jsOut = false; @@ -48,5 +62,3 @@ JFactory::getDocument()->addStyleSheet('media/system/css/frontediting.css') ->addScript('media/system/js/frontediting.js'); } - -?> diff --git a/libraries/joomla/document/html/renderer/modules.php b/libraries/joomla/document/html/renderer/modules.php index 6db5be3a552d6..c787d15c594bd 100644 --- a/libraries/joomla/document/html/renderer/modules.php +++ b/libraries/joomla/document/html/renderer/modules.php @@ -45,14 +45,15 @@ public function render($position, $params = array(), $content = null) { $moduleHtml = trim($renderer->render($mod, $params, $content)); - if ($canEdit && $moduleHtml != '') - // Once FR http://joomlacode.org/gf/project/joomla/tracker/?action=TrackerItemEdit&tracker_item_id=28638&start=200 && PR https://github.com/joomla/joomla-cms/pull/1930/files are merged: - // + && $user->authorise('core.edit', 'com_modules.module.' . $mod->id) + if ($canEdit && $moduleHtml != '' && $user->authorise('core.edit', 'com_modules.module.' . $mod->id)) { - JLayoutHelper::render('joomla.edit.frontediting_modules', array('moduleHtml' => &$moduleHtml, 'module' => $mod, 'position' => $position, 'menusediting' => $menusEditing)); + $displayData = array('moduleHtml' => &$moduleHtml, 'module' => $mod, 'position' => $position, 'menusediting' => $menusEditing); + JLayoutHelper::render('joomla.edit.frontediting_modules', $displayData); } + $buffer .= $moduleHtml; } + return $buffer; } } From f19b7a7f2a26a4a1b569eb5031b902e7bccf82d4 Mon Sep 17 00:00:00 2001 From: Beat Date: Fri, 4 Oct 2013 23:56:50 +0200 Subject: [PATCH 09/13] [JUX2] Front-end modules editing: Fixed Beez3 issues and removed inneffective code --- layouts/joomla/edit/frontediting_modules.php | 6 ++---- libraries/joomla/document/html/renderer/modules.php | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/layouts/joomla/edit/frontediting_modules.php b/layouts/joomla/edit/frontediting_modules.php index bd8e6731acd02..f4871fd75cc34 100644 --- a/layouts/joomla/edit/frontediting_modules.php +++ b/layouts/joomla/edit/frontediting_modules.php @@ -50,12 +50,10 @@ $count ); -static $jsOut = false; - -if ($count && !$jsOut) +if ($count) { // Load once booststrap tooltip and add stylesheet and javascript to head: - $jsOut = true; + JHtml::_('bootstrap.loadCss'); JHtml::_('bootstrap.tooltip'); JHtml::_('bootstrap.popover'); diff --git a/libraries/joomla/document/html/renderer/modules.php b/libraries/joomla/document/html/renderer/modules.php index c787d15c594bd..ba45a050381e4 100644 --- a/libraries/joomla/document/html/renderer/modules.php +++ b/libraries/joomla/document/html/renderer/modules.php @@ -43,9 +43,9 @@ public function render($position, $params = array(), $content = null) foreach (JModuleHelper::getModules($position) as $mod) { - $moduleHtml = trim($renderer->render($mod, $params, $content)); + $moduleHtml = $renderer->render($mod, $params, $content); - if ($canEdit && $moduleHtml != '' && $user->authorise('core.edit', 'com_modules.module.' . $mod->id)) + if ($canEdit && trim($moduleHtml) != '' && $user->authorise('core.edit', 'com_modules.module.' . $mod->id)) { $displayData = array('moduleHtml' => &$moduleHtml, 'module' => $mod, 'position' => $position, 'menusediting' => $menusEditing); JLayoutHelper::render('joomla.edit.frontediting_modules', $displayData); From b456d877ba128e341d80f8af6484a119598be8d3 Mon Sep 17 00:00:00 2001 From: Beat Date: Tue, 8 Oct 2013 01:02:13 +0200 Subject: [PATCH 10/13] Fixed bootstrap loading of RTL files --- layouts/joomla/edit/frontediting_modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layouts/joomla/edit/frontediting_modules.php b/layouts/joomla/edit/frontediting_modules.php index f4871fd75cc34..5480619ee2c9e 100644 --- a/layouts/joomla/edit/frontediting_modules.php +++ b/layouts/joomla/edit/frontediting_modules.php @@ -53,7 +53,7 @@ if ($count) { // Load once booststrap tooltip and add stylesheet and javascript to head: - JHtml::_('bootstrap.loadCss'); + JHtml::_('bootstrap.loadCss', true, JFactory::getDocument()->getDirection()); JHtml::_('bootstrap.tooltip'); JHtml::_('bootstrap.popover'); From 0a61974fddf45edd88b9cee0d53673a651f1466b Mon Sep 17 00:00:00 2001 From: Beat Date: Tue, 8 Oct 2013 03:15:18 +0200 Subject: [PATCH 11/13] Fixes for Beez3 sensitivity on Bootstrap CSS loaded --- templates/beez3/css/general.css | 25 ++++++++++++++++++++++++- templates/beez3/css/layout.css | 22 +++++++++++----------- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/templates/beez3/css/general.css b/templates/beez3/css/general.css index 5a4343bc2352b..cdff7eac7430a 100644 --- a/templates/beez3/css/general.css +++ b/templates/beez3/css/general.css @@ -425,4 +425,27 @@ span.optional } .input-mini { width: 60px; -} \ No newline at end of file +} + +/* Bootstrap overrides anhiliation + * @since 3.2 + */ +body#shadow { + line-height: 1.5em; +} +body .nav-pills > .active > a, body .nav-pills > .active > a:hover, body .nav-pills > .active > a:focus { + background-color: transparent; +} +body .nav-pills > li > a { + border-radius: 0px; + line-height: 1.5em; +} +body a { + text-decoration: underline; +} +body input[type="text"].search-query { + line-height: 1.5em; + height: auto; + border-radius: 4px; + +} diff --git a/templates/beez3/css/layout.css b/templates/beez3/css/layout.css index 8024dc87bcb06..51fed06d13094 100644 --- a/templates/beez3/css/layout.css +++ b/templates/beez3/css/layout.css @@ -10,11 +10,11 @@ * source software licenses. See COPYRIGHT.php for copyright notices and * details. /* Typography =================================================== */ -body { +body#shadow { font-family: arial,sans-serif } -h1,h2,h3,h4,h5,h6 { +body h1,body h2,body h3,body h4,body h5,body h6 { margin: 0; font-family: inherit; font-weight: normal; @@ -22,38 +22,38 @@ h1,h2,h3,h4,h5,h6 { text-rendering: optimizelegibility; } -h1 { +body h1 { margin-bottom: 0.75em; font-size: 3.6em; line-height: 1.2; } -h2 { +body h2 { margin-bottom: 0.75em; font-size: 1.5em; line-height: 1.2; padding: 5px 0 } -h3 { +body h3 { margin-bottom: 1em; font-size: 1.4em; line-height: 1.3; padding-bottom: 5px } -h4 { +body h4 { margin-bottom: 1.5em; font-size: 1.2em; line-height: 1.25; } -h5 { +body h5 { font-size: 1.1em; margin-bottom: 1.5em; } -p,ol,ul,dl,address { +body p,body ol,body ul,body dl,body address { margin-bottom: 1.5em; font-size: 1.0em; line-height: 1.5em; @@ -63,12 +63,12 @@ small { font-size: 0.9em; } -ul,ol { +body ul,body ol { margin: 0 0 1.5em 12px; padding: 0 0 0 12px; } -li ul,li ol { +body li ul,body li ol { margin: 0; } @@ -226,7 +226,7 @@ label { max-width: 90% } -input,textarea,select,#advanced-search-toggle { +input,textarea,select,#advanced-search-toggle, input.search-query { border: 1px solid #CCCCCC; border-radius: 3px; display: inline-block; From 1c3bdfbd93d10a9d1501901a962ef3f657dc00fb Mon Sep 17 00:00:00 2001 From: Beat Date: Tue, 8 Oct 2013 03:24:39 +0200 Subject: [PATCH 12/13] Fixed Javascript TypeError --- media/system/js/frontediting.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media/system/js/frontediting.js b/media/system/js/frontediting.js index a2c67e5720964..00206b05db6b0 100644 --- a/media/system/js/frontediting.js +++ b/media/system/js/frontediting.js @@ -152,7 +152,7 @@ var activePopover = null; - $('.jmoddiv .nav li,.jmoddiv.nav li,.jmoddiv .nav .nav-child li,.jmoddiv.nav .nav-child li').on({ + $('.jmoddiv[data-jmenuedittip] .nav li,.jmoddiv[data-jmenuedittip].nav li,.jmoddiv[data-jmenuedittip] .nav .nav-child li,.jmoddiv[data-jmenuedittip].nav .nav-child li').on({ mouseenter: function() { // Get menu ItemId from the item-nnn class of the li element of the menu: From 63c2f3bb2ec1458308160e6350dd213d7dee7af2 Mon Sep 17 00:00:00 2001 From: Beat Date: Tue, 8 Oct 2013 03:30:03 +0200 Subject: [PATCH 13/13] Made Menu popover bottom to address right-screen border issue --- media/system/js/frontediting.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media/system/js/frontediting.js b/media/system/js/frontediting.js index 00206b05db6b0..c26699febc103 100644 --- a/media/system/js/frontediting.js +++ b/media/system/js/frontediting.js @@ -175,7 +175,7 @@ if (activePopover) { $(activePopover).popover('hide'); } - $(this).popover({html:true, content:content.html(), container:'body', trigger:'manual', animation:false, placement: $('html').attr('dir')=='rtl' ? 'left' : 'right'}).popover('show'); + $(this).popover({html:true, content:content.html(), container:'body', trigger:'manual', animation:false, placement: 'bottom'}).popover('show'); activePopover = this; $('body>div.popover')