diff --git a/public/language/en-GB/global.json b/public/language/en-GB/global.json index 08835e8386..741fb4d2b8 100644 --- a/public/language/en-GB/global.json +++ b/public/language/en-GB/global.json @@ -132,5 +132,6 @@ "cookies.learn_more": "Learn More", "edited": "Edited", - "disabled": "Disabled" + "disabled": "Disabled", + "select": "Select" } diff --git a/public/language/en-GB/topic.json b/public/language/en-GB/topic.json index e25ef4973c..d206960156 100644 --- a/public/language/en-GB/topic.json +++ b/public/language/en-GB/topic.json @@ -100,7 +100,6 @@ "move_post": "Move Post", "post_moved": "Post moved!", "fork_topic": "Fork Topic", - "topic_will_be_moved_to": "This topic will be moved to the category", "fork_topic_instruction": "Click the posts you want to fork", "fork_no_pids": "No posts selected!", "fork_pid_count": "%1 post(s) selected", diff --git a/public/less/admin/admin.less b/public/less/admin/admin.less index 8f713028ed..0e4c590d00 100644 --- a/public/less/admin/admin.less +++ b/public/less/admin/admin.less @@ -232,6 +232,11 @@ body { } } +.category-dropdown-menu { + max-height: 600px; + overflow-y: auto; +} + .table-reordering { tr:hover { cursor: move; diff --git a/public/src/admin/manage/category.js b/public/src/admin/manage/category.js index 0373d3837a..70bcb571b2 100644 --- a/public/src/admin/manage/category.js +++ b/public/src/admin/manage/category.js @@ -7,7 +7,8 @@ define('admin/manage/category', [ 'admin/modules/colorpicker', 'autocomplete', 'translator', -], function (uploader, iconSelect, colorpicker, autocomplete, translator) { + 'categorySelector', +], function (uploader, iconSelect, colorpicker, autocomplete, translator, categorySelector) { var Category = {}; var modified_categories = {}; @@ -411,21 +412,24 @@ define('admin/manage/category', [ }, function (html) { translator.translate(html, function (html) { var modal = bootbox.dialog({ - title: 'Select a Category', + title: '[[modules:composer.select_category]]', message: html, buttons: { save: { - label: 'Copy', + label: '[[global:select]]', className: 'btn-primary', callback: submit, }, }, }); - - function submit() { - var formData = modal.find('form').serializeObject(); - callback(formData['select-cid']); - modal.modal('hide'); + categorySelector.init(modal.find('[component="category-selector"]')); + function submit(ev) { + ev.preventDefault(); + var selectedCategory = categorySelector.getSelectedCategory(); + if (selectedCategory) { + callback(selectedCategory.cid); + modal.modal('hide'); + } return false; } diff --git a/public/src/client/topic/move.js b/public/src/client/topic/move.js index e023d6822e..0b969ef6b9 100644 --- a/public/src/client/topic/move.js +++ b/public/src/client/topic/move.js @@ -1,7 +1,7 @@ 'use strict'; -define('forum/topic/move', function () { +define('forum/topic/move', ['categorySelector'], function (categorySelector) { var Move = {}; var modal; var selectedCategory; @@ -31,18 +31,7 @@ define('forum/topic/move', function () { modal.find('.modal-header h3').translateText('[[topic:move_topics]]'); } - modal.find('#select-cid').on('change', function () { - var cid = $(this).val(); - var optionEl = $(this).find('option[value="' + cid + '"]'); - - var selectedCategory = { - cid: cid, - name: optionEl.attr('data-name'), - text: optionEl.text(), - icon: optionEl.attr('data-icon'), - }; - selectCategory(selectedCategory); - }); + categorySelector.init(modal.find('[component="category-selector"]'), onCategorySelected); modal.find('#move_thread_commit').on('click', onCommitClicked); @@ -58,10 +47,7 @@ define('forum/topic/move', function () { }); } - function selectCategory(category) { - modal.find('#confirm-category-name').text(category.name); - modal.find('#move-confirm').removeClass('hide'); - + function onCategorySelected(category) { selectedCategory = category; modal.find('#move_thread_commit').prop('disabled', false); } @@ -88,7 +74,7 @@ define('forum/topic/move', function () { return app.alertError(err.message); } - app.alertSuccess('[[topic:topic_move_success, ' + selectedCategory.name + ']] <i class="fa fa-fw ' + selectedCategory.icon + '"></i>'); + app.alertSuccess('[[topic:topic_move_success, ' + selectedCategory.name + ']]'); if (typeof Move.onComplete === 'function') { Move.onComplete(); } diff --git a/public/src/modules/categorySelector.js b/public/src/modules/categorySelector.js new file mode 100644 index 0000000000..51b71e7117 --- /dev/null +++ b/public/src/modules/categorySelector.js @@ -0,0 +1,33 @@ +'use strict'; + + +define('categorySelector', function () { + var categorySelector = {}; + var selectedCategory; + var el; + categorySelector.init = function (_el, callback) { + callback = callback || function () {}; + el = _el; + el.on('click', '[data-cid]', function () { + var categoryEl = $(this); + categorySelector.selectCategory(categoryEl.attr('data-cid')); + callback(selectedCategory); + }); + }; + + categorySelector.getSelectedCategory = function () { + return selectedCategory; + }; + + categorySelector.selectCategory = function (cid) { + var categoryEl = el.find('[data-cid="' + cid + '"]'); + selectedCategory = { + cid: cid, + name: categoryEl.attr('data-name'), + }; + el.find('[component="category-selector-selected"]').html(categoryEl.find('[component="category-markup"]').html()); + }; + + return categorySelector; +}); + diff --git a/src/categories.js b/src/categories.js index fbafad7e50..4fd6ec3b1f 100644 --- a/src/categories.js +++ b/src/categories.js @@ -314,10 +314,10 @@ Categories.getTree = function (categories, parentCid) { return tree; }; -Categories.buildForSelect = function (uid, callback) { +Categories.buildForSelect = function (uid, privilege, callback) { async.waterfall([ function (next) { - Categories.getCategoriesByPrivilege('cid:0:children', uid, 'read', next); + Categories.getCategoriesByPrivilege('cid:0:children', uid, privilege, next); }, function (categories, next) { Categories.buildForSelectCategories(categories, next); @@ -333,6 +333,7 @@ Categories.buildForSelectCategories = function (categories, callback) { var bullet = level ? '• ' : ''; category.value = category.cid; + category.level = level; category.text = level + bullet + category.name; categoriesData.push(category); diff --git a/src/controllers/admin/categories.js b/src/controllers/admin/categories.js index 3dae05a388..0b78912644 100644 --- a/src/controllers/admin/categories.js +++ b/src/controllers/admin/categories.js @@ -16,7 +16,7 @@ categoriesController.get = function (req, res, callback) { async.parallel({ category: async.apply(categories.getCategories, [req.params.category_id], req.user.uid), privileges: async.apply(privileges.categories.list, req.params.category_id), - allCategories: async.apply(categories.buildForSelect, req.uid), + allCategories: async.apply(categories.buildForSelect, req.uid, 'read'), }, next); }, function (data, next) { diff --git a/src/controllers/mods.js b/src/controllers/mods.js index 32e416a20d..98990e97ba 100644 --- a/src/controllers/mods.js +++ b/src/controllers/mods.js @@ -59,7 +59,7 @@ modsController.flags.list = function (req, res, next) { async.parallel({ flags: async.apply(flags.list, filters, req.uid), analytics: async.apply(analytics.getDailyStatsForSet, 'analytics:flags', Date.now(), 30), - categories: async.apply(categories.buildForSelect, req.uid), + categories: async.apply(categories.buildForSelect, req.uid, 'read'), }, next); }, function (data) { diff --git a/src/controllers/search.js b/src/controllers/search.js index bf818a39d5..309f77f557 100644 --- a/src/controllers/search.js +++ b/src/controllers/search.js @@ -46,7 +46,7 @@ searchController.search = function (req, res, next) { }; async.parallel({ - categories: async.apply(categories.buildForSelect, req.uid), + categories: async.apply(categories.buildForSelect, req.uid, 'read'), search: async.apply(search.search, data), }, function (err, results) { if (err) { diff --git a/src/meta/js.js b/src/meta/js.js index 4858f69bf5..d1777e35b1 100644 --- a/src/meta/js.js +++ b/src/meta/js.js @@ -67,6 +67,7 @@ module.exports = function (Meta) { 'public/src/modules/sort.js', 'public/src/modules/navigator.js', 'public/src/modules/topicSelect.js', + 'public/src/modules/categorySelector.js', 'public/src/modules/share.js', 'public/src/modules/search.js', 'public/src/modules/alerts.js', diff --git a/src/views/admin/partials/categories/select-category.tpl b/src/views/admin/partials/categories/select-category.tpl index b9b8e39e2e..1cf5e90529 100644 --- a/src/views/admin/partials/categories/select-category.tpl +++ b/src/views/admin/partials/categories/select-category.tpl @@ -1,10 +1,16 @@ <form type="form"> <div class="form-group"> - <label for="select-cid">[[admin/manage/categories:select-category]]</label> - <select class="form-control" name="select-cid" id="select-cid"> - <!-- BEGIN categories --> - <option value="{categories.cid}">{categories.text}</option> - <!-- END categories --> - </select> + <div component="category-selector" class="btn-group"> + <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> + <span component="category-selector-selected">[[topic:thread_tools.select_category]]</span> <span class="caret"></span> + </button> + <ul class="dropdown-menu category-dropdown-menu" role="menu"> + <!-- BEGIN categories --> + <li role="presentation" class="category" data-cid="{categories.cid}" data-name="{categories.name}"> + <a role="menu-item">{categories.level}<span component="category-markup"><!-- IF categories.icon --><span class="fa-stack"><i style="color: {categories.bgColor};" class="fa fa-circle fa-stack-2x"></i><i style="color: {categories.color};" class="fa fa-stack-1x fa-fw {categories.icon}"></i></span><!-- ENDIF categories.icon --> {categories.name}</span></a> + </li> + <!-- END categories --> + </ul> + </div> </div> </form> \ No newline at end of file