From 6203f795144fad76f9607000b3ad0adf2291efef Mon Sep 17 00:00:00 2001 From: Guillaume Delhumeau <guillaume.delhumeau@xwiki.com> Date: Mon, 9 Nov 2015 18:06:04 +0100 Subject: [PATCH] XWIKI-12485: Improve the watchlist icons. --- .../main/resources/flamingo/menus_content.vm | 52 -- .../java/org/xwiki/test/ui/po/BasePage.java | 16 +- .../xwiki-platform-watchlist-ui/pom.xml | 15 + .../XWiki/WatchListNotificationsUIX.xml | 454 ++++++++++++++++++ .../main/webapp/resources/js/xwiki/xwiki.js | 12 + 5 files changed, 489 insertions(+), 60 deletions(-) create mode 100644 xwiki-platform-core/xwiki-platform-watchlist/xwiki-platform-watchlist-ui/src/main/resources/XWiki/WatchListNotificationsUIX.xml diff --git a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/menus_content.vm b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/menus_content.vm index 5b96a9b0b22..5509fb35d90 100644 --- a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/menus_content.vm +++ b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/menus_content.vm @@ -222,58 +222,6 @@ #macro(diplayOptionsMenu) #set ($staticExtensions = []) ## - ## WATCH /UNWATCH PAGE - ## TODO: the watchlist items will be moved afterwards, so we implement them here as static extensions for now, - ## but then we have to implement them as regular UIX in the watchlist module. - ## - #if (!$doc.isNew() && $hasWatch) - #set ($watchClasses = '') - #set ($unwatchClasses = 'hidden') - #if ($services.watchlist.isWatched("DOCUMENT")) - #set ($watchClasses = 'hidden') - #set ($unwatchClasses = '') - #end - #define ($watchPage) - #submenuitem("$xwiki.getURL($doc.documentReference, 'view', 'xpage=watch&do=adddocument')&xredirect=$escapetool.url($xwiki.getURL($doc.documentReference))" $services.localization.render('core.menu.watchlist.add.page') 'tmWatchDocument' $watchClasses 'eye-open') - #submenuitem("$xwiki.getURL($doc.documentReference, 'view', 'xpage=watch&do=removedocument')&xredirect=$escapetool.url($xwiki.getURL($doc.documentReference))" $services.localization.render('core.menu.watchlist.remove.page') 'tmUnwatchDocument' $unwatchClasses 'eye-close') - #end - #set ($discard = $staticExtensions.add( { 'content': $watchPage, 'order': 10000})) - #end - ## - ## WATCH /UNWATCH SPACE - ## TODO: see watch page - ## - #if ($hasWatch) - #set ($watchClasses = '') - #set ($unwatchClasses = 'hidden') - #if ($services.watchlist.isWatched("SPACE")) - #set ($watchClasses = 'hidden') - #set ($unwatchClasses = '') - #end - #define ($watchSpace) - #submenuitem("$doc.getURL('view', 'xpage=watch&do=addspace')&xredirect=$escapetool.url($doc.getURL())" $services.localization.render('core.menu.watchlist.add.space') 'tmWatchSpace', $watchClasses, 'eye-open') - #submenuitem("$doc.getURL('view', 'xpage=watch&do=removespace')&xredirect=$escapetool.url($doc.getURL())" $services.localization.render('core.menu.watchlist.remove.space') 'tmUnwatchSpace', $unwatchClasses, 'eye-close') - #end - #set ($discard = $staticExtensions.add( { 'content': $watchSpace, 'order': 20000})) - #end - ## - ## WATCH /UNWATCH WIKI - ## TODO: see watch page - ## - #if ($hasWatch) - #set ($watchClasses = '') - #set ($unwatchClasses = 'hidden') - #if ($services.watchlist.isWatched("WIKI")) - #set ($watchClasses = 'hidden') - #set ($unwatchClasses = '') - #end - #define ($watchWiki) - #submenuitem("$doc.getURL('view', 'xpage=watch&do=addwiki')&xredirect=$escapetool.url($doc.getURL())" $services.localization.render('core.menu.watchlist.add.wiki') 'tmWatchWiki', $watchClasses 'eye-open') - #submenuitem("$doc.getURL('view', 'xpage=watch&do=removewiki')&xredirect=$escapetool.url($doc.getURL())" $services.localization.render('core.menu.watchlist.remove.wiki') 'tmUnwatchWiki', $unwatchClasses 'eye-close') - #end - #set ($discard = $staticExtensions.add( { 'content': $watchWiki, 'order': 30000})) - #end - ## ## EXPORT / PRINT / SOURCE / SHARE ## #if ($canView) diff --git a/xwiki-platform-core/xwiki-platform-test/xwiki-platform-test-ui/src/main/java/org/xwiki/test/ui/po/BasePage.java b/xwiki-platform-core/xwiki-platform-test/xwiki-platform-test-ui/src/main/java/org/xwiki/test/ui/po/BasePage.java index ae65f9c6404..1b17e0f8c68 100644 --- a/xwiki-platform-core/xwiki-platform-test/xwiki-platform-test-ui/src/main/java/org/xwiki/test/ui/po/BasePage.java +++ b/xwiki-platform-core/xwiki-platform-test/xwiki-platform-test-ui/src/main/java/org/xwiki/test/ui/po/BasePage.java @@ -65,7 +65,7 @@ public class BasePage extends BaseElement @FindBy(id = "tmActionDelete") private WebElement deletePageLink; - @FindBy(id = "tmWatchDocument") + @FindBy(xpath = "//input[@id='tmWatchDocument']/../span[contains(@class, 'bootstrap-switch-label')]") private WebElement watchDocumentLink; @FindBy(id = "tmPage") @@ -86,10 +86,10 @@ public class BasePage extends BaseElement @FindBy(id = "document-title") private WebElement documentTitle; - @FindBy(id = "tmWatchSpace") + @FindBy(xpath = "//input[@id='tmWatchSpace']/../span[contains(@class, 'bootstrap-switch-label')]") private WebElement watchSpaceLink; - @FindBy(id = "tmWatchWiki") + @FindBy(xpath = "//input[@id='tmWatchWiki']/../span[contains(@class, 'bootstrap-switch-label')]") private WebElement watchWikiLink; @FindBy(css = "#tmMoreActions a[title='Children']") @@ -397,7 +397,7 @@ public boolean canDelete() */ public void watchDocument() { - toggleActionMenu(); + toggleNotificationsMenu(); this.watchDocumentLink.click(); toggleActionMenu(); } @@ -472,9 +472,9 @@ public String getDocumentTitle() */ public void watchSpace() { - toggleActionMenu(); + toggleNotificationsMenu(); this.watchSpaceLink.click(); - toggleActionMenu(); + toggleNotificationsMenu(); } /** @@ -482,9 +482,9 @@ public void watchSpace() */ public void watchWiki() { - toggleActionMenu(); + toggleNotificationsMenu(); this.watchWikiLink.click(); - toggleActionMenu(); + toggleNotificationsMenu(); } /** diff --git a/xwiki-platform-core/xwiki-platform-watchlist/xwiki-platform-watchlist-ui/pom.xml b/xwiki-platform-core/xwiki-platform-watchlist/xwiki-platform-watchlist-ui/pom.xml index e286ac49c29..5dd64e81aa3 100644 --- a/xwiki-platform-core/xwiki-platform-watchlist/xwiki-platform-watchlist-ui/pom.xml +++ b/xwiki-platform-core/xwiki-platform-watchlist/xwiki-platform-watchlist-ui/pom.xml @@ -67,5 +67,20 @@ <scope>runtime</scope> <type>xar</type> </dependency> + <!-- Needed to have the notifications menu. --> + <dependency> + <groupId>org.xwiki.platform</groupId> + <artifactId>xwiki-platform-notifications-ui</artifactId> + <version>${project.version}</version> + <scope>runtime</scope> + <type>xar</type> + </dependency> + <!-- Needed to have a nice toggle buttons on watchlist notifications area. --> + <dependency> + <groupId>org.webjars</groupId> + <artifactId>bootstrap-switch</artifactId> + <version>3.3.2</version> + <scope>runtime</scope> + </dependency> </dependencies> </project> diff --git a/xwiki-platform-core/xwiki-platform-watchlist/xwiki-platform-watchlist-ui/src/main/resources/XWiki/WatchListNotificationsUIX.xml b/xwiki-platform-core/xwiki-platform-watchlist/xwiki-platform-watchlist-ui/src/main/resources/XWiki/WatchListNotificationsUIX.xml new file mode 100644 index 00000000000..09b39615e86 --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-watchlist/xwiki-platform-watchlist-ui/src/main/resources/XWiki/WatchListNotificationsUIX.xml @@ -0,0 +1,454 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. +--> + +<xwikidoc version="1.2" reference="XWiki.WatchListNotificationsUIX" locale=""> + <web>XWiki</web> + <name>WatchListNotificationsUIX</name> + <language/> + <defaultLanguage/> + <translation>0</translation> + <creator>xwiki:XWiki.Admin</creator> + <creationDate>1446468725000</creationDate> + <parent>XWiki.WatchListMacro</parent> + <author>xwiki:XWiki.Admin</author> + <contentAuthor>xwiki:XWiki.Admin</contentAuthor> + <date>1447083576000</date> + <contentUpdateDate>1447068415000</contentUpdateDate> + <version>1.1</version> + <title/> + <comment/> + <minorEdit>false</minorEdit> + <syntaxId>xwiki/2.1</syntaxId> + <hidden>true</hidden> + <content/> + <object> + <name>XWiki.WatchListNotificationsUIX</name> + <number>0</number> + <className>XWiki.JavaScriptExtension</className> + <guid>5f5a2c84-f31f-4e63-a7cc-69cf394427c8</guid> + <class> + <name>XWiki.JavaScriptExtension</name> + <customClass/> + <customMapping/> + <defaultViewSheet/> + <defaultEditSheet/> + <defaultWeb/> + <nameField/> + <validationScript/> + <cache> + <cache>0</cache> + <disabled>0</disabled> + <displayType>select</displayType> + <multiSelect>0</multiSelect> + <name>cache</name> + <number>5</number> + <prettyName>Caching policy</prettyName> + <relationalStorage>0</relationalStorage> + <separator> </separator> + <separators>|, </separators> + <size>1</size> + <unmodifiable>0</unmodifiable> + <values>long|short|default|forbid</values> + <classType>com.xpn.xwiki.objects.classes.StaticListClass</classType> + </cache> + <code> + <disabled>0</disabled> + <name>code</name> + <number>2</number> + <prettyName>Code</prettyName> + <rows>20</rows> + <size>50</size> + <unmodifiable>0</unmodifiable> + <classType>com.xpn.xwiki.objects.classes.TextAreaClass</classType> + </code> + <name> + <disabled>0</disabled> + <name>name</name> + <number>1</number> + <prettyName>Name</prettyName> + <size>30</size> + <unmodifiable>0</unmodifiable> + <classType>com.xpn.xwiki.objects.classes.StringClass</classType> + </name> + <parse> + <disabled>0</disabled> + <displayFormType>select</displayFormType> + <displayType>yesno</displayType> + <name>parse</name> + <number>4</number> + <prettyName>Parse content</prettyName> + <unmodifiable>0</unmodifiable> + <classType>com.xpn.xwiki.objects.classes.BooleanClass</classType> + </parse> + <use> + <cache>0</cache> + <disabled>0</disabled> + <displayType>select</displayType> + <multiSelect>0</multiSelect> + <name>use</name> + <number>3</number> + <prettyName>Use this extension</prettyName> + <relationalStorage>0</relationalStorage> + <separator> </separator> + <separators>|, </separators> + <size>1</size> + <unmodifiable>0</unmodifiable> + <values>currentPage|onDemand|always</values> + <classType>com.xpn.xwiki.objects.classes.StaticListClass</classType> + </use> + </class> + <property> + <cache>long</cache> + </property> + <property> + <code>'use strict'; +## We handle the ability to disable the minification, by choosing the file extension to add to the script paths. +#set ($jsExtension = '.min.js') +#if (!$services.debug.minify) + #set ($jsExtension = '.js') +#end +/// +/// Start the requirejs config. +/// +require.config({ + paths: { + 'bootstrap-switch': '$services.webjars.url('bootstrap-switch', "js/bootstrap-switch${jsExtension}")' + }, + shim: { + 'bootstrap-switch' : ['jquery'] + } +}); +/// +/// Start the real script +/// +require(['jquery', 'bootstrap', 'bootstrap-switch'], function($) { + $(document).ready(function () { + + /// + /// Get the watchlist inputs for future usage + /// + var watchPageSwitch = $('#tmWatchDocument'); + var watchSpaceSwitch = $('#tmWatchSpace'); + var watchWikiSwitch = $('#tmWatchWiki'); + + /// + /// Apply the bootstrap switch plugin to the watchlist inputs + /// + $('notifications-watchlist-item input').each(function() { + var input = $(this); + input.bootstrapSwitch('onColor', 'success'); + input.bootstrapSwitch('offColor', 'danger'); + input.bootstrapSwitch('onText', 'ON'); + input.bootstrapSwitch('offText', 'OFF'); + input.bootstrapSwitch('size', 'small'); + }); + + /// + /// Set the icon corresponding to each switch + /// + watchPageSwitch.bootstrapSwitch('labelText', '$escapetool.javascript($services.icon.renderHTML('page'))'); + watchSpaceSwitch.bootstrapSwitch('labelText', '$escapetool.javascript($services.icon.renderHTML('chart-organisation'))'); + watchWikiSwitch.bootstrapSwitch('labelText', '$escapetool.javascript($services.icon.renderHTML('wiki'))'); + + /// + /// Add a tooltip to each switch + /// + $('.bootstrap-switch-id-tmWatchDocument').tooltip({title: 'Watch this page', placement: 'bottom'}); + $('.bootstrap-switch-id-tmWatchSpace').tooltip({title: 'Watch this page and children', placement: 'bottom'}); + $('.bootstrap-switch-id-tmWatchWiki').tooltip({title: 'Watch this wiki', placement: 'bottom'}); + + /** + * Change the watchlist status of a document/space/wiki. + * @param action the action to execute ('adddocument', 'removedocument', 'addspace', 'removespace', 'addwiki' + * or 'removewiki'). + */ + var changeWatchListStatus = function (action) { + var url = XWiki.currentDocument.getURL('get', 'xpage=watch'); + $.ajax(url, { 'data': { 'do': action } } ) + .fail (function() { + new XWiki.widgets.Notification('Failed to change the status of the WatchList.', 'error'); + }); + } + + /// + /// Change the watchlist status when the switched are manipulated by the user + /// + watchPageSwitch.bootstrapSwitch('onSwitchChange', function (event, status) { + changeWatchListStatus(status ? 'adddocument' : 'removedocument'); + }); + watchSpaceSwitch.bootstrapSwitch('onSwitchChange', function (event, status) { + changeWatchListStatus(status ? 'addspace' : 'removespace'); + }); + watchWikiSwitch.bootstrapSwitch('onSwitchChange', function (event, status) { + changeWatchListStatus(status ? 'addwiki' : 'removewiki'); + }); + + /// + /// Avoid the dropdown menu to be closed when the user click on the bootstrap switch + /// + $('.bootstrap-switch').click(function(event) { + event.stopImmediatePropagation(); + }); + + }); +}); +</code> + </property> + <property> + <name>JS</name> + </property> + <property> + <parse>1</parse> + </property> + <property> + <use>currentPage</use> + </property> + </object> + <object> + <name>XWiki.WatchListNotificationsUIX</name> + <number>0</number> + <className>XWiki.StyleSheetExtension</className> + <guid>9e56d70c-43b0-4008-9cce-ef2db85c0e64</guid> + <class> + <name>XWiki.StyleSheetExtension</name> + <customClass/> + <customMapping/> + <defaultViewSheet/> + <defaultEditSheet/> + <defaultWeb/> + <nameField/> + <validationScript/> + <cache> + <cache>0</cache> + <disabled>0</disabled> + <displayType>select</displayType> + <multiSelect>0</multiSelect> + <name>cache</name> + <number>6</number> + <prettyName>Caching policy</prettyName> + <relationalStorage>0</relationalStorage> + <separator> </separator> + <separators>|, </separators> + <size>1</size> + <unmodifiable>0</unmodifiable> + <values>long|short|default|forbid</values> + <classType>com.xpn.xwiki.objects.classes.StaticListClass</classType> + </cache> + <code> + <disabled>0</disabled> + <name>code</name> + <number>3</number> + <prettyName>Code</prettyName> + <rows>20</rows> + <size>50</size> + <unmodifiable>0</unmodifiable> + <classType>com.xpn.xwiki.objects.classes.TextAreaClass</classType> + </code> + <contentType> + <cache>0</cache> + <disabled>0</disabled> + <displayType>select</displayType> + <multiSelect>0</multiSelect> + <name>contentType</name> + <number>1</number> + <prettyName>Content Type</prettyName> + <relationalStorage>0</relationalStorage> + <separator> </separator> + <separators>|, </separators> + <size>1</size> + <unmodifiable>0</unmodifiable> + <values>CSS|LESS</values> + <classType>com.xpn.xwiki.objects.classes.StaticListClass</classType> + </contentType> + <name> + <disabled>0</disabled> + <name>name</name> + <number>2</number> + <prettyName>Name</prettyName> + <size>30</size> + <unmodifiable>0</unmodifiable> + <classType>com.xpn.xwiki.objects.classes.StringClass</classType> + </name> + <parse> + <disabled>0</disabled> + <displayFormType>select</displayFormType> + <displayType>yesno</displayType> + <name>parse</name> + <number>5</number> + <prettyName>Parse content</prettyName> + <unmodifiable>0</unmodifiable> + <classType>com.xpn.xwiki.objects.classes.BooleanClass</classType> + </parse> + <use> + <cache>0</cache> + <disabled>0</disabled> + <displayType>select</displayType> + <multiSelect>0</multiSelect> + <name>use</name> + <number>4</number> + <prettyName>Use this extension</prettyName> + <relationalStorage>0</relationalStorage> + <separator> </separator> + <separators>|, </separators> + <size>1</size> + <unmodifiable>0</unmodifiable> + <values>currentPage|onDemand|always</values> + <classType>com.xpn.xwiki.objects.classes.StaticListClass</classType> + </use> + </class> + <property> + <cache>long</cache> + </property> + <property> + <code>/* TODO: replace with @import statement when XWIKI-12788 is closed. Reason: http://www.stevesouders.com/blog/2009/04/09/dont-use-import/ */ +@import url("$services.webjars.url('bootstrap-switch', 'css/bootstrap3/bootstrap-switch.min.css')"); + +.notifications-watchlist-item { + margin: 0; + padding: 5px; + text-align: center; + text-transform: uppercase; +} + +.notifications-watchlist-item pre { + margin: 0; +} + +.notifications-watchlist-item .bootstrap-switch .bootstrap-switch-label { + /* TODO: use color theme */ + background-image: linear-gradient(#FFF, #ECECEC 50%, #DFDFDF); +} +</code> + </property> + <property> + <contentType>CSS</contentType> + </property> + <property> + <name>CSS</name> + </property> + <property> + <parse>1</parse> + </property> + <property> + <use>currentPage</use> + </property> + </object> + <object> + <name>XWiki.WatchListNotificationsUIX</name> + <number>0</number> + <className>XWiki.UIExtensionClass</className> + <guid>684dc8f1-fa89-4748-b9f0-2e83295dfa22</guid> + <class> + <name>XWiki.UIExtensionClass</name> + <customClass/> + <customMapping/> + <defaultViewSheet/> + <defaultEditSheet/> + <defaultWeb/> + <nameField/> + <validationScript/> + <content> + <disabled>0</disabled> + <name>content</name> + <number>3</number> + <prettyName>Extension Content</prettyName> + <rows>10</rows> + <size>40</size> + <unmodifiable>0</unmodifiable> + <classType>com.xpn.xwiki.objects.classes.TextAreaClass</classType> + </content> + <extensionPointId> + <disabled>0</disabled> + <name>extensionPointId</name> + <number>1</number> + <prettyName>Extension Point ID</prettyName> + <size>30</size> + <unmodifiable>0</unmodifiable> + <classType>com.xpn.xwiki.objects.classes.StringClass</classType> + </extensionPointId> + <name> + <disabled>0</disabled> + <name>name</name> + <number>2</number> + <prettyName>Extension ID</prettyName> + <size>30</size> + <unmodifiable>0</unmodifiable> + <classType>com.xpn.xwiki.objects.classes.StringClass</classType> + </name> + <parameters> + <disabled>0</disabled> + <name>parameters</name> + <number>4</number> + <prettyName>Extension Parameters</prettyName> + <rows>10</rows> + <size>40</size> + <unmodifiable>0</unmodifiable> + <classType>com.xpn.xwiki.objects.classes.TextAreaClass</classType> + </parameters> + <scope> + <cache>0</cache> + <disabled>0</disabled> + <displayType>select</displayType> + <multiSelect>0</multiSelect> + <name>scope</name> + <number>5</number> + <prettyName>Extension Scope</prettyName> + <relationalStorage>0</relationalStorage> + <separator> </separator> + <separators>|, </separators> + <size>1</size> + <unmodifiable>0</unmodifiable> + <values>wiki=Current Wiki|user=Current User|global=Global</values> + <classType>com.xpn.xwiki.objects.classes.StaticListClass</classType> + </scope> + </class> + <property> + <content>{{velocity}}{{html clean="false"}} ## we need clean="false" because we want to display the raw content of #submenuitem() +## +## Enable SSX and JSX +## +#set ($discard = $xwiki.ssx.use('XWiki.WatchListNotificationsUIX')) +#set ($discard = $xwiki.jsx.use('XWiki.WatchListNotificationsUIX')) +## +## Display the 3 toggle buttons +## +<li class="notifications-watchlist-item"> + #macro(displayCheckedIfWatched $scope)#if($services.watchlist.isWatched($scope))checked="checked"#end#end + <pre><input type="checkbox" id="tmWatchDocument" #displayCheckedIfWatched('DOCUMENT')/> <input type="checkbox" id="tmWatchSpace" displayCheckedIfWatched('SPACE')/> <input type="checkbox" id="tmWatchWiki" displayCheckedIfWatched('WIKI')/></pre> +</li> +</content> + </property> + <property> + <extensionPointId>org.xwiki.platform.notifications</extensionPointId> + </property> + <property> + <name>org.xwiki.platform.watchlist.ui.watchlistNotificationUix</name> + </property> + <property> + <parameters>order:10000 +separator:true</parameters> + </property> + <property> + <scope>wiki</scope> + </property> + </object> +</xwikidoc> diff --git a/xwiki-platform-core/xwiki-platform-web/src/main/webapp/resources/js/xwiki/xwiki.js b/xwiki-platform-core/xwiki-platform-web/src/main/webapp/resources/js/xwiki/xwiki.js index fe6587d6f45..41b09bff8ea 100644 --- a/xwiki-platform-core/xwiki-platform-web/src/main/webapp/resources/js/xwiki/xwiki.js +++ b/xwiki-platform-core/xwiki-platform-web/src/main/webapp/resources/js/xwiki/xwiki.js @@ -411,6 +411,9 @@ Object.extend(XWiki, { /** * Watchlist methods. + * + * @deprecated Since XWiki 7.4, the watchlist UI is implemented in a UI extension. This code is still there to not + * break the retro-compatibility but we can consider removing it. */ watchlist : { @@ -474,6 +477,15 @@ Object.extend(XWiki, { if (element.nodeName != 'A') { element = $(button).down('A'); } + + if (!element) { + // This is supposed to happen every time since the watchlist icons are implemented in the notifications + // menu. The watchlist icons are now implemented as a UI extension, and the inputs are handled with a + // custom solution (bootstrap-switch). + // For these reasons, we stop the initialization here. + // We keep this function for old skins (like Colibri), that still have the old-fashioned watchlist icons. + return; + } // unregister previously registered handler if any element.stopObserving('click'); -- GitLab