From 805d1bf5a2ba21dac6af48ef0794b7e391cd803b Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Sun, 21 Oct 2018 20:32:40 +0700 Subject: [PATCH 01/34] add list.js library Add lib for user list features. http://listjs.com/ --- common/js/list.js | 1758 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1758 insertions(+) create mode 100644 common/js/list.js diff --git a/common/js/list.js b/common/js/list.js new file mode 100644 index 000000000..d40457fb3 --- /dev/null +++ b/common/js/list.js @@ -0,0 +1,1758 @@ +/*! List.js v1.5.0 (http://listjs.com) by Jonny Strömberg (http://javve.com) */ +var List = +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.l = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // identity function for calling harmony imports with the correct context +/******/ __webpack_require__.i = function(value) { return value; }; + +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; + +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; + +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 11); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Module dependencies. + */ + +var index = __webpack_require__(4); + +/** + * Whitespace regexp. + */ + +var re = /\s+/; + +/** + * toString reference. + */ + +var toString = Object.prototype.toString; + +/** + * Wrap `el` in a `ClassList`. + * + * @param {Element} el + * @return {ClassList} + * @api public + */ + +module.exports = function(el){ + return new ClassList(el); +}; + +/** + * Initialize a new ClassList for `el`. + * + * @param {Element} el + * @api private + */ + +function ClassList(el) { + if (!el || !el.nodeType) { + throw new Error('A DOM element reference is required'); + } + this.el = el; + this.list = el.classList; +} + +/** + * Add class `name` if not already present. + * + * @param {String} name + * @return {ClassList} + * @api public + */ + +ClassList.prototype.add = function(name){ + // classList + if (this.list) { + this.list.add(name); + return this; + } + + // fallback + var arr = this.array(); + var i = index(arr, name); + if (!~i) arr.push(name); + this.el.className = arr.join(' '); + return this; +}; + +/** + * Remove class `name` when present, or + * pass a regular expression to remove + * any which match. + * + * @param {String|RegExp} name + * @return {ClassList} + * @api public + */ + +ClassList.prototype.remove = function(name){ + // classList + if (this.list) { + this.list.remove(name); + return this; + } + + // fallback + var arr = this.array(); + var i = index(arr, name); + if (~i) arr.splice(i, 1); + this.el.className = arr.join(' '); + return this; +}; + + +/** + * Toggle class `name`, can force state via `force`. + * + * For browsers that support classList, but do not support `force` yet, + * the mistake will be detected and corrected. + * + * @param {String} name + * @param {Boolean} force + * @return {ClassList} + * @api public + */ + +ClassList.prototype.toggle = function(name, force){ + // classList + if (this.list) { + if ("undefined" !== typeof force) { + if (force !== this.list.toggle(name, force)) { + this.list.toggle(name); // toggle again to correct + } + } else { + this.list.toggle(name); + } + return this; + } + + // fallback + if ("undefined" !== typeof force) { + if (!force) { + this.remove(name); + } else { + this.add(name); + } + } else { + if (this.has(name)) { + this.remove(name); + } else { + this.add(name); + } + } + + return this; +}; + +/** + * Return an array of classes. + * + * @return {Array} + * @api public + */ + +ClassList.prototype.array = function(){ + var className = this.el.getAttribute('class') || ''; + var str = className.replace(/^\s+|\s+$/g, ''); + var arr = str.split(re); + if ('' === arr[0]) arr.shift(); + return arr; +}; + +/** + * Check if class `name` is present. + * + * @param {String} name + * @return {ClassList} + * @api public + */ + +ClassList.prototype.has = +ClassList.prototype.contains = function(name){ + return this.list ? this.list.contains(name) : !! ~index(this.array(), name); +}; + + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + +var bind = window.addEventListener ? 'addEventListener' : 'attachEvent', + unbind = window.removeEventListener ? 'removeEventListener' : 'detachEvent', + prefix = bind !== 'addEventListener' ? 'on' : '', + toArray = __webpack_require__(5); + +/** + * Bind `el` event `type` to `fn`. + * + * @param {Element} el, NodeList, HTMLCollection or Array + * @param {String} type + * @param {Function} fn + * @param {Boolean} capture + * @api public + */ + +exports.bind = function(el, type, fn, capture){ + el = toArray(el); + for ( var i = 0; i < el.length; i++ ) { + el[i][bind](prefix + type, fn, capture || false); + } +}; + +/** + * Unbind `el` event `type`'s callback `fn`. + * + * @param {Element} el, NodeList, HTMLCollection or Array + * @param {String} type + * @param {Function} fn + * @param {Boolean} capture + * @api public + */ + +exports.unbind = function(el, type, fn, capture){ + el = toArray(el); + for ( var i = 0; i < el.length; i++ ) { + el[i][unbind](prefix + type, fn, capture || false); + } +}; + + +/***/ }), +/* 2 */ +/***/ (function(module, exports) { + +module.exports = function(list) { + return function(initValues, element, notCreate) { + var item = this; + + this._values = {}; + + this.found = false; // Show if list.searched == true and this.found == true + this.filtered = false;// Show if list.filtered == true and this.filtered == true + + var init = function(initValues, element, notCreate) { + if (element === undefined) { + if (notCreate) { + item.values(initValues, notCreate); + } else { + item.values(initValues); + } + } else { + item.elm = element; + var values = list.templater.get(item, initValues); + item.values(values); + } + }; + + this.values = function(newValues, notCreate) { + if (newValues !== undefined) { + for(var name in newValues) { + item._values[name] = newValues[name]; + } + if (notCreate !== true) { + list.templater.set(item, item.values()); + } + } else { + return item._values; + } + }; + + this.show = function() { + list.templater.show(item); + }; + + this.hide = function() { + list.templater.hide(item); + }; + + this.matching = function() { + return ( + (list.filtered && list.searched && item.found && item.filtered) || + (list.filtered && !list.searched && item.filtered) || + (!list.filtered && list.searched && item.found) || + (!list.filtered && !list.searched) + ); + }; + + this.visible = function() { + return (item.elm && (item.elm.parentNode == list.list)) ? true : false; + }; + + init(initValues, element, notCreate); + }; +}; + + +/***/ }), +/* 3 */ +/***/ (function(module, exports) { + +/** + * A cross-browser implementation of getElementsByClass. + * Heavily based on Dustin Diaz's function: http://dustindiaz.com/getelementsbyclass. + * + * Find all elements with class `className` inside `container`. + * Use `single = true` to increase performance in older browsers + * when only one element is needed. + * + * @param {String} className + * @param {Element} container + * @param {Boolean} single + * @api public + */ + +var getElementsByClassName = function(container, className, single) { + if (single) { + return container.getElementsByClassName(className)[0]; + } else { + return container.getElementsByClassName(className); + } +}; + +var querySelector = function(container, className, single) { + className = '.' + className; + if (single) { + return container.querySelector(className); + } else { + return container.querySelectorAll(className); + } +}; + +var polyfill = function(container, className, single) { + var classElements = [], + tag = '*'; + + var els = container.getElementsByTagName(tag); + var elsLen = els.length; + var pattern = new RegExp("(^|\\s)"+className+"(\\s|$)"); + for (var i = 0, j = 0; i < elsLen; i++) { + if ( pattern.test(els[i].className) ) { + if (single) { + return els[i]; + } else { + classElements[j] = els[i]; + j++; + } + } + } + return classElements; +}; + +module.exports = (function() { + return function(container, className, single, options) { + options = options || {}; + if ((options.test && options.getElementsByClassName) || (!options.test && document.getElementsByClassName)) { + return getElementsByClassName(container, className, single); + } else if ((options.test && options.querySelector) || (!options.test && document.querySelector)) { + return querySelector(container, className, single); + } else { + return polyfill(container, className, single); + } + }; +})(); + + +/***/ }), +/* 4 */ +/***/ (function(module, exports) { + +var indexOf = [].indexOf; + +module.exports = function(arr, obj){ + if (indexOf) return arr.indexOf(obj); + for (var i = 0; i < arr.length; ++i) { + if (arr[i] === obj) return i; + } + return -1; +}; + + +/***/ }), +/* 5 */ +/***/ (function(module, exports) { + +/** + * Source: https://github.com/timoxley/to-array + * + * Convert an array-like object into an `Array`. + * If `collection` is already an `Array`, then will return a clone of `collection`. + * + * @param {Array | Mixed} collection An `Array` or array-like object to convert e.g. `arguments` or `NodeList` + * @return {Array} Naive conversion of `collection` to a new `Array`. + * @api public + */ + +module.exports = function toArray(collection) { + if (typeof collection === 'undefined') return []; + if (collection === null) return [null]; + if (collection === window) return [window]; + if (typeof collection === 'string') return [collection]; + if (isArray(collection)) return collection; + if (typeof collection.length != 'number') return [collection]; + if (typeof collection === 'function' && collection instanceof Function) return [collection]; + + var arr = []; + for (var i = 0; i < collection.length; i++) { + if (Object.prototype.hasOwnProperty.call(collection, i) || i in collection) { + arr.push(collection[i]); + } + } + if (!arr.length) return []; + return arr; +}; + +function isArray(arr) { + return Object.prototype.toString.call(arr) === "[object Array]"; +} + + +/***/ }), +/* 6 */ +/***/ (function(module, exports) { + +module.exports = function(s) { + s = (s === undefined) ? "" : s; + s = (s === null) ? "" : s; + s = s.toString(); + return s; +}; + + +/***/ }), +/* 7 */ +/***/ (function(module, exports) { + +/* + * Source: https://github.com/segmentio/extend + */ + +module.exports = function extend (object) { + // Takes an unlimited number of extenders. + var args = Array.prototype.slice.call(arguments, 1); + + // For each extender, copy their properties on our object. + for (var i = 0, source; source = args[i]; i++) { + if (!source) continue; + for (var property in source) { + object[property] = source[property]; + } + } + + return object; +}; + + +/***/ }), +/* 8 */ +/***/ (function(module, exports) { + +module.exports = function(list) { + var addAsync = function(values, callback, items) { + var valuesToAdd = values.splice(0, 50); + items = items || []; + items = items.concat(list.add(valuesToAdd)); + if (values.length > 0) { + setTimeout(function() { + addAsync(values, callback, items); + }, 1); + } else { + list.update(); + callback(items); + } + }; + return addAsync; +}; + + +/***/ }), +/* 9 */ +/***/ (function(module, exports) { + +module.exports = function(list) { + + // Add handlers + list.handlers.filterStart = list.handlers.filterStart || []; + list.handlers.filterComplete = list.handlers.filterComplete || []; + + return function(filterFunction) { + list.trigger('filterStart'); + list.i = 1; // Reset paging + list.reset.filter(); + if (filterFunction === undefined) { + list.filtered = false; + } else { + list.filtered = true; + var is = list.items; + for (var i = 0, il = is.length; i < il; i++) { + var item = is[i]; + if (filterFunction(item)) { + item.filtered = true; + } else { + item.filtered = false; + } + } + } + list.update(); + list.trigger('filterComplete'); + return list.visibleItems; + }; +}; + + +/***/ }), +/* 10 */ +/***/ (function(module, exports, __webpack_require__) { + + +var classes = __webpack_require__(0), + events = __webpack_require__(1), + extend = __webpack_require__(7), + toString = __webpack_require__(6), + getByClass = __webpack_require__(3), + fuzzy = __webpack_require__(19); + +module.exports = function(list, options) { + options = options || {}; + + options = extend({ + location: 0, + distance: 100, + threshold: 0.4, + multiSearch: true, + searchClass: 'fuzzy-search' + }, options); + + + + var fuzzySearch = { + search: function(searchString, columns) { + // Substract arguments from the searchString or put searchString as only argument + var searchArguments = options.multiSearch ? searchString.replace(/ +$/, '').split(/ +/) : [searchString]; + + for (var k = 0, kl = list.items.length; k < kl; k++) { + fuzzySearch.item(list.items[k], columns, searchArguments); + } + }, + item: function(item, columns, searchArguments) { + var found = true; + for(var i = 0; i < searchArguments.length; i++) { + var foundArgument = false; + for (var j = 0, jl = columns.length; j < jl; j++) { + if (fuzzySearch.values(item.values(), columns[j], searchArguments[i])) { + foundArgument = true; + } + } + if(!foundArgument) { + found = false; + } + } + item.found = found; + }, + values: function(values, value, searchArgument) { + if (values.hasOwnProperty(value)) { + var text = toString(values[value]).toLowerCase(); + + if (fuzzy(text, searchArgument, options)) { + return true; + } + } + return false; + } + }; + + + events.bind(getByClass(list.listContainer, options.searchClass), 'keyup', function(e) { + var target = e.target || e.srcElement; // IE have srcElement + list.search(target.value, fuzzySearch.search); + }); + + return function(str, columns) { + list.search(str, columns, fuzzySearch.search); + }; +}; + + +/***/ }), +/* 11 */ +/***/ (function(module, exports, __webpack_require__) { + +var naturalSort = __webpack_require__(18), + getByClass = __webpack_require__(3), + extend = __webpack_require__(7), + indexOf = __webpack_require__(4), + events = __webpack_require__(1), + toString = __webpack_require__(6), + classes = __webpack_require__(0), + getAttribute = __webpack_require__(17), + toArray = __webpack_require__(5); + +module.exports = function(id, options, values) { + + var self = this, + init, + Item = __webpack_require__(2)(self), + addAsync = __webpack_require__(8)(self), + initPagination = __webpack_require__(12)(self); + + init = { + start: function() { + self.listClass = "list"; + self.searchClass = "search"; + self.sortClass = "sort"; + self.page = 10000; + self.i = 1; + self.items = []; + self.visibleItems = []; + self.matchingItems = []; + self.searched = false; + self.filtered = false; + self.searchColumns = undefined; + self.handlers = { 'updated': [] }; + self.valueNames = []; + self.utils = { + getByClass: getByClass, + extend: extend, + indexOf: indexOf, + events: events, + toString: toString, + naturalSort: naturalSort, + classes: classes, + getAttribute: getAttribute, + toArray: toArray + }; + + self.utils.extend(self, options); + + self.listContainer = (typeof(id) === 'string') ? document.getElementById(id) : id; + if (!self.listContainer) { return; } + self.list = getByClass(self.listContainer, self.listClass, true); + + self.parse = __webpack_require__(13)(self); + self.templater = __webpack_require__(16)(self); + self.search = __webpack_require__(14)(self); + self.filter = __webpack_require__(9)(self); + self.sort = __webpack_require__(15)(self); + self.fuzzySearch = __webpack_require__(10)(self, options.fuzzySearch); + + this.handlers(); + this.items(); + this.pagination(); + + self.update(); + }, + handlers: function() { + for (var handler in self.handlers) { + if (self[handler]) { + self.on(handler, self[handler]); + } + } + }, + items: function() { + self.parse(self.list); + if (values !== undefined) { + self.add(values); + } + }, + pagination: function() { + if (options.pagination !== undefined) { + if (options.pagination === true) { + options.pagination = [{}]; + } + if (options.pagination[0] === undefined){ + options.pagination = [options.pagination]; + } + for (var i = 0, il = options.pagination.length; i < il; i++) { + initPagination(options.pagination[i]); + } + } + } + }; + + /* + * Re-parse the List, use if html have changed + */ + this.reIndex = function() { + self.items = []; + self.visibleItems = []; + self.matchingItems = []; + self.searched = false; + self.filtered = false; + self.parse(self.list); + }; + + this.toJSON = function() { + var json = []; + for (var i = 0, il = self.items.length; i < il; i++) { + json.push(self.items[i].values()); + } + return json; + }; + + + /* + * Add object to list + */ + this.add = function(values, callback) { + if (values.length === 0) { + return; + } + if (callback) { + addAsync(values, callback); + return; + } + var added = [], + notCreate = false; + if (values[0] === undefined){ + values = [values]; + } + for (var i = 0, il = values.length; i < il; i++) { + var item = null; + notCreate = (self.items.length > self.page) ? true : false; + item = new Item(values[i], undefined, notCreate); + self.items.push(item); + added.push(item); + } + self.update(); + return added; + }; + + this.show = function(i, page) { + this.i = i; + this.page = page; + self.update(); + return self; + }; + + /* Removes object from list. + * Loops through the list and removes objects where + * property "valuename" === value + */ + this.remove = function(valueName, value, options) { + var found = 0; + for (var i = 0, il = self.items.length; i < il; i++) { + if (self.items[i].values()[valueName] == value) { + self.templater.remove(self.items[i], options); + self.items.splice(i,1); + il--; + i--; + found++; + } + } + self.update(); + return found; + }; + + /* Gets the objects in the list which + * property "valueName" === value + */ + this.get = function(valueName, value) { + var matchedItems = []; + for (var i = 0, il = self.items.length; i < il; i++) { + var item = self.items[i]; + if (item.values()[valueName] == value) { + matchedItems.push(item); + } + } + return matchedItems; + }; + + /* + * Get size of the list + */ + this.size = function() { + return self.items.length; + }; + + /* + * Removes all items from the list + */ + this.clear = function() { + self.templater.clear(); + self.items = []; + return self; + }; + + this.on = function(event, callback) { + self.handlers[event].push(callback); + return self; + }; + + this.off = function(event, callback) { + var e = self.handlers[event]; + var index = indexOf(e, callback); + if (index > -1) { + e.splice(index, 1); + } + return self; + }; + + this.trigger = function(event) { + var i = self.handlers[event].length; + while(i--) { + self.handlers[event][i](self); + } + return self; + }; + + this.reset = { + filter: function() { + var is = self.items, + il = is.length; + while (il--) { + is[il].filtered = false; + } + return self; + }, + search: function() { + var is = self.items, + il = is.length; + while (il--) { + is[il].found = false; + } + return self; + } + }; + + this.update = function() { + var is = self.items, + il = is.length; + + self.visibleItems = []; + self.matchingItems = []; + self.templater.clear(); + for (var i = 0; i < il; i++) { + if (is[i].matching() && ((self.matchingItems.length+1) >= self.i && self.visibleItems.length < self.page)) { + is[i].show(); + self.visibleItems.push(is[i]); + self.matchingItems.push(is[i]); + } else if (is[i].matching()) { + self.matchingItems.push(is[i]); + is[i].hide(); + } else { + is[i].hide(); + } + } + self.trigger('updated'); + return self; + }; + + init.start(); +}; + + +/***/ }), +/* 12 */ +/***/ (function(module, exports, __webpack_require__) { + +var classes = __webpack_require__(0), + events = __webpack_require__(1), + List = __webpack_require__(11); + +module.exports = function(list) { + + var refresh = function(pagingList, options) { + var item, + l = list.matchingItems.length, + index = list.i, + page = list.page, + pages = Math.ceil(l / page), + currentPage = Math.ceil((index / page)), + innerWindow = options.innerWindow || 2, + left = options.left || options.outerWindow || 0, + right = options.right || options.outerWindow || 0; + + right = pages - right; + + pagingList.clear(); + for (var i = 1; i <= pages; i++) { + var className = (currentPage === i) ? "active" : ""; + + //console.log(i, left, right, currentPage, (currentPage - innerWindow), (currentPage + innerWindow), className); + + if (is.number(i, left, right, currentPage, innerWindow)) { + item = pagingList.add({ + page: i, + dotted: false + })[0]; + if (className) { + classes(item.elm).add(className); + } + addEvent(item.elm, i, page); + } else if (is.dotted(pagingList, i, left, right, currentPage, innerWindow, pagingList.size())) { + item = pagingList.add({ + page: "...", + dotted: true + })[0]; + classes(item.elm).add("disabled"); + } + } + }; + + var is = { + number: function(i, left, right, currentPage, innerWindow) { + return this.left(i, left) || this.right(i, right) || this.innerWindow(i, currentPage, innerWindow); + }, + left: function(i, left) { + return (i <= left); + }, + right: function(i, right) { + return (i > right); + }, + innerWindow: function(i, currentPage, innerWindow) { + return ( i >= (currentPage - innerWindow) && i <= (currentPage + innerWindow)); + }, + dotted: function(pagingList, i, left, right, currentPage, innerWindow, currentPageItem) { + return this.dottedLeft(pagingList, i, left, right, currentPage, innerWindow) || (this.dottedRight(pagingList, i, left, right, currentPage, innerWindow, currentPageItem)); + }, + dottedLeft: function(pagingList, i, left, right, currentPage, innerWindow) { + return ((i == (left + 1)) && !this.innerWindow(i, currentPage, innerWindow) && !this.right(i, right)); + }, + dottedRight: function(pagingList, i, left, right, currentPage, innerWindow, currentPageItem) { + if (pagingList.items[currentPageItem-1].values().dotted) { + return false; + } else { + return ((i == (right)) && !this.innerWindow(i, currentPage, innerWindow) && !this.right(i, right)); + } + } + }; + + var addEvent = function(elm, i, page) { + events.bind(elm, 'click', function() { + list.show((i-1)*page + 1, page); + }); + }; + + return function(options) { + var pagingList = new List(list.listContainer.id, { + listClass: options.paginationClass || 'pagination', + item: "
  • ", + valueNames: ['page', 'dotted'], + searchClass: 'pagination-search-that-is-not-supposed-to-exist', + sortClass: 'pagination-sort-that-is-not-supposed-to-exist' + }); + + list.on('updated', function() { + refresh(pagingList, options); + }); + refresh(pagingList, options); + }; +}; + + +/***/ }), +/* 13 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = function(list) { + + var Item = __webpack_require__(2)(list); + + var getChildren = function(parent) { + var nodes = parent.childNodes, + items = []; + for (var i = 0, il = nodes.length; i < il; i++) { + // Only textnodes have a data attribute + if (nodes[i].data === undefined) { + items.push(nodes[i]); + } + } + return items; + }; + + var parse = function(itemElements, valueNames) { + for (var i = 0, il = itemElements.length; i < il; i++) { + list.items.push(new Item(valueNames, itemElements[i])); + } + }; + var parseAsync = function(itemElements, valueNames) { + var itemsToIndex = itemElements.splice(0, 50); // TODO: If < 100 items, what happens in IE etc? + parse(itemsToIndex, valueNames); + if (itemElements.length > 0) { + setTimeout(function() { + parseAsync(itemElements, valueNames); + }, 1); + } else { + list.update(); + list.trigger('parseComplete'); + } + }; + + list.handlers.parseComplete = list.handlers.parseComplete || []; + + return function() { + var itemsToIndex = getChildren(list.list), + valueNames = list.valueNames; + + if (list.indexAsync) { + parseAsync(itemsToIndex, valueNames); + } else { + parse(itemsToIndex, valueNames); + } + }; +}; + + +/***/ }), +/* 14 */ +/***/ (function(module, exports) { + +module.exports = function(list) { + var item, + text, + columns, + searchString, + customSearch; + + var prepare = { + resetList: function() { + list.i = 1; + list.templater.clear(); + customSearch = undefined; + }, + setOptions: function(args) { + if (args.length == 2 && args[1] instanceof Array) { + columns = args[1]; + } else if (args.length == 2 && typeof(args[1]) == "function") { + columns = undefined; + customSearch = args[1]; + } else if (args.length == 3) { + columns = args[1]; + customSearch = args[2]; + } else { + columns = undefined; + } + }, + setColumns: function() { + if (list.items.length === 0) return; + if (columns === undefined) { + columns = (list.searchColumns === undefined) ? prepare.toArray(list.items[0].values()) : list.searchColumns; + } + }, + setSearchString: function(s) { + s = list.utils.toString(s).toLowerCase(); + s = s.replace(/[-[\]{}()*+?.,\\^$|#]/g, "\\$&"); // Escape regular expression characters + searchString = s; + }, + toArray: function(values) { + var tmpColumn = []; + for (var name in values) { + tmpColumn.push(name); + } + return tmpColumn; + } + }; + var search = { + list: function() { + for (var k = 0, kl = list.items.length; k < kl; k++) { + search.item(list.items[k]); + } + }, + item: function(item) { + item.found = false; + for (var j = 0, jl = columns.length; j < jl; j++) { + if (search.values(item.values(), columns[j])) { + item.found = true; + return; + } + } + }, + values: function(values, column) { + if (values.hasOwnProperty(column)) { + text = list.utils.toString(values[column]).toLowerCase(); + if ((searchString !== "") && (text.search(searchString) > -1)) { + return true; + } + } + return false; + }, + reset: function() { + list.reset.search(); + list.searched = false; + } + }; + + var searchMethod = function(str) { + list.trigger('searchStart'); + + prepare.resetList(); + prepare.setSearchString(str); + prepare.setOptions(arguments); // str, cols|searchFunction, searchFunction + prepare.setColumns(); + + if (searchString === "" ) { + search.reset(); + } else { + list.searched = true; + if (customSearch) { + customSearch(searchString, columns); + } else { + search.list(); + } + } + + list.update(); + list.trigger('searchComplete'); + return list.visibleItems; + }; + + list.handlers.searchStart = list.handlers.searchStart || []; + list.handlers.searchComplete = list.handlers.searchComplete || []; + + list.utils.events.bind(list.utils.getByClass(list.listContainer, list.searchClass), 'keyup', function(e) { + var target = e.target || e.srcElement, // IE have srcElement + alreadyCleared = (target.value === "" && !list.searched); + if (!alreadyCleared) { // If oninput already have resetted the list, do nothing + searchMethod(target.value); + } + }); + + // Used to detect click on HTML5 clear button + list.utils.events.bind(list.utils.getByClass(list.listContainer, list.searchClass), 'input', function(e) { + var target = e.target || e.srcElement; + if (target.value === "") { + searchMethod(''); + } + }); + + return searchMethod; +}; + + +/***/ }), +/* 15 */ +/***/ (function(module, exports) { + +module.exports = function(list) { + + var buttons = { + els: undefined, + clear: function() { + for (var i = 0, il = buttons.els.length; i < il; i++) { + list.utils.classes(buttons.els[i]).remove('asc'); + list.utils.classes(buttons.els[i]).remove('desc'); + } + }, + getOrder: function(btn) { + var predefinedOrder = list.utils.getAttribute(btn, 'data-order'); + if (predefinedOrder == "asc" || predefinedOrder == "desc") { + return predefinedOrder; + } else if (list.utils.classes(btn).has('desc')) { + return "asc"; + } else if (list.utils.classes(btn).has('asc')) { + return "desc"; + } else { + return "asc"; + } + }, + getInSensitive: function(btn, options) { + var insensitive = list.utils.getAttribute(btn, 'data-insensitive'); + if (insensitive === "false") { + options.insensitive = false; + } else { + options.insensitive = true; + } + }, + setOrder: function(options) { + for (var i = 0, il = buttons.els.length; i < il; i++) { + var btn = buttons.els[i]; + if (list.utils.getAttribute(btn, 'data-sort') !== options.valueName) { + continue; + } + var predefinedOrder = list.utils.getAttribute(btn, 'data-order'); + if (predefinedOrder == "asc" || predefinedOrder == "desc") { + if (predefinedOrder == options.order) { + list.utils.classes(btn).add(options.order); + } + } else { + list.utils.classes(btn).add(options.order); + } + } + } + }; + + var sort = function() { + list.trigger('sortStart'); + var options = {}; + + var target = arguments[0].currentTarget || arguments[0].srcElement || undefined; + + if (target) { + options.valueName = list.utils.getAttribute(target, 'data-sort'); + buttons.getInSensitive(target, options); + options.order = buttons.getOrder(target); + } else { + options = arguments[1] || options; + options.valueName = arguments[0]; + options.order = options.order || "asc"; + options.insensitive = (typeof options.insensitive == "undefined") ? true : options.insensitive; + } + + buttons.clear(); + buttons.setOrder(options); + + + // caseInsensitive + // alphabet + var customSortFunction = (options.sortFunction || list.sortFunction || null), + multi = ((options.order === 'desc') ? -1 : 1), + sortFunction; + + if (customSortFunction) { + sortFunction = function(itemA, itemB) { + return customSortFunction(itemA, itemB, options) * multi; + }; + } else { + sortFunction = function(itemA, itemB) { + var sort = list.utils.naturalSort; + sort.alphabet = list.alphabet || options.alphabet || undefined; + if (!sort.alphabet && options.insensitive) { + sort = list.utils.naturalSort.caseInsensitive; + } + return sort(itemA.values()[options.valueName], itemB.values()[options.valueName]) * multi; + }; + } + + list.items.sort(sortFunction); + list.update(); + list.trigger('sortComplete'); + }; + + // Add handlers + list.handlers.sortStart = list.handlers.sortStart || []; + list.handlers.sortComplete = list.handlers.sortComplete || []; + + buttons.els = list.utils.getByClass(list.listContainer, list.sortClass); + list.utils.events.bind(buttons.els, 'click', sort); + list.on('searchStart', buttons.clear); + list.on('filterStart', buttons.clear); + + return sort; +}; + + +/***/ }), +/* 16 */ +/***/ (function(module, exports) { + +var Templater = function(list) { + var itemSource, + templater = this; + + var init = function() { + itemSource = templater.getItemSource(list.item); + if (itemSource) { + itemSource = templater.clearSourceItem(itemSource, list.valueNames); + } + }; + + this.clearSourceItem = function(el, valueNames) { + for(var i = 0, il = valueNames.length; i < il; i++) { + var elm; + if (valueNames[i].data) { + for (var j = 0, jl = valueNames[i].data.length; j < jl; j++) { + el.setAttribute('data-'+valueNames[i].data[j], ''); + } + } else if (valueNames[i].attr && valueNames[i].name) { + elm = list.utils.getByClass(el, valueNames[i].name, true); + if (elm) { + elm.setAttribute(valueNames[i].attr, ""); + } + } else { + elm = list.utils.getByClass(el, valueNames[i], true); + if (elm) { + elm.innerHTML = ""; + } + } + elm = undefined; + } + return el; + }; + + this.getItemSource = function(item) { + if (item === undefined) { + var nodes = list.list.childNodes, + items = []; + + for (var i = 0, il = nodes.length; i < il; i++) { + // Only textnodes have a data attribute + if (nodes[i].data === undefined) { + return nodes[i].cloneNode(true); + } + } + } else if (/]/g.exec(item)) { + var tbody = document.createElement('tbody'); + tbody.innerHTML = item; + return tbody.firstChild; + } else if (item.indexOf("<") !== -1) { + var div = document.createElement('div'); + div.innerHTML = item; + return div.firstChild; + } else { + var source = document.getElementById(list.item); + if (source) { + return source; + } + } + return undefined; + }; + + this.get = function(item, valueNames) { + templater.create(item); + var values = {}; + for(var i = 0, il = valueNames.length; i < il; i++) { + var elm; + if (valueNames[i].data) { + for (var j = 0, jl = valueNames[i].data.length; j < jl; j++) { + values[valueNames[i].data[j]] = list.utils.getAttribute(item.elm, 'data-'+valueNames[i].data[j]); + } + } else if (valueNames[i].attr && valueNames[i].name) { + elm = list.utils.getByClass(item.elm, valueNames[i].name, true); + values[valueNames[i].name] = elm ? list.utils.getAttribute(elm, valueNames[i].attr) : ""; + } else { + elm = list.utils.getByClass(item.elm, valueNames[i], true); + values[valueNames[i]] = elm ? elm.innerHTML : ""; + } + elm = undefined; + } + return values; + }; + + this.set = function(item, values) { + var getValueName = function(name) { + for (var i = 0, il = list.valueNames.length; i < il; i++) { + if (list.valueNames[i].data) { + var data = list.valueNames[i].data; + for (var j = 0, jl = data.length; j < jl; j++) { + if (data[j] === name) { + return { data: name }; + } + } + } else if (list.valueNames[i].attr && list.valueNames[i].name && list.valueNames[i].name == name) { + return list.valueNames[i]; + } else if (list.valueNames[i] === name) { + return name; + } + } + }; + var setValue = function(name, value) { + var elm; + var valueName = getValueName(name); + if (!valueName) + return; + if (valueName.data) { + item.elm.setAttribute('data-'+valueName.data, value); + } else if (valueName.attr && valueName.name) { + elm = list.utils.getByClass(item.elm, valueName.name, true); + if (elm) { + elm.setAttribute(valueName.attr, value); + } + } else { + elm = list.utils.getByClass(item.elm, valueName, true); + if (elm) { + elm.innerHTML = value; + } + } + elm = undefined; + }; + if (!templater.create(item)) { + for(var v in values) { + if (values.hasOwnProperty(v)) { + setValue(v, values[v]); + } + } + } + }; + + this.create = function(item) { + if (item.elm !== undefined) { + return false; + } + if (itemSource === undefined) { + throw new Error("The list need to have at list one item on init otherwise you'll have to add a template."); + } + /* If item source does not exists, use the first item in list as + source for new items */ + var newItem = itemSource.cloneNode(true); + newItem.removeAttribute('id'); + item.elm = newItem; + templater.set(item, item.values()); + return true; + }; + this.remove = function(item) { + if (item.elm.parentNode === list.list) { + list.list.removeChild(item.elm); + } + }; + this.show = function(item) { + templater.create(item); + list.list.appendChild(item.elm); + }; + this.hide = function(item) { + if (item.elm !== undefined && item.elm.parentNode === list.list) { + list.list.removeChild(item.elm); + } + }; + this.clear = function() { + /* .innerHTML = ''; fucks up IE */ + if (list.list.hasChildNodes()) { + while (list.list.childNodes.length >= 1) + { + list.list.removeChild(list.list.firstChild); + } + } + }; + + init(); +}; + +module.exports = function(list) { + return new Templater(list); +}; + + +/***/ }), +/* 17 */ +/***/ (function(module, exports) { + +/** + * A cross-browser implementation of getAttribute. + * Source found here: http://stackoverflow.com/a/3755343/361337 written by Vivin Paliath + * + * Return the value for `attr` at `element`. + * + * @param {Element} el + * @param {String} attr + * @api public + */ + +module.exports = function(el, attr) { + var result = (el.getAttribute && el.getAttribute(attr)) || null; + if( !result ) { + var attrs = el.attributes; + var length = attrs.length; + for(var i = 0; i < length; i++) { + if (attr[i] !== undefined) { + if(attr[i].nodeName === attr) { + result = attr[i].nodeValue; + } + } + } + } + return result; +}; + + +/***/ }), +/* 18 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var alphabet; +var alphabetIndexMap; +var alphabetIndexMapLength = 0; + +function isNumberCode(code) { + return code >= 48 && code <= 57; +} + +function naturalCompare(a, b) { + var lengthA = (a += '').length; + var lengthB = (b += '').length; + var aIndex = 0; + var bIndex = 0; + + while (aIndex < lengthA && bIndex < lengthB) { + var charCodeA = a.charCodeAt(aIndex); + var charCodeB = b.charCodeAt(bIndex); + + if (isNumberCode(charCodeA)) { + if (!isNumberCode(charCodeB)) { + return charCodeA - charCodeB; + } + + var numStartA = aIndex; + var numStartB = bIndex; + + while (charCodeA === 48 && ++numStartA < lengthA) { + charCodeA = a.charCodeAt(numStartA); + } + while (charCodeB === 48 && ++numStartB < lengthB) { + charCodeB = b.charCodeAt(numStartB); + } + + var numEndA = numStartA; + var numEndB = numStartB; + + while (numEndA < lengthA && isNumberCode(a.charCodeAt(numEndA))) { + ++numEndA; + } + while (numEndB < lengthB && isNumberCode(b.charCodeAt(numEndB))) { + ++numEndB; + } + + var difference = numEndA - numStartA - numEndB + numStartB; // numA length - numB length + if (difference) { + return difference; + } + + while (numStartA < numEndA) { + difference = a.charCodeAt(numStartA++) - b.charCodeAt(numStartB++); + if (difference) { + return difference; + } + } + + aIndex = numEndA; + bIndex = numEndB; + continue; + } + + if (charCodeA !== charCodeB) { + if ( + charCodeA < alphabetIndexMapLength && + charCodeB < alphabetIndexMapLength && + alphabetIndexMap[charCodeA] !== -1 && + alphabetIndexMap[charCodeB] !== -1 + ) { + return alphabetIndexMap[charCodeA] - alphabetIndexMap[charCodeB]; + } + + return charCodeA - charCodeB; + } + + ++aIndex; + ++bIndex; + } + + return lengthA - lengthB; +} + +naturalCompare.caseInsensitive = naturalCompare.i = function(a, b) { + return naturalCompare(('' + a).toLowerCase(), ('' + b).toLowerCase()); +}; + +Object.defineProperties(naturalCompare, { + alphabet: { + get: function() { + return alphabet; + }, + set: function(value) { + alphabet = value; + alphabetIndexMap = []; + var i = 0; + if (alphabet) { + for (; i < alphabet.length; i++) { + alphabetIndexMap[alphabet.charCodeAt(i)] = i; + } + } + alphabetIndexMapLength = alphabetIndexMap.length; + for (i = 0; i < alphabetIndexMapLength; i++) { + if (alphabetIndexMap[i] === undefined) { + alphabetIndexMap[i] = -1; + } + } + }, + }, +}); + +module.exports = naturalCompare; + + +/***/ }), +/* 19 */ +/***/ (function(module, exports) { + +module.exports = function(text, pattern, options) { + // Aproximately where in the text is the pattern expected to be found? + var Match_Location = options.location || 0; + + //Determines how close the match must be to the fuzzy location (specified above). An exact letter match which is 'distance' characters away from the fuzzy location would score as a complete mismatch. A distance of '0' requires the match be at the exact location specified, a threshold of '1000' would require a perfect match to be within 800 characters of the fuzzy location to be found using a 0.8 threshold. + var Match_Distance = options.distance || 100; + + // At what point does the match algorithm give up. A threshold of '0.0' requires a perfect match (of both letters and location), a threshold of '1.0' would match anything. + var Match_Threshold = options.threshold || 0.4; + + if (pattern === text) return true; // Exact match + if (pattern.length > 32) return false; // This algorithm cannot be used + + // Set starting location at beginning text and initialise the alphabet. + var loc = Match_Location, + s = (function() { + var q = {}, + i; + + for (i = 0; i < pattern.length; i++) { + q[pattern.charAt(i)] = 0; + } + + for (i = 0; i < pattern.length; i++) { + q[pattern.charAt(i)] |= 1 << (pattern.length - i - 1); + } + + return q; + }()); + + // Compute and return the score for a match with e errors and x location. + // Accesses loc and pattern through being a closure. + + function match_bitapScore_(e, x) { + var accuracy = e / pattern.length, + proximity = Math.abs(loc - x); + + if (!Match_Distance) { + // Dodge divide by zero error. + return proximity ? 1.0 : accuracy; + } + return accuracy + (proximity / Match_Distance); + } + + var score_threshold = Match_Threshold, // Highest score beyond which we give up. + best_loc = text.indexOf(pattern, loc); // Is there a nearby exact match? (speedup) + + if (best_loc != -1) { + score_threshold = Math.min(match_bitapScore_(0, best_loc), score_threshold); + // What about in the other direction? (speedup) + best_loc = text.lastIndexOf(pattern, loc + pattern.length); + + if (best_loc != -1) { + score_threshold = Math.min(match_bitapScore_(0, best_loc), score_threshold); + } + } + + // Initialise the bit arrays. + var matchmask = 1 << (pattern.length - 1); + best_loc = -1; + + var bin_min, bin_mid; + var bin_max = pattern.length + text.length; + var last_rd; + for (var d = 0; d < pattern.length; d++) { + // Scan for the best match; each iteration allows for one more error. + // Run a binary search to determine how far from 'loc' we can stray at this + // error level. + bin_min = 0; + bin_mid = bin_max; + while (bin_min < bin_mid) { + if (match_bitapScore_(d, loc + bin_mid) <= score_threshold) { + bin_min = bin_mid; + } else { + bin_max = bin_mid; + } + bin_mid = Math.floor((bin_max - bin_min) / 2 + bin_min); + } + // Use the result from this iteration as the maximum for the next. + bin_max = bin_mid; + var start = Math.max(1, loc - bin_mid + 1); + var finish = Math.min(loc + bin_mid, text.length) + pattern.length; + + var rd = Array(finish + 2); + rd[finish + 1] = (1 << d) - 1; + for (var j = finish; j >= start; j--) { + // The alphabet (s) is a sparse hash, so the following line generates + // warnings. + var charMatch = s[text.charAt(j - 1)]; + if (d === 0) { // First pass: exact match. + rd[j] = ((rd[j + 1] << 1) | 1) & charMatch; + } else { // Subsequent passes: fuzzy match. + rd[j] = (((rd[j + 1] << 1) | 1) & charMatch) | + (((last_rd[j + 1] | last_rd[j]) << 1) | 1) | + last_rd[j + 1]; + } + if (rd[j] & matchmask) { + var score = match_bitapScore_(d, j - 1); + // This match will almost certainly be better than any existing match. + // But check anyway. + if (score <= score_threshold) { + // Told you so. + score_threshold = score; + best_loc = j - 1; + if (best_loc > loc) { + // When passing loc, don't exceed our current distance from loc. + start = Math.max(1, 2 * loc - best_loc); + } else { + // Already passed loc, downhill from here on in. + break; + } + } + } + } + // No hope for a (better) match at greater error levels. + if (match_bitapScore_(d + 1, loc) > score_threshold) { + break; + } + last_rd = rd; + } + + return (best_loc < 0) ? false : true; +}; + + +/***/ }) +/******/ ]); \ No newline at end of file From 25e1b3ea5a517646d7a4091d64897bcc86ade826 Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Sun, 21 Oct 2018 20:34:12 +0700 Subject: [PATCH 02/34] add twbsPagination.js jquery plugin add a jquery plugin for pagination. https://github.com/josecebe/twbs-pagination/ --- common/js/jquery.twbsPagination.js | 364 +++++++++++++++++++++++++++++ 1 file changed, 364 insertions(+) create mode 100644 common/js/jquery.twbsPagination.js diff --git a/common/js/jquery.twbsPagination.js b/common/js/jquery.twbsPagination.js new file mode 100644 index 000000000..2451a6109 --- /dev/null +++ b/common/js/jquery.twbsPagination.js @@ -0,0 +1,364 @@ +/*! + * jQuery pagination plugin v1.4.2 + * http://josecebe.github.io/twbs-pagination/ + * + * Copyright 2014-2018, Eugene Simakin + * Released under Apache 2.0 license + * http://apache.org/licenses/LICENSE-2.0.html + */ +(function ($, window, document, undefined) { + + 'use strict'; + + var old = $.fn.twbsPagination; + + // PROTOTYPE AND CONSTRUCTOR + + var TwbsPagination = function (element, options) { + this.$element = $(element); + this.options = $.extend({}, $.fn.twbsPagination.defaults, options); + + if (this.options.startPage < 1 || this.options.startPage > this.options.totalPages) { + throw new Error('Start page option is incorrect'); + } + + this.options.totalPages = parseInt(this.options.totalPages); + if (isNaN(this.options.totalPages)) { + throw new Error('Total pages option is not correct!'); + } + + this.options.visiblePages = parseInt(this.options.visiblePages); + if (isNaN(this.options.visiblePages)) { + throw new Error('Visible pages option is not correct!'); + } + + if (this.options.beforePageClick instanceof Function) { + this.$element.first().on('beforePage', this.options.beforePageClick); + } + + if (this.options.onPageClick instanceof Function) { + this.$element.first().on('page', this.options.onPageClick); + } + + // hide if only one page exists + if (this.options.hideOnlyOnePage && this.options.totalPages == 1) { + if (this.options.initiateStartPageClick) { + this.$element.trigger('page', 1); + } + return this; + } + + if (this.options.href) { + this.options.startPage = this.getPageFromQueryString(); + if (!this.options.startPage) { + this.options.startPage = 1; + } + } + + var tagName = (typeof this.$element.prop === 'function') ? + this.$element.prop('tagName') : this.$element.attr('tagName'); + + if (tagName === 'UL') { + this.$listContainer = this.$element; + } else { + var elements = this.$element; + var $newListContainer = $([]); + elements.each(function(index) { + var $newElem = $("
      "); + $(this).append($newElem); + $newListContainer.push($newElem[0]); + }); + this.$listContainer = $newListContainer; + this.$element = $newListContainer; + } + + this.$listContainer.addClass(this.options.paginationClass); + + if (this.options.initiateStartPageClick) { + this.show(this.options.startPage); + } else { + this.currentPage = this.options.startPage; + this.render(this.getPages(this.options.startPage)); + this.setupEvents(); + } + + return this; + }; + + TwbsPagination.prototype = { + + constructor: TwbsPagination, + + destroy: function () { + this.$element.empty(); + this.$element.removeData('twbs-pagination'); + this.$element.off('page'); + + return this; + }, + + show: function (page) { + if (page < 1 || page > this.options.totalPages) { + throw new Error('Page is incorrect.'); + } + this.currentPage = page; + + this.$element.trigger('beforePage', page); + + var pages = this.getPages(page); + this.render(pages); + this.setupEvents(); + + this.$element.trigger('page', page); + + return pages; + }, + + enable: function () { + this.show(this.currentPage); + }, + + disable: function () { + var _this = this; + this.$listContainer.off('click').on('click', 'li', function (evt) { + evt.preventDefault(); + }); + this.$listContainer.children().each(function () { + var $this = $(this); + if (!$this.hasClass(_this.options.activeClass)) { + $(this).addClass(_this.options.disabledClass); + } + }); + }, + + buildListItems: function (pages) { + var listItems = []; + + if (this.options.first) { + listItems.push(this.buildItem('first', 1)); + } + + if (this.options.prev) { + var prev = pages.currentPage > 1 ? pages.currentPage - 1 : this.options.loop ? this.options.totalPages : 1; + listItems.push(this.buildItem('prev', prev)); + } + + for (var i = 0; i < pages.numeric.length; i++) { + listItems.push(this.buildItem('page', pages.numeric[i])); + } + + if (this.options.next) { + var next = pages.currentPage < this.options.totalPages ? pages.currentPage + 1 : this.options.loop ? 1 : this.options.totalPages; + listItems.push(this.buildItem('next', next)); + } + + if (this.options.last) { + listItems.push(this.buildItem('last', this.options.totalPages)); + } + + return listItems; + }, + + buildItem: function (type, page) { + var $itemContainer = $('
    • '), + $itemContent = $(''), + itemText = this.options[type] ? this.makeText(this.options[type], page) : page; + + $itemContainer.addClass(this.options[type + 'Class']); + $itemContainer.data('page', page); + $itemContainer.data('page-type', type); + $itemContainer.append($itemContent.attr('href', this.makeHref(page)).addClass(this.options.anchorClass).html(itemText)); + + return $itemContainer; + }, + + getPages: function (currentPage) { + var pages = []; + + var half = Math.floor(this.options.visiblePages / 2); + var start = currentPage - half + 1 - this.options.visiblePages % 2; + var end = currentPage + half; + + var visiblePages = this.options.visiblePages; + if (visiblePages > this.options.totalPages) { + visiblePages = this.options.totalPages; + } + + // handle boundary case + if (start <= 0) { + start = 1; + end = visiblePages; + } + if (end > this.options.totalPages) { + start = this.options.totalPages - visiblePages + 1; + end = this.options.totalPages; + } + + var itPage = start; + while (itPage <= end) { + pages.push(itPage); + itPage++; + } + + return {"currentPage": currentPage, "numeric": pages}; + }, + + render: function (pages) { + var _this = this; + this.$listContainer.children().remove(); + var items = this.buildListItems(pages); + $.each(items, function(key, item){ + _this.$listContainer.append(item); + }); + + this.$listContainer.children().each(function () { + var $this = $(this), + pageType = $this.data('page-type'); + + switch (pageType) { + case 'page': + if ($this.data('page') === pages.currentPage) { + $this.addClass(_this.options.activeClass); + } + break; + case 'first': + $this.toggleClass(_this.options.disabledClass, pages.currentPage === 1); + break; + case 'last': + $this.toggleClass(_this.options.disabledClass, pages.currentPage === _this.options.totalPages); + break; + case 'prev': + $this.toggleClass(_this.options.disabledClass, !_this.options.loop && pages.currentPage === 1); + break; + case 'next': + $this.toggleClass(_this.options.disabledClass, + !_this.options.loop && pages.currentPage === _this.options.totalPages); + break; + default: + break; + } + + }); + }, + + setupEvents: function () { + var _this = this; + this.$listContainer.off('click').on('click', 'li', function (evt) { + var $this = $(this); + if ($this.hasClass(_this.options.disabledClass) || $this.hasClass(_this.options.activeClass)) { + return false; + } + // Prevent click event if href is not set. + !_this.options.href && evt.preventDefault(); + _this.show(parseInt($this.data('page'))); + }); + }, + + changeTotalPages: function(totalPages, currentPage) { + this.options.totalPages = totalPages; + return this.show(currentPage); + }, + + makeHref: function (page) { + return this.options.href ? this.generateQueryString(page) : "#"; + }, + + makeText: function (text, page) { + return text.replace(this.options.pageVariable, page) + .replace(this.options.totalPagesVariable, this.options.totalPages) + }, + + getPageFromQueryString: function (searchStr) { + var search = this.getSearchString(searchStr), + regex = new RegExp(this.options.pageVariable + '(=([^&#]*)|&|#|$)'), + page = regex.exec(search); + if (!page || !page[2]) { + return null; + } + page = decodeURIComponent(page[2]); + page = parseInt(page); + if (isNaN(page)) { + return null; + } + return page; + }, + + generateQueryString: function (pageNumber, searchStr) { + var search = this.getSearchString(searchStr), + regex = new RegExp(this.options.pageVariable + '=*[^&#]*'); + if (!search) return ''; + return '?' + search.replace(regex, this.options.pageVariable + '=' + pageNumber); + }, + + getSearchString: function (searchStr) { + var search = searchStr || window.location.search; + if (search === '') { + return null; + } + if (search.indexOf('?') === 0) search = search.substr(1); + return search; + }, + + getCurrentPage: function () { + return this.currentPage; + }, + + getTotalPages: function () { + return this.options.totalPages; + } + }; + + // PLUGIN DEFINITION + + $.fn.twbsPagination = function (option) { + var args = Array.prototype.slice.call(arguments, 1); + var methodReturn; + + var $this = $(this); + var data = $this.data('twbs-pagination'); + var options = typeof option === 'object' ? option : {}; + + if (!data) $this.data('twbs-pagination', (data = new TwbsPagination(this, options) )); + if (typeof option === 'string') methodReturn = data[ option ].apply(data, args); + + return ( methodReturn === undefined ) ? $this : methodReturn; + }; + + $.fn.twbsPagination.defaults = { + totalPages: 1, + startPage: 1, + visiblePages: 5, + initiateStartPageClick: true, + hideOnlyOnePage: false, + href: false, + pageVariable: '{{page}}', + totalPagesVariable: '{{total_pages}}', + page: null, + first: 'First', + prev: 'Previous', + next: 'Next', + last: 'Last', + loop: false, + beforePageClick: null, + onPageClick: null, + paginationClass: 'pagination', + nextClass: 'page-item next', + prevClass: 'page-item prev', + lastClass: 'page-item last', + firstClass: 'page-item first', + pageClass: 'page-item', + activeClass: 'active', + disabledClass: 'disabled', + anchorClass: 'page-link' + }; + + $.fn.twbsPagination.Constructor = TwbsPagination; + + $.fn.twbsPagination.noConflict = function () { + $.fn.twbsPagination = old; + return this; + }; + + $.fn.twbsPagination.version = "1.4.2"; + +})(window.jQuery, window, document); From 7e59f7790ba81c6d3e2e447f47ff5bced25fbb36 Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Sun, 21 Oct 2018 20:36:25 +0700 Subject: [PATCH 03/34] Turned off saving users in user-groups Turned off the users saved in user-groups. Making '$users' parameter in update_usergroup function default to null --- modules/user-groups/user-groups.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/user-groups/user-groups.php b/modules/user-groups/user-groups.php index e85fa9ff6..2dc0331c9 100644 --- a/modules/user-groups/user-groups.php +++ b/modules/user-groups/user-groups.php @@ -384,9 +384,11 @@ function handle_edit_usergroup() { 'description' => $description, ); // Gracefully handle the case where all users have been unsubscribed from the user group - $users = isset( $_POST['usergroup_users'] ) ? (array)$_POST['usergroup_users'] : array(); - $users = array_map( 'intval', $users ); - $usergroup = $this->update_usergroup( $existing_usergroup->term_id, $args, $users ); +// $users = isset( $_POST['usergroup_users'] ) ? (array)$_POST['usergroup_users'] : array(); +// $users = array_map( 'intval', $users ); +// $users = null; +// $usergroup = $this->update_usergroup( $existing_usergroup->term_id, $args, $users ); + $usergroup = $this->update_usergroup( $existing_usergroup->term_id, $args ); if ( is_wp_error( $usergroup ) ) wp_die( __( 'Error updating user group.', 'edit-flow' ) ); From 2a87bb1b4bbf58e3ba1f062557584e869ec8701f Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Sun, 21 Oct 2018 20:37:05 +0700 Subject: [PATCH 04/34] Register list.js and twbsPagination --- edit_flow.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/edit_flow.php b/edit_flow.php index 6e6024e32..45f01ad9a 100644 --- a/edit_flow.php +++ b/edit_flow.php @@ -375,6 +375,10 @@ function register_scripts_and_styles() { wp_register_script( 'jquery-quicksearch', EDIT_FLOW_URL . 'common/js/jquery.quicksearch.js', array( 'jquery' ), EDIT_FLOW_VERSION, true ); + + wp_register_script( 'list', EDIT_FLOW_URL . 'common/js/list.js', false, EDIT_FLOW_VERSION, true); + wp_register_script( 'jquery-twbsPagination', EDIT_FLOW_URL . 'common/js/jquery.twbsPagination.js', array('jquery'), EDIT_FLOW_VERSION, true); + } } From edce914d25d31fdffe0da54c0e0ad69a27092a68 Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Sun, 21 Oct 2018 20:40:27 +0700 Subject: [PATCH 05/34] Made the users list in notification paginated In this commit the users list is redefined using list.js and twbsPagination. Mainly using DOM modification triggered by ajax calls. --- modules/notifications/lib/notifications.js | 196 ++++++++++++++++++++- modules/notifications/notifications.php | 164 ++++++++++++++++- 2 files changed, 350 insertions(+), 10 deletions(-) diff --git a/modules/notifications/lib/notifications.js b/modules/notifications/lib/notifications.js index a611f3486..a3bba77e0 100644 --- a/modules/notifications/lib/notifications.js +++ b/modules/notifications/lib/notifications.js @@ -1,5 +1,5 @@ jQuery(document).ready(function($) { - $('#ef-post_following_users_box ul').listFilterizer(); + // $('#ef-post_following_users_box ul').listFilterizer(); var params = { action: 'save_notifications', @@ -29,6 +29,7 @@ jQuery(document).ready(function($) { data : params, success : function(x) { + console.log(params); // This event is used to show an updated list of who will be notified of editorial comments and status updates. $( '#ef-post_following_box' ).trigger( 'following_list_updated' ); @@ -42,4 +43,197 @@ jQuery(document).ready(function($) { } }); }); + + //// Users list for notifications meta + + // Options for the list + var options = { + // values used for filters + valueNames: [ 'user-item-name', 'user-item-email', { name: 'user_checked', attr: ''}, {data: ['user-item-id']} ], + + // searchClass is used for filtering values in the list + searchClass: 'filter-users', + + // item used for user list template + item: '
    • ' + }; + + // Initialize the list.js, 'users' is the html class name to fill in the users list + var userList = new List('users', options); + var usersPerPage = 10; + var totalUsers = 0; + + // Fill the initial users list on document load + function initiateUsersList() { + + //// Retrieve total user counts for pagination numbering + // Data sent to WP through ajax for user counts + var data_user_count = { + action: 'retrieve_users', + nonce: ajax_object.ajax_nonce, + count_users: true + }; + + jQuery.post(ajax_object.ajax_url, data_user_count) + .done( function (response) { + totalUsers = parseInt(response); + fillPaginatedUsersList(totalUsers, usersPerPage, ''); + }) + .fail( function (xhr, status, error) { + $('#ef-post_following_users_box').prev().append('

      There was an error. Please reload the page.

      '); + }); + + } + function fillPaginatedUsersList(totalUsers, usersPerPage, searchKeyword){ + + // remove pagination if it existed + if($('#users-pagination').data("twbs-pagination")){ + $('#users-pagination').twbsPagination('destroy'); + } + + $('#users-pagination').twbsPagination({ + totalPages: Math.ceil(totalUsers/usersPerPage), // The total number of user pages + visiblePages: usersPerPage, // Number of users displayed in a page + next: 'Next', + prev: 'Prev', + onPageClick: function (event, page) { + + // clear the users list when the page created + userList.clear(); + + // Data sent to WP through ajax for paginated users list + var data = { + action: 'retrieve_users', + post_id: $('#post_ID').val(), + page: page, + users_per_page: usersPerPage, + nonce: ajax_object.ajax_nonce, + search_keyword: searchKeyword, + count_users: false + }; + + jQuery.post(ajax_object.ajax_url, data, function (response) { + // Add the users retrieved from wordpress db to list + for (var user of response.users){ + userList.add(user); + if(user.user_checked){ + $('li[data-user-item-id='+user['user-item-id']+'] input:checkbox').prop("checked", true); + } + } + + // Fill in users count info + $('.users-total-info-value').text(totalUsers); + if (searchKeyword !== ''){ + $('.users-total-info-text').text('Totals users found'); + } + + }); + + } + }); + } + + function fillUsersListByKeyword(searchKeyword){ + //// Retrieve total user counts for pagination numbering + // Data sent to WP through ajax for user counts + var data_user_count = { + action: 'retrieve_users', + nonce: ajax_object.ajax_nonce, + count_users: true, + search_keyword: searchKeyword + }; + + jQuery.post(ajax_object.ajax_url, data_user_count, function (response) { + + totalUsers = parseInt(response); + + if(totalUsers > 0) { + fillPaginatedUsersList(totalUsers, usersPerPage, searchKeyword); + } else { + $('#users-pagination').twbsPagination('destroy'); + $('.users-total-info-text').text('Totals users found'); + $('.users-total-info-value').text(totalUsers); + + } + }); + } + + $('.search-users').bind('keypress', function(e){ + if(e.keyCode == 13) { + clearTimeout($.data(this, 'timer')); + + e.preventDefault(); + var searchKeyword = $('.search-users').val(); + userList.clear(); + + var wait = setTimeout(fillUsersListByKeyword(searchKeyword), 10000); + + $(this).data('timer', wait); + + } + }); + + $('.btn-search-users').click(function (e) { + clearTimeout($.data(this, 'timer')); + + e.preventDefault(); + var searchKeyword = $('.search-users').val(); + userList.clear(); + + var wait = setTimeout(fillUsersListByKeyword(searchKeyword), 10000); + + $(this).data('timer', wait); + + }); + + $(document).on('click', '.user-item', function (e) { + + var item_element = $(this); + var checkbox = item_element.find("input[type='checkbox']"); + var user_group_ids = []; + + + // check the checkbox when .user-item element is clicked + if (!$(e.target).is(':checkbox') && !checkbox.is(':checked')) { + checkbox.attr('checked', true); + } else if ((!$(e.target).is(':checkbox') && checkbox.is(':checked'))){ + checkbox.attr('checked', false); + } + + params.ef_notifications_name = 'ef-selected-users[]'; + params._nonce = $("#ef_notifications_nonce").val(); + user_group_ids.push($(this).data('user-item-id')); + params.user_group_ids = user_group_ids; + + console.log(params); + console.log($(this).find('input').is(':checked')); + + if (checkbox.is(':checked')){ + params.follow = true; + } else { + params.follow = false; + } + + jQuery.post(ajaxurl, params) + .done( function (response) { + console.log(params); + // This event is used to show an updated list of who will be notified of editorial comments and status updates. + $( '#ef-post_following_box' ).trigger( 'following_list_updated' ); + + + // Trigger visual effect when ajax successful + var backgroundColor = item_element.parent().css( 'background-color' ); + item_element + .animate( { 'backgroundColor':'#CCEEBB' }, 200 ) + .animate( { 'backgroundColor':backgroundColor }, 200 ); + }) + .fail( function (xhr, status, error) { + $('#ef-post_following_users_box').prev().append('

      There was an error. Please reload the page.

      '); + }); + + + }); + + initiateUsersList(); + }); \ No newline at end of file diff --git a/modules/notifications/notifications.php b/modules/notifications/notifications.php index 8bc794590..4825644ea 100644 --- a/modules/notifications/notifications.php +++ b/modules/notifications/notifications.php @@ -100,7 +100,12 @@ function init() { //Ajax for saving notifiction updates add_action( 'wp_ajax_save_notifications', array( $this, 'ajax_save_post_subscriptions' ) ); add_action( 'wp_ajax_ef_notifications_user_post_subscription', array( $this, 'handle_user_post_subscription' ) ); - + + //Ajax for retrieving users + add_action('wp_ajax_retrieve_users', array($this, 'ajax_retrieve_users')); + + //Ajax for retrieving users count + add_action('wp_ajax_retrieve_users_count', array($this, 'ajax_retrieve_users_count')); } /** @@ -191,6 +196,16 @@ function enqueue_admin_scripts() { wp_enqueue_script( 'jquery-listfilterizer' ); wp_enqueue_script( 'jquery-quicksearch' ); wp_enqueue_script( 'edit-flow-notifications-js', $this->module_url . 'lib/notifications.js', array( 'jquery', 'jquery-listfilterizer', 'jquery-quicksearch' ), EDIT_FLOW_VERSION, true ); + + wp_enqueue_script( 'list'); + wp_enqueue_script( 'jquery-twbsPagination'); + + + wp_localize_script( 'edit-flow-notifications-js', 'ajax_object', + array( 'ajax_url' => admin_url( 'admin-ajax.php' ), + 'ajax_nonce' => wp_create_nonce( "edit-flow-users-list-ajax" ) + ) + ); } } @@ -336,7 +351,8 @@ function notifications_meta_box() { $select_form_args = array( 'list_class' => 'ef-post_following_list', ); - $this->users_select_form( $followers, $select_form_args ); ?> +// $this->users_select_form( $followers, $select_form_args ); + $this->users_list(); ?> module_enabled( 'user_groups' ) && in_array( $this->get_current_post_type(), $this->get_post_types_for_module( $edit_flow->user_groups->module ) ) ): ?> @@ -354,7 +370,133 @@ function notifications_meta_box() { +
      + + + + + + + + + + + + + + + + + +
      + Total users + +
      + +
        + +
          +
          + 'authors', + ); + + $users_count = count(get_users($args)); + + wp_send_json($users_count); + + } + + /* + * Ajax processing for retrieving users + */ + function ajax_retrieve_users(){ + + $post_id = isset( $_POST['post_id'] ) ? intval($_POST['post_id']) : 0; + $selected = $this->get_following_users( $post_id, 'id' ); + + + $search_keyword = isset( $_POST['search_keyword']) ? sanitize_text_field($_POST['search_keyword']) : ''; +// $search_keyword = 'jon'; +// wp_send_json('*' . $search_keyword .'*'); + + $users_per_page = isset( $_POST['users_per_page']) ? intval($_POST['users_per_page']) : 0; + $page = isset( $_POST['page']) ? intval($_POST['page']) : 0; + $offset = $users_per_page * ($page - 1); + + $args = array( + 'number' => $users_per_page, + 'offset' => $offset, + 'who' => 'authors', + 'fields' => array( + 'ID', + 'display_name', + 'user_email' + ), + 'orderby' => 'display_name', + 'search' => '*' . $search_keyword .'*', + 'search_columns' => array('display_name', 'user_email'), +// 'include' => $selected + ); + + $usersQuery = new WP_User_Query($args); + + $count_users = isset( $_POST['count_users']) ? filter_var($_POST['count_users'], FILTER_VALIDATE_BOOLEAN) : false; + if($count_users){ + $users_count = $usersQuery->get_total(); + wp_send_json($users_count); + } + + $users = $usersQuery->get_results(); + + + if ( ! is_array($selected)){ + $selected = array(); + } + + // Compile users with selected users on top of the list + $users_with_selection = array(); + $selected_users = array(); + $unselected_users = array(); + + foreach ($users as $user){ + + $user_arr['user-item-id'] = $user->ID; + $user_arr['user-item-name'] = $user->display_name; + $user_arr['user-item-email'] = $user->user_email; + + if ( in_array($user->ID, $selected) ){ + $user_arr['user_checked'] = true; +// array_push($selected_users, $user_arr); + } else { + $user_arr['user_checked'] = false; +// array_push($unselected_users, $user_arr); + } + + array_push($users_with_selection, $user_arr); + } + +// $users_with_selection = array_merge($selected_users, $unselected_users); + + + wp_send_json(['users' => $users_with_selection, 'users_total' => $usersQuery->get_total()]); + + } + /** * Called when a notification editorial metadata checkbox is checked. Handles saving of a user/usergroup to a post. */ @@ -380,7 +522,8 @@ function ajax_save_post_subscriptions() { } if ( 'ef-selected-users[]' === $_POST['ef_notifications_name'] ) { - $this->save_post_following_users( $post, $user_group_ids ); + $follow = isset( $_POST['follow'] ) ? filter_var($_POST['follow'], FILTER_VALIDATE_BOOLEAN) : true; + $this->save_post_following_users( $post, $user_group_ids, $follow ); } $groups_enabled = $this->module_enabled( 'user_groups' ) && in_array( get_post_type( $post_id ), $this->get_post_types_for_module( $edit_flow->user_groups->module ) ); @@ -444,7 +587,7 @@ function save_post_subscriptions( $new_status, $old_status, $post ) { * * @param int $post ID of the post */ - function save_post_following_users( $post, $users = null ) { + function save_post_following_users( $post, $users = null, $follow = true ) { if( !is_array( $users ) ) $users = array(); @@ -459,8 +602,11 @@ function save_post_following_users( $post, $users = null ) { $users = array_unique( array_map( 'intval', $users ) ); - $follow = $this->follow_post_user( $post, $users, false ); - + if ( $follow ) { + $this->follow_post_user( $post, $users, true ); + } else { + $this->unfollow_post_user($post, $users[0]); + } } /** @@ -475,8 +621,8 @@ function save_post_following_usergroups( $post, $usergroups = null ) { $usergroups = array_map( 'intval', $usergroups ); $follow = $this->follow_post_usergroups($post, $usergroups, false); - } - + } + /** * Set up and send post status change notification email */ From cd7ed0a3a1282116d0cdd7533c83445dd37017b3 Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Sun, 21 Oct 2018 20:46:16 +0700 Subject: [PATCH 06/34] Styling users list --- common/css/edit-flow-admin.css | 50 ++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/common/css/edit-flow-admin.css b/common/css/edit-flow-admin.css index 4cd35b711..768fc8682 100644 --- a/common/css/edit-flow-admin.css +++ b/common/css/edit-flow-admin.css @@ -20,3 +20,53 @@ display: block; } +/* +Users list style + */ + +.list { + margin: 0; +} + +.pagination li { + display:inline-block; + padding:5px; +} + +.user-item { + display: block; + padding: 10px 5px 5px 5px; + margin: 0; + border-bottom: 1px solid #ccc; +} + +.user-item:hover { + background: #EAF2FA; +} + +.user-item-name { + display: block; + font-size: 14px; + margin: 0; +} + +.user-item-email { + display: block; + color: #ccc; + font-size: 12px; + margin: 0; +} + +.user-item input { + float: right; +} + +.users-list-infos { + text-align: right; + display: block; + border-bottom: 1px solid #ccc; +} + +.users-total-info-value{ + font-weight: bold; +} \ No newline at end of file From eb402fb1395836acbcbf1652e24bdbf0d35d9a26 Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Sun, 21 Oct 2018 22:32:43 +0700 Subject: [PATCH 07/34] Put the users list template in class-module The users list template should be able to be accessed in notifications and user-groups. In class-module this can be done. --- common/php/class-module.php | 36 +++++++++++++++++++++++++ modules/notifications/notifications.php | 33 ----------------------- 2 files changed, 36 insertions(+), 33 deletions(-) diff --git a/common/php/class-module.php b/common/php/class-module.php index dff2dd17c..557d6d7cb 100755 --- a/common/php/class-module.php +++ b/common/php/class-module.php @@ -483,6 +483,42 @@ function users_select_form( $selected = null, $args = null ) { +
          + + + + + + + + + + + + + + + + + +
          + Total users + +
          + +
            + +
              +
              + -
              - - - - - - - - - - - - - - - - - -
              - Total users - -
              - -
                - -
                  -
                  - Date: Sun, 21 Oct 2018 22:33:07 +0700 Subject: [PATCH 08/34] Remove unused ajax endpoint --- modules/notifications/notifications.php | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/modules/notifications/notifications.php b/modules/notifications/notifications.php index 9aa70bba4..9195c8d64 100644 --- a/modules/notifications/notifications.php +++ b/modules/notifications/notifications.php @@ -371,23 +371,6 @@ function notifications_meta_box() { 'authors', - ); - - $users_count = count(get_users($args)); - - wp_send_json($users_count); - - } - /* * Ajax processing for retrieving users */ From fcec270e331fb4c5bca27ffcb3c107121d2defc5 Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Sun, 21 Oct 2018 22:50:06 +0700 Subject: [PATCH 09/34] cleanup commented codes --- modules/notifications/notifications.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/modules/notifications/notifications.php b/modules/notifications/notifications.php index 9195c8d64..f76bee222 100644 --- a/modules/notifications/notifications.php +++ b/modules/notifications/notifications.php @@ -379,10 +379,7 @@ function ajax_retrieve_users(){ $post_id = isset( $_POST['post_id'] ) ? intval($_POST['post_id']) : 0; $selected = $this->get_following_users( $post_id, 'id' ); - $search_keyword = isset( $_POST['search_keyword']) ? sanitize_text_field($_POST['search_keyword']) : ''; -// $search_keyword = 'jon'; -// wp_send_json('*' . $search_keyword .'*'); $users_per_page = isset( $_POST['users_per_page']) ? intval($_POST['users_per_page']) : 0; $page = isset( $_POST['page']) ? intval($_POST['page']) : 0; @@ -420,8 +417,6 @@ function ajax_retrieve_users(){ // Compile users with selected users on top of the list $users_with_selection = array(); - $selected_users = array(); - $unselected_users = array(); foreach ($users as $user){ @@ -431,18 +426,13 @@ function ajax_retrieve_users(){ if ( in_array($user->ID, $selected) ){ $user_arr['user_checked'] = true; -// array_push($selected_users, $user_arr); } else { $user_arr['user_checked'] = false; -// array_push($unselected_users, $user_arr); } array_push($users_with_selection, $user_arr); } -// $users_with_selection = array_merge($selected_users, $unselected_users); - - wp_send_json(['users' => $users_with_selection, 'users_total' => $usersQuery->get_total()]); } From 8d9ee11b289f7562a1a55a6d8ab4ecf19cb6c80e Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Sun, 21 Oct 2018 22:51:37 +0700 Subject: [PATCH 10/34] put a check on notifications.js put a check on the javascript so it only run on post creation/edit --- modules/notifications/lib/notifications.js | 398 +++++++++++---------- 1 file changed, 204 insertions(+), 194 deletions(-) diff --git a/modules/notifications/lib/notifications.js b/modules/notifications/lib/notifications.js index a3bba77e0..fdc207efa 100644 --- a/modules/notifications/lib/notifications.js +++ b/modules/notifications/lib/notifications.js @@ -1,239 +1,249 @@ jQuery(document).ready(function($) { // $('#ef-post_following_users_box ul').listFilterizer(); - var params = { - action: 'save_notifications', - post_id: $('#post_ID').val(), - }; - - $(document).on('click','.ef-post_following_list li input:checkbox, .ef-following_usergroups li input:checkbox', function() { - var user_group_ids = []; - var parent_this = $(this); - params.ef_notifications_name = $(this).attr('name'); - params._nonce = $("#ef_notifications_nonce").val(); - - $(this) - .parent() - .parent() - .parent() - .find('input:checked') - .map(function(){ - user_group_ids.push($(this).val()); - }) - - params.user_group_ids = user_group_ids; - - $.ajax({ - type : 'POST', - url : (ajaxurl) ? ajaxurl : wpListL10n.url, - data : params, - success : function(x) { - - console.log(params); - // This event is used to show an updated list of who will be notified of editorial comments and status updates. - $( '#ef-post_following_box' ).trigger( 'following_list_updated' ); - - var backgroundColor = parent_this.css( 'background-color' ); - $(parent_this.parent().parent()) - .animate( { 'backgroundColor':'#CCEEBB' }, 200 ) - .animate( { 'backgroundColor':backgroundColor }, 200 ); - }, - error : function(r) { - $('#ef-post_following_users_box').prev().append('

                  There was an error. Please reload the page.

                  '); - } - }); - }); - - //// Users list for notifications meta - - // Options for the list - var options = { - // values used for filters - valueNames: [ 'user-item-name', 'user-item-email', { name: 'user_checked', attr: ''}, {data: ['user-item-id']} ], - - // searchClass is used for filtering values in the list - searchClass: 'filter-users', - - // item used for user list template - item: '
                • ' - }; - - // Initialize the list.js, 'users' is the html class name to fill in the users list - var userList = new List('users', options); - var usersPerPage = 10; - var totalUsers = 0; - - // Fill the initial users list on document load - function initiateUsersList() { - - //// Retrieve total user counts for pagination numbering - // Data sent to WP through ajax for user counts - var data_user_count = { - action: 'retrieve_users', - nonce: ajax_object.ajax_nonce, - count_users: true + var post_id = $('#post_ID').val(); + + // check post_id, only run the following JS if it is in post page + if (post_id !== undefined) { + + var params = { + action: 'save_notifications', + post_id: post_id, }; - jQuery.post(ajax_object.ajax_url, data_user_count) - .done( function (response) { - totalUsers = parseInt(response); - fillPaginatedUsersList(totalUsers, usersPerPage, ''); - }) - .fail( function (xhr, status, error) { - $('#ef-post_following_users_box').prev().append('

                  There was an error. Please reload the page.

                  '); + $(document).on('click', '.ef-post_following_list li input:checkbox, .ef-following_usergroups li input:checkbox', function () { + var user_group_ids = []; + var parent_this = $(this); + params.ef_notifications_name = $(this).attr('name'); + params._nonce = $("#ef_notifications_nonce").val(); + + $(this) + .parent() + .parent() + .parent() + .find('input:checked') + .map(function () { + user_group_ids.push($(this).val()); + }) + + params.user_group_ids = user_group_ids; + + $.ajax({ + type: 'POST', + url: (ajaxurl) ? ajaxurl : wpListL10n.url, + data: params, + success: function (x) { + + console.log(params); + // This event is used to show an updated list of who will be notified of editorial comments and status updates. + $('#ef-post_following_box').trigger('following_list_updated'); + + var backgroundColor = parent_this.css('background-color'); + $(parent_this.parent().parent()) + .animate({'backgroundColor': '#CCEEBB'}, 200) + .animate({'backgroundColor': backgroundColor}, 200); + }, + error: function (r) { + $('#ef-post_following_users_box').prev().append('

                  There was an error. Please reload the page.

                  '); + } }); + }); + + //// Users list for notifications meta + + // Options for the list + var options = { + // values used for filters + valueNames: ['user-item-name', 'user-item-email', { + name: 'user_checked', + attr: '' + }, {data: ['user-item-id']}], - } - function fillPaginatedUsersList(totalUsers, usersPerPage, searchKeyword){ + // searchClass is used for filtering values in the list + searchClass: 'filter-users', + + // item used for user list template + item: '
                • ' + }; + + // Initialize the list.js, 'users' is the html class name to fill in the users list + var userList = new List('users', options); + var usersPerPage = 10; + var totalUsers = 0; + + // Fill the initial users list on document load + function initiateUsersList() { + + //// Retrieve total user counts for pagination numbering + // Data sent to WP through ajax for user counts + var data_user_count = { + action: 'retrieve_users', + nonce: ajax_object.ajax_nonce, + count_users: true + }; + + jQuery.post(ajax_object.ajax_url, data_user_count) + .done(function (response) { + totalUsers = parseInt(response); + fillPaginatedUsersList(totalUsers, usersPerPage, ''); + }) + .fail(function (xhr, status, error) { + $('#ef-post_following_users_box').prev().append('

                  There was an error. Please reload the page.

                  '); + }); - // remove pagination if it existed - if($('#users-pagination').data("twbs-pagination")){ - $('#users-pagination').twbsPagination('destroy'); } - $('#users-pagination').twbsPagination({ - totalPages: Math.ceil(totalUsers/usersPerPage), // The total number of user pages - visiblePages: usersPerPage, // Number of users displayed in a page - next: 'Next', - prev: 'Prev', - onPageClick: function (event, page) { + function fillPaginatedUsersList(totalUsers, usersPerPage, searchKeyword) { - // clear the users list when the page created - userList.clear(); + // remove pagination if it existed + if ($('#users-pagination').data("twbs-pagination")) { + $('#users-pagination').twbsPagination('destroy'); + } - // Data sent to WP through ajax for paginated users list - var data = { - action: 'retrieve_users', - post_id: $('#post_ID').val(), - page: page, - users_per_page: usersPerPage, - nonce: ajax_object.ajax_nonce, - search_keyword: searchKeyword, - count_users: false - }; - - jQuery.post(ajax_object.ajax_url, data, function (response) { - // Add the users retrieved from wordpress db to list - for (var user of response.users){ - userList.add(user); - if(user.user_checked){ - $('li[data-user-item-id='+user['user-item-id']+'] input:checkbox').prop("checked", true); + $('#users-pagination').twbsPagination({ + totalPages: Math.ceil(totalUsers / usersPerPage), // The total number of user pages + visiblePages: usersPerPage, // Number of users displayed in a page + next: 'Next', + prev: 'Prev', + onPageClick: function (event, page) { + + // clear the users list when the page created + userList.clear(); + + // Data sent to WP through ajax for paginated users list + var data = { + action: 'retrieve_users', + post_id: $('#post_ID').val(), + page: page, + users_per_page: usersPerPage, + nonce: ajax_object.ajax_nonce, + search_keyword: searchKeyword, + count_users: false + }; + + jQuery.post(ajax_object.ajax_url, data, function (response) { + // Add the users retrieved from wordpress db to list + for (var user of response.users) { + userList.add(user); + if (user.user_checked) { + $('li[data-user-item-id=' + user['user-item-id'] + '] input:checkbox').prop("checked", true); + } } - } - // Fill in users count info - $('.users-total-info-value').text(totalUsers); - if (searchKeyword !== ''){ - $('.users-total-info-text').text('Totals users found'); - } + // Fill in users count info + $('.users-total-info-value').text(totalUsers); + if (searchKeyword !== '') { + $('.users-total-info-text').text('Totals users found'); + } - }); + }); - } - }); - } - - function fillUsersListByKeyword(searchKeyword){ - //// Retrieve total user counts for pagination numbering - // Data sent to WP through ajax for user counts - var data_user_count = { - action: 'retrieve_users', - nonce: ajax_object.ajax_nonce, - count_users: true, - search_keyword: searchKeyword - }; + } + }); + } - jQuery.post(ajax_object.ajax_url, data_user_count, function (response) { + function fillUsersListByKeyword(searchKeyword) { + //// Retrieve total user counts for pagination numbering + // Data sent to WP through ajax for user counts + var data_user_count = { + action: 'retrieve_users', + nonce: ajax_object.ajax_nonce, + count_users: true, + search_keyword: searchKeyword + }; - totalUsers = parseInt(response); + jQuery.post(ajax_object.ajax_url, data_user_count, function (response) { - if(totalUsers > 0) { - fillPaginatedUsersList(totalUsers, usersPerPage, searchKeyword); - } else { - $('#users-pagination').twbsPagination('destroy'); - $('.users-total-info-text').text('Totals users found'); - $('.users-total-info-value').text(totalUsers); + totalUsers = parseInt(response); + + if (totalUsers > 0) { + fillPaginatedUsersList(totalUsers, usersPerPage, searchKeyword); + } else { + $('#users-pagination').twbsPagination('destroy'); + $('.users-total-info-text').text('Totals users found'); + $('.users-total-info-value').text(totalUsers); + + } + }); + } + + $('.search-users').bind('keypress', function (e) { + if (e.keyCode == 13) { + clearTimeout($.data(this, 'timer')); + + e.preventDefault(); + var searchKeyword = $('.search-users').val(); + userList.clear(); + + var wait = setTimeout(fillUsersListByKeyword(searchKeyword), 10000); + + $(this).data('timer', wait); } }); - } - $('.search-users').bind('keypress', function(e){ - if(e.keyCode == 13) { + $('.btn-search-users').click(function (e) { clearTimeout($.data(this, 'timer')); e.preventDefault(); - var searchKeyword = $('.search-users').val(); + var searchKeyword = $('.search-users').val(); userList.clear(); var wait = setTimeout(fillUsersListByKeyword(searchKeyword), 10000); $(this).data('timer', wait); - } - }); - - $('.btn-search-users').click(function (e) { - clearTimeout($.data(this, 'timer')); - - e.preventDefault(); - var searchKeyword = $('.search-users').val(); - userList.clear(); - - var wait = setTimeout(fillUsersListByKeyword(searchKeyword), 10000); - - $(this).data('timer', wait); - - }); + }); - $(document).on('click', '.user-item', function (e) { + $(document).on('click', '.user-item', function (e) { - var item_element = $(this); - var checkbox = item_element.find("input[type='checkbox']"); - var user_group_ids = []; + var item_element = $(this); + var checkbox = item_element.find("input[type='checkbox']"); + var user_group_ids = []; - // check the checkbox when .user-item element is clicked - if (!$(e.target).is(':checkbox') && !checkbox.is(':checked')) { - checkbox.attr('checked', true); - } else if ((!$(e.target).is(':checkbox') && checkbox.is(':checked'))){ - checkbox.attr('checked', false); - } + // check the checkbox when .user-item element is clicked + if (!$(e.target).is(':checkbox') && !checkbox.is(':checked')) { + checkbox.attr('checked', true); + } else if ((!$(e.target).is(':checkbox') && checkbox.is(':checked'))) { + checkbox.attr('checked', false); + } - params.ef_notifications_name = 'ef-selected-users[]'; - params._nonce = $("#ef_notifications_nonce").val(); - user_group_ids.push($(this).data('user-item-id')); - params.user_group_ids = user_group_ids; + params.ef_notifications_name = 'ef-selected-users[]'; + params._nonce = $("#ef_notifications_nonce").val(); + user_group_ids.push($(this).data('user-item-id')); + params.user_group_ids = user_group_ids; - console.log(params); - console.log($(this).find('input').is(':checked')); + console.log(params); + console.log($(this).find('input').is(':checked')); - if (checkbox.is(':checked')){ - params.follow = true; - } else { - params.follow = false; - } + if (checkbox.is(':checked')) { + params.follow = true; + } else { + params.follow = false; + } - jQuery.post(ajaxurl, params) - .done( function (response) { - console.log(params); - // This event is used to show an updated list of who will be notified of editorial comments and status updates. - $( '#ef-post_following_box' ).trigger( 'following_list_updated' ); - - - // Trigger visual effect when ajax successful - var backgroundColor = item_element.parent().css( 'background-color' ); - item_element - .animate( { 'backgroundColor':'#CCEEBB' }, 200 ) - .animate( { 'backgroundColor':backgroundColor }, 200 ); - }) - .fail( function (xhr, status, error) { - $('#ef-post_following_users_box').prev().append('

                  There was an error. Please reload the page.

                  '); - }); + jQuery.post(ajaxurl, params) + .done(function (response) { + console.log(params); + // This event is used to show an updated list of who will be notified of editorial comments and status updates. + $('#ef-post_following_box').trigger('following_list_updated'); + + + // Trigger visual effect when ajax successful + var backgroundColor = item_element.parent().css('background-color'); + item_element + .animate({'backgroundColor': '#CCEEBB'}, 200) + .animate({'backgroundColor': backgroundColor}, 200); + }) + .fail(function (xhr, status, error) { + $('#ef-post_following_users_box').prev().append('

                  There was an error. Please reload the page.

                  '); + }); - }); + }); - initiateUsersList(); + initiateUsersList(); + }// checks post_id }); \ No newline at end of file From 2a100bc103db936d522a3454ae156f0161363411 Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Sun, 21 Oct 2018 23:08:28 +0700 Subject: [PATCH 11/34] change users_select_form with user_list --- modules/user-groups/user-groups.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/user-groups/user-groups.php b/modules/user-groups/user-groups.php index 2dc0331c9..e2d1d3b3d 100644 --- a/modules/user-groups/user-groups.php +++ b/modules/user-groups/user-groups.php @@ -561,8 +561,9 @@ function print_configure_view() { 'input_id' => 'usergroup_users' ); ?> - users_select_form( $usergroup->user_ids , $select_form_args ); ?> - + users_list(); ?> + users_select_form( $usergroup->user_ids , $select_form_args ); ?> +
                  @@ -586,7 +587,7 @@ function print_configure_view() {

                  - + Date: Sun, 21 Oct 2018 23:08:46 +0700 Subject: [PATCH 12/34] turn off unused javascript --- modules/user-groups/lib/user-groups.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/user-groups/lib/user-groups.js b/modules/user-groups/lib/user-groups.js index 04403ad6a..8fa3820c9 100644 --- a/modules/user-groups/lib/user-groups.js +++ b/modules/user-groups/lib/user-groups.js @@ -1,9 +1,9 @@ jQuery(document).ready(function () { - jQuery('ul#ef-post_following_users li').quicksearch({ - position: 'before', - attached: 'ul#ef-post_following_users', - loaderText: '', - delay: 100 - }) - jQuery('#ef-usergroup-users ul').listFilterizer(); + // jQuery('ul#ef-post_following_users li').quicksearch({ + // position: 'before', + // attached: 'ul#ef-post_following_users', + // loaderText: '', + // delay: 100 + // }) + // jQuery('#ef-usergroup-users ul').listFilterizer(); }); \ No newline at end of file From 500ed889caf2b1616f8e6b524243af1db472c264 Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Sun, 21 Oct 2018 23:14:40 +0700 Subject: [PATCH 13/34] put check on usergroup_id put check on user-groups.js so the javascript only run on user-groups --- modules/user-groups/lib/user-groups.js | 9 ++++++++- modules/user-groups/user-groups.php | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/modules/user-groups/lib/user-groups.js b/modules/user-groups/lib/user-groups.js index 8fa3820c9..3a374c9bf 100644 --- a/modules/user-groups/lib/user-groups.js +++ b/modules/user-groups/lib/user-groups.js @@ -1,4 +1,4 @@ -jQuery(document).ready(function () { +jQuery(document).ready(function ($) { // jQuery('ul#ef-post_following_users li').quicksearch({ // position: 'before', // attached: 'ul#ef-post_following_users', @@ -6,4 +6,11 @@ jQuery(document).ready(function () { // delay: 100 // }) // jQuery('#ef-usergroup-users ul').listFilterizer(); + + var usergroup_id = $('#usergroup_id').val(); + + if( usergroup_id !== undefined ){ + + } + }); \ No newline at end of file diff --git a/modules/user-groups/user-groups.php b/modules/user-groups/user-groups.php index e2d1d3b3d..87885042b 100644 --- a/modules/user-groups/user-groups.php +++ b/modules/user-groups/user-groups.php @@ -566,7 +566,7 @@ function print_configure_view() {
                  - + Date: Sun, 21 Oct 2018 23:41:31 +0700 Subject: [PATCH 14/34] remove unused action --- modules/notifications/notifications.php | 3 -- modules/user-groups/user-groups.php | 71 ++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/modules/notifications/notifications.php b/modules/notifications/notifications.php index f76bee222..5211b766d 100644 --- a/modules/notifications/notifications.php +++ b/modules/notifications/notifications.php @@ -103,9 +103,6 @@ function init() { //Ajax for retrieving users add_action('wp_ajax_retrieve_users', array($this, 'ajax_retrieve_users')); - - //Ajax for retrieving users count - add_action('wp_ajax_retrieve_users_count', array($this, 'ajax_retrieve_users_count')); } /** diff --git a/modules/user-groups/user-groups.php b/modules/user-groups/user-groups.php index 87885042b..c3921fab2 100644 --- a/modules/user-groups/user-groups.php +++ b/modules/user-groups/user-groups.php @@ -101,7 +101,10 @@ function init() { // Javascript and CSS if we need it add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) ); - add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_styles' ) ); + add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_styles' ) ); + + // Ajax for retrieving users + add_action( 'wp_ajax_retrieve_users_in_usergroup', array( $this, 'ajax_retrieve_users_in_usergroups')); } @@ -633,6 +636,72 @@ function print_configure_view() { inline_edit(); ?> get_following_users( $post_id, 'id' ); + + $search_keyword = isset( $_POST['search_keyword']) ? sanitize_text_field($_POST['search_keyword']) : ''; + + $users_per_page = isset( $_POST['users_per_page']) ? intval($_POST['users_per_page']) : 0; + $page = isset( $_POST['page']) ? intval($_POST['page']) : 0; + $offset = $users_per_page * ($page - 1); + + $args = array( + 'number' => $users_per_page, + 'offset' => $offset, + 'who' => 'authors', + 'fields' => array( + 'ID', + 'display_name', + 'user_email' + ), + 'orderby' => 'display_name', + 'search' => '*' . $search_keyword .'*', + 'search_columns' => array('display_name', 'user_email'), +// 'include' => $selected + ); + + $usersQuery = new WP_User_Query($args); + + $count_users = isset( $_POST['count_users']) ? filter_var($_POST['count_users'], FILTER_VALIDATE_BOOLEAN) : false; + if($count_users){ + $users_count = $usersQuery->get_total(); + wp_send_json($users_count); + } + + $users = $usersQuery->get_results(); + + + if ( ! is_array($selected)){ + $selected = array(); + } + + // Compile users with selected users on top of the list + $users_with_selection = array(); + + foreach ($users as $user){ + + $user_arr['user-item-id'] = $user->ID; + $user_arr['user-item-name'] = $user->display_name; + $user_arr['user-item-email'] = $user->user_email; + + if ( in_array($user->ID, $selected) ){ + $user_arr['user_checked'] = true; + } else { + $user_arr['user_checked'] = false; + } + + array_push($users_with_selection, $user_arr); + } + + wp_send_json(['users' => $users_with_selection, 'users_total' => $usersQuery->get_total()]); + + } /** * Adds a form to the user profile page to allow adding usergroup selecting options From 111228233425f7c12145c5c9998870d0b82a836b Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Mon, 22 Oct 2018 17:32:50 +0700 Subject: [PATCH 15/34] add important to styles --- common/css/edit-flow-admin.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/css/edit-flow-admin.css b/common/css/edit-flow-admin.css index 768fc8682..20423c705 100644 --- a/common/css/edit-flow-admin.css +++ b/common/css/edit-flow-admin.css @@ -45,12 +45,14 @@ Users list style } .user-item-name { + !important; display: block; font-size: 14px; margin: 0; } .user-item-email { + !important; display: block; color: #ccc; font-size: 12px; From 39585530bf52367b4ecb153539f77c1385222a1e Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Mon, 22 Oct 2018 17:33:37 +0700 Subject: [PATCH 16/34] reorder enqueue script --- modules/notifications/notifications.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/notifications/notifications.php b/modules/notifications/notifications.php index 5211b766d..9cce9eb51 100644 --- a/modules/notifications/notifications.php +++ b/modules/notifications/notifications.php @@ -192,11 +192,12 @@ function enqueue_admin_scripts() { if ( $this->is_whitelisted_functional_view() ) { wp_enqueue_script( 'jquery-listfilterizer' ); wp_enqueue_script( 'jquery-quicksearch' ); - wp_enqueue_script( 'edit-flow-notifications-js', $this->module_url . 'lib/notifications.js', array( 'jquery', 'jquery-listfilterizer', 'jquery-quicksearch' ), EDIT_FLOW_VERSION, true ); wp_enqueue_script( 'list'); wp_enqueue_script( 'jquery-twbsPagination'); + wp_enqueue_script( 'edit-flow-notifications-js', $this->module_url . 'lib/notifications.js', array( 'jquery', 'jquery-listfilterizer', 'jquery-quicksearch', 'list', 'jquery-twbsPagination' ), EDIT_FLOW_VERSION, true ); + wp_localize_script( 'edit-flow-notifications-js', 'ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), From f08890fe4d245013bed9544d6f0e7aa19d41e2c2 Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Mon, 22 Oct 2018 17:34:11 +0700 Subject: [PATCH 17/34] paginated users list with ajax in usergroup --- modules/user-groups/lib/user-groups.js | 200 ++++++++++++++++++++++++- modules/user-groups/user-groups.php | 52 ++++++- 2 files changed, 246 insertions(+), 6 deletions(-) diff --git a/modules/user-groups/lib/user-groups.js b/modules/user-groups/lib/user-groups.js index 3a374c9bf..183303f81 100644 --- a/modules/user-groups/lib/user-groups.js +++ b/modules/user-groups/lib/user-groups.js @@ -11,6 +11,204 @@ jQuery(document).ready(function ($) { if( usergroup_id !== undefined ){ - } + // Options for the list + var options = { + // values used for filters + valueNames: ['user-item-name', 'user-item-email', { + name: 'user_checked', + attr: '' + }, {data: ['user-item-id']}], + + // searchClass is used for filtering values in the list + searchClass: 'filter-users', + + // item used for user list template + item: '
                • ' + }; + + // Initialize the list.js, 'users' is the html class name to fill in the users list + var userList = new List('users', options); + var usersPerPage = 10; + var totalUsers = 0; + + // Fill the initial users list on document load + function initiateUsersList() { + + //// Retrieve total user counts for pagination numbering + // Data sent to WP through ajax for user counts + var data_user_count = { + action: 'retrieve_users_in_usergroup', + nonce: ajax_object.ajax_nonce, + count_users: true + }; + + jQuery.post(ajax_object.ajax_url, data_user_count) + .done(function (response) { + console.log(data_user_count); + console.log(response); + totalUsers = parseInt(response); + fillPaginatedUsersList(totalUsers, usersPerPage, ''); + }) + .fail(function (xhr, status, error) { + $('#ef-usergroup-users').append('

                  There was an error. Please reload the page.

                  '); + }); + + } + + function fillPaginatedUsersList(totalUsers, usersPerPage, searchKeyword) { + + // remove pagination if it existed + if ($('#users-pagination').data("twbs-pagination")) { + $('#users-pagination').twbsPagination('destroy'); + } + + $('#users-pagination').twbsPagination({ + totalPages: Math.ceil(totalUsers / usersPerPage), // The total number of user pages + visiblePages: usersPerPage, // Number of users displayed in a page + next: 'Next', + prev: 'Prev', + onPageClick: function (event, page) { + + // clear the users list when the page created + userList.clear(); + + // Data sent to WP through ajax for paginated users list + var data = { + action: 'retrieve_users_in_usergroup', + usergroup_id: usergroup_id, + page: page, + users_per_page: usersPerPage, + nonce: ajax_object.ajax_nonce, + search_keyword: searchKeyword, + count_users: false + }; + + jQuery.post(ajax_object.ajax_url, data, function (response) { + console.log(data); + console.log(response); + // Add the users retrieved from wordpress db to list + for (var user of response.users) { + userList.add(user); + if (user.user_checked) { + $('li[data-user-item-id=' + user['user-item-id'] + '] input:checkbox').prop("checked", true); + } + } + + // Fill in users count info + $('.users-total-info-value').text(totalUsers); + if (searchKeyword !== '') { + $('.users-total-info-text').text('Totals users found'); + } + + }); + + } + }); + } + + function fillUsersListByKeyword(searchKeyword) { + //// Retrieve total user counts for pagination numbering + // Data sent to WP through ajax for user counts + var data_user_count = { + action: 'retrieve_users_in_usergroup', + nonce: ajax_object.ajax_nonce, + count_users: true, + search_keyword: searchKeyword + }; + + jQuery.post(ajax_object.ajax_url, data_user_count, function (response) { + + totalUsers = parseInt(response); + + if (totalUsers > 0) { + fillPaginatedUsersList(totalUsers, usersPerPage, searchKeyword); + } else { + $('#users-pagination').twbsPagination('destroy'); + $('.users-total-info-text').text('Totals users found'); + $('.users-total-info-value').text(totalUsers); + + } + }); + } + + $('.search-users').bind('keypress', function (e) { + if (e.keyCode == 13) { + clearTimeout($.data(this, 'timer')); + + e.preventDefault(); + var searchKeyword = $('.search-users').val(); + userList.clear(); + + var wait = setTimeout(fillUsersListByKeyword(searchKeyword), 10000); + + $(this).data('timer', wait); + + } + }); + + $('.btn-search-users').click(function (e) { + clearTimeout($.data(this, 'timer')); + + e.preventDefault(); + var searchKeyword = $('.search-users').val(); + userList.clear(); + + var wait = setTimeout(fillUsersListByKeyword(searchKeyword), 10000); + + $(this).data('timer', wait); + + }); + + $(document).on('click', '.user-item', function (e) { + + var item_element = $(this); + var checkbox = item_element.find("input[type='checkbox']"); + + // check the checkbox when .user-item element is clicked + if (!$(e.target).is(':checkbox') && !checkbox.is(':checked')) { + checkbox.attr('checked', true); + } else if ((!$(e.target).is(':checkbox') && checkbox.is(':checked'))) { + checkbox.attr('checked', false); + } + + var params = { + action: 'save_user_to_usergroup', + usergroup_id: usergroup_id, + nonce: ajax_object.ajax_nonce, + user_id: ($(this).data('user-item-id')), + }; + + if (checkbox.is(':checked')) { + params.add = true; + } else { + params.remove = true; + } + + jQuery.post(ajaxurl, params) + .done(function (response) { + console.log(params); + console.log(item_element); + console.log(response); + + + // item_element.css('background-color', 'black'); + + // Trigger visual effect when ajax successful + var backgroundColor = item_element.parent().css('background-color'); + item_element + .animate({'backgroundColor': '#CCEEBB'}, 200) + .animate({'backgroundColor': backgroundColor}, 200); + }) + .fail(function (xhr, status, error) { + $('#ef-post_following_users_box').prev().append('

                  There was an error. Please reload the page.

                  '); + }); + + + }); + + initiateUsersList(); + + + } // check on usergroup }); \ No newline at end of file diff --git a/modules/user-groups/user-groups.php b/modules/user-groups/user-groups.php index c3921fab2..c9b05584d 100644 --- a/modules/user-groups/user-groups.php +++ b/modules/user-groups/user-groups.php @@ -105,7 +105,10 @@ function init() { // Ajax for retrieving users add_action( 'wp_ajax_retrieve_users_in_usergroup', array( $this, 'ajax_retrieve_users_in_usergroups')); - + + // Ajax for saving user to usergroup + add_action( 'wp_ajax_save_user_to_usergroup', array( $this, 'ajax_save_user_to_usergroup' ) ); + } /** @@ -234,7 +237,18 @@ function enqueue_admin_scripts() { if ( $this->is_whitelisted_functional_view() || $this->is_whitelisted_settings_view( $this->module->name ) ) { wp_enqueue_script( 'jquery-listfilterizer' ); wp_enqueue_script( 'jquery-quicksearch' ); - wp_enqueue_script( 'edit-flow-user-groups-js', $this->module_url . 'lib/user-groups.js', array( 'jquery', 'jquery-listfilterizer', 'jquery-quicksearch' ), EDIT_FLOW_VERSION, true ); + + wp_enqueue_script( 'list'); + wp_enqueue_script( 'jquery-twbsPagination'); + + + wp_enqueue_script( 'edit-flow-user-groups-js', $this->module_url . 'lib/user-groups.js', array( 'jquery', 'jquery-color', 'jquery-listfilterizer', 'jquery-quicksearch', 'list', 'jquery-twbsPagination' ), EDIT_FLOW_VERSION, true ); + + wp_localize_script( 'edit-flow-user-groups-js', 'ajax_object', + array( 'ajax_url' => admin_url( 'admin-ajax.php' ), + 'ajax_nonce' => wp_create_nonce( "edit-flow-users-list-usergroups-ajax" ) + ) + ); } if ( $this->is_whitelisted_settings_view( $this->module->name ) ) @@ -638,12 +652,17 @@ function print_configure_view() { } /* - * Ajax processing for retrieving users in usergroups + * Ajax processing for retrieving users in usergroups. + * It can return total number of users if $count_users flag is true + * and return the users if $count_users is false */ function ajax_retrieve_users_in_usergroups(){ - $post_id = isset( $_POST['post_id'] ) ? intval($_POST['post_id']) : 0; - $selected = $this->get_following_users( $post_id, 'id' ); + // find user ids who are selected in the usergroup + $usergroup_id = isset( $_POST['usergroup_id'] ) ? intval($_POST['usergroup_id']) : 0; + $usergroup_by_id = $this->get_usergroup_by('id', $usergroup_id); + $usergroup_by_id_arr = ($usergroup_by_id !== false) ? $usergroup_by_id->to_array() : array(); + $selected = $usergroup_by_id_arr['user_ids']; $search_keyword = isset( $_POST['search_keyword']) ? sanitize_text_field($_POST['search_keyword']) : ''; @@ -673,6 +692,7 @@ function ajax_retrieve_users_in_usergroups(){ $users_count = $usersQuery->get_total(); wp_send_json($users_count); } +// wp_send_json(['response oyeee', $selected['user_ids']]); $users = $usersQuery->get_results(); @@ -702,6 +722,28 @@ function ajax_retrieve_users_in_usergroups(){ wp_send_json(['users' => $users_with_selection, 'users_total' => $usersQuery->get_total()]); } + + /* + * Ajax handling saving and removing user from usergroup + */ + function ajax_save_user_to_usergroup(){ + $nonce = $_POST['nonce']; + + $add = isset( $_POST['add']) ? filter_var($_POST['add'], FILTER_VALIDATE_BOOLEAN) : false; + $remove = isset( $_POST['remove']) ? filter_var($_POST['remove'], FILTER_VALIDATE_BOOLEAN) : false; + + $user_id = isset( $_POST['user_id'] ) ? intval( $_POST['user_id']) : 0; + $usergroup_id = isset( $_POST['usergroup_id'] ) ? intval( $_POST['usergroup_id']) : 0; + + if($add){ + $this->add_user_to_usergroup($user_id, $usergroup_id); + } + + if($remove){ + $this->remove_user_from_usergroup($user_id, $usergroup_id); + } + + } /** * Adds a form to the user profile page to allow adding usergroup selecting options From 61ba336873179dbc84571d5079c7f19443b4c43f Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Mon, 22 Oct 2018 18:22:25 +0700 Subject: [PATCH 18/34] remove console logs --- modules/notifications/lib/notifications.js | 5 ----- modules/user-groups/lib/user-groups.js | 12 ++---------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/modules/notifications/lib/notifications.js b/modules/notifications/lib/notifications.js index fdc207efa..88ca96c10 100644 --- a/modules/notifications/lib/notifications.js +++ b/modules/notifications/lib/notifications.js @@ -34,7 +34,6 @@ jQuery(document).ready(function($) { data: params, success: function (x) { - console.log(params); // This event is used to show an updated list of who will be notified of editorial comments and status updates. $('#ef-post_following_box').trigger('following_list_updated'); @@ -214,9 +213,6 @@ jQuery(document).ready(function($) { user_group_ids.push($(this).data('user-item-id')); params.user_group_ids = user_group_ids; - console.log(params); - console.log($(this).find('input').is(':checked')); - if (checkbox.is(':checked')) { params.follow = true; } else { @@ -225,7 +221,6 @@ jQuery(document).ready(function($) { jQuery.post(ajaxurl, params) .done(function (response) { - console.log(params); // This event is used to show an updated list of who will be notified of editorial comments and status updates. $('#ef-post_following_box').trigger('following_list_updated'); diff --git a/modules/user-groups/lib/user-groups.js b/modules/user-groups/lib/user-groups.js index 183303f81..b55568347 100644 --- a/modules/user-groups/lib/user-groups.js +++ b/modules/user-groups/lib/user-groups.js @@ -44,8 +44,7 @@ jQuery(document).ready(function ($) { jQuery.post(ajax_object.ajax_url, data_user_count) .done(function (response) { - console.log(data_user_count); - console.log(response); + totalUsers = parseInt(response); fillPaginatedUsersList(totalUsers, usersPerPage, ''); }) @@ -84,8 +83,7 @@ jQuery(document).ready(function ($) { }; jQuery.post(ajax_object.ajax_url, data, function (response) { - console.log(data); - console.log(response); + // Add the users retrieved from wordpress db to list for (var user of response.users) { userList.add(user); @@ -186,12 +184,6 @@ jQuery(document).ready(function ($) { jQuery.post(ajaxurl, params) .done(function (response) { - console.log(params); - console.log(item_element); - console.log(response); - - - // item_element.css('background-color', 'black'); // Trigger visual effect when ajax successful var backgroundColor = item_element.parent().css('background-color'); From bd845c7f25f9b1e7b0cbffc17ddedc61bfd86521 Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Mon, 22 Oct 2018 18:22:43 +0700 Subject: [PATCH 19/34] add styling for pagination items --- common/css/edit-flow-admin.css | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/common/css/edit-flow-admin.css b/common/css/edit-flow-admin.css index 20423c705..c060c08c8 100644 --- a/common/css/edit-flow-admin.css +++ b/common/css/edit-flow-admin.css @@ -30,7 +30,13 @@ Users list style .pagination li { display:inline-block; - padding:5px; + padding-top:5px; +} + +.page-item { + !important; + padding-right: 4px; + padding-left: 4px; } .user-item { From a8e518933bcd8c33ff88278352292178eff7a0cc Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Mon, 22 Oct 2018 19:00:02 +0700 Subject: [PATCH 20/34] add nonce security checks --- modules/notifications/lib/notifications.js | 8 +++++--- modules/notifications/notifications.php | 4 +++- modules/user-groups/user-groups.php | 2 ++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/modules/notifications/lib/notifications.js b/modules/notifications/lib/notifications.js index 88ca96c10..173b6fef4 100644 --- a/modules/notifications/lib/notifications.js +++ b/modules/notifications/lib/notifications.js @@ -77,7 +77,7 @@ jQuery(document).ready(function($) { // Data sent to WP through ajax for user counts var data_user_count = { action: 'retrieve_users', - nonce: ajax_object.ajax_nonce, + nonce: $("#ef_notifications_nonce").val(), count_users: true }; @@ -85,9 +85,11 @@ jQuery(document).ready(function($) { .done(function (response) { totalUsers = parseInt(response); fillPaginatedUsersList(totalUsers, usersPerPage, ''); + }) .fail(function (xhr, status, error) { $('#ef-post_following_users_box').prev().append('

                  There was an error. Please reload the page.

                  '); + console.log(data_user_count); }); } @@ -115,7 +117,7 @@ jQuery(document).ready(function($) { post_id: $('#post_ID').val(), page: page, users_per_page: usersPerPage, - nonce: ajax_object.ajax_nonce, + nonce: $("#ef_notifications_nonce").val(), search_keyword: searchKeyword, count_users: false }; @@ -146,7 +148,7 @@ jQuery(document).ready(function($) { // Data sent to WP through ajax for user counts var data_user_count = { action: 'retrieve_users', - nonce: ajax_object.ajax_nonce, + nonce: $("#ef_notifications_nonce").val(), count_users: true, search_keyword: searchKeyword }; diff --git a/modules/notifications/notifications.php b/modules/notifications/notifications.php index 9cce9eb51..b714113d1 100644 --- a/modules/notifications/notifications.php +++ b/modules/notifications/notifications.php @@ -201,7 +201,7 @@ function enqueue_admin_scripts() { wp_localize_script( 'edit-flow-notifications-js', 'ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), - 'ajax_nonce' => wp_create_nonce( "edit-flow-users-list-ajax" ) + 'ajax_nonce' => wp_create_nonce( "edit-flow-users-list-notifications-ajax" ) ) ); } @@ -374,6 +374,8 @@ function notifications_meta_box() { */ function ajax_retrieve_users(){ + check_ajax_referer("save_user_usergroups" , "nonce"); + $post_id = isset( $_POST['post_id'] ) ? intval($_POST['post_id']) : 0; $selected = $this->get_following_users( $post_id, 'id' ); diff --git a/modules/user-groups/user-groups.php b/modules/user-groups/user-groups.php index c9b05584d..27554afe7 100644 --- a/modules/user-groups/user-groups.php +++ b/modules/user-groups/user-groups.php @@ -658,6 +658,8 @@ function print_configure_view() { */ function ajax_retrieve_users_in_usergroups(){ + check_ajax_referer('edit-flow-users-list-usergroups-ajax', 'nonce'); + // find user ids who are selected in the usergroup $usergroup_id = isset( $_POST['usergroup_id'] ) ? intval($_POST['usergroup_id']) : 0; $usergroup_by_id = $this->get_usergroup_by('id', $usergroup_id); From 0d9d3e2c5c2c26287dae594010bcbc50c747d6b3 Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Mon, 22 Oct 2018 19:01:05 +0700 Subject: [PATCH 21/34] remove commented code --- modules/user-groups/user-groups.php | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/user-groups/user-groups.php b/modules/user-groups/user-groups.php index 27554afe7..f2ce3f8bd 100644 --- a/modules/user-groups/user-groups.php +++ b/modules/user-groups/user-groups.php @@ -694,7 +694,6 @@ function ajax_retrieve_users_in_usergroups(){ $users_count = $usersQuery->get_total(); wp_send_json($users_count); } -// wp_send_json(['response oyeee', $selected['user_ids']]); $users = $usersQuery->get_results(); From b49f96f5e298b77f6fc6aa9380294f49b431406b Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Mon, 22 Oct 2018 19:02:37 +0700 Subject: [PATCH 22/34] add ajax nonce check when saving user in usergroup --- modules/user-groups/user-groups.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/user-groups/user-groups.php b/modules/user-groups/user-groups.php index f2ce3f8bd..b20004409 100644 --- a/modules/user-groups/user-groups.php +++ b/modules/user-groups/user-groups.php @@ -728,7 +728,7 @@ function ajax_retrieve_users_in_usergroups(){ * Ajax handling saving and removing user from usergroup */ function ajax_save_user_to_usergroup(){ - $nonce = $_POST['nonce']; + check_ajax_referer('edit-flow-users-list-usergroups-ajax', 'nonce'); $add = isset( $_POST['add']) ? filter_var($_POST['add'], FILTER_VALIDATE_BOOLEAN) : false; $remove = isset( $_POST['remove']) ? filter_var($_POST['remove'], FILTER_VALIDATE_BOOLEAN) : false; From 97557e5ff2a2b73acc79225ad0192f65def0ed7b Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Tue, 23 Oct 2018 16:24:18 +0700 Subject: [PATCH 23/34] fix whitespaces from editor misconfiguration --- modules/notifications/notifications.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/notifications/notifications.php b/modules/notifications/notifications.php index b714113d1..ac4f26402 100644 --- a/modules/notifications/notifications.php +++ b/modules/notifications/notifications.php @@ -374,7 +374,7 @@ function notifications_meta_box() { */ function ajax_retrieve_users(){ - check_ajax_referer("save_user_usergroups" , "nonce"); + check_ajax_referer("save_user_usergroups" , "nonce"); $post_id = isset( $_POST['post_id'] ) ? intval($_POST['post_id']) : 0; $selected = $this->get_following_users( $post_id, 'id' ); @@ -382,11 +382,11 @@ function ajax_retrieve_users(){ $search_keyword = isset( $_POST['search_keyword']) ? sanitize_text_field($_POST['search_keyword']) : ''; $users_per_page = isset( $_POST['users_per_page']) ? intval($_POST['users_per_page']) : 0; - $page = isset( $_POST['page']) ? intval($_POST['page']) : 0; - $offset = $users_per_page * ($page - 1); + $page = isset( $_POST['page']) ? intval($_POST['page']) : 0; + $offset = $users_per_page * ($page - 1); $args = array( - 'number' => $users_per_page, + 'number' => $users_per_page, 'offset' => $offset, 'who' => 'authors', 'fields' => array( @@ -395,9 +395,9 @@ function ajax_retrieve_users(){ 'user_email' ), 'orderby' => 'display_name', - 'search' => '*' . $search_keyword .'*', - 'search_columns' => array('display_name', 'user_email'), -// 'include' => $selected + 'search' => '*' . $search_keyword .'*', + 'search_columns' => array('display_name', 'user_email'), + // 'include' => $selected ); $usersQuery = new WP_User_Query($args); From 9b143182db4b68139832712720546b1b931b6a7e Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Tue, 23 Oct 2018 21:01:43 +0700 Subject: [PATCH 24/34] changed how user added and removed from notification Made a new separate function for adding and removing user to notification. Revert changes made to save_post_following_users() function to prevent breaking other codes. --- modules/notifications/lib/notifications.js | 28 +++++------ modules/notifications/notifications.php | 58 ++++++++++++++++++---- 2 files changed, 62 insertions(+), 24 deletions(-) diff --git a/modules/notifications/lib/notifications.js b/modules/notifications/lib/notifications.js index 173b6fef4..5c4e7355d 100644 --- a/modules/notifications/lib/notifications.js +++ b/modules/notifications/lib/notifications.js @@ -200,8 +200,6 @@ jQuery(document).ready(function($) { var item_element = $(this); var checkbox = item_element.find("input[type='checkbox']"); - var user_group_ids = []; - // check the checkbox when .user-item element is clicked if (!$(e.target).is(':checkbox') && !checkbox.is(':checked')) { @@ -209,24 +207,26 @@ jQuery(document).ready(function($) { } else if ((!$(e.target).is(':checkbox') && checkbox.is(':checked'))) { checkbox.attr('checked', false); } - - params.ef_notifications_name = 'ef-selected-users[]'; - params._nonce = $("#ef_notifications_nonce").val(); - user_group_ids.push($(this).data('user-item-id')); - params.user_group_ids = user_group_ids; - - if (checkbox.is(':checked')) { - params.follow = true; + + var data = { + action: 'save_user_in_notification', + post_id: post_id, + nonce: $("#ef_notifications_nonce").val(), + user_id: $(this).data('user-item-id') + } + + // add the user to notification if the checkbox checked or remove if unchecked + if (checkbox.is(':checked')) { + data.follow = true; } else { - params.follow = false; - } + data.follow = false; + } - jQuery.post(ajaxurl, params) + jQuery.post(ajaxurl, data) .done(function (response) { // This event is used to show an updated list of who will be notified of editorial comments and status updates. $('#ef-post_following_box').trigger('following_list_updated'); - // Trigger visual effect when ajax successful var backgroundColor = item_element.parent().css('background-color'); item_element diff --git a/modules/notifications/notifications.php b/modules/notifications/notifications.php index ac4f26402..9214a816c 100644 --- a/modules/notifications/notifications.php +++ b/modules/notifications/notifications.php @@ -102,7 +102,9 @@ function init() { add_action( 'wp_ajax_ef_notifications_user_post_subscription', array( $this, 'handle_user_post_subscription' ) ); //Ajax for retrieving users - add_action('wp_ajax_retrieve_users', array($this, 'ajax_retrieve_users')); + add_action('wp_ajax_retrieve_users', array($this, 'ajax_retrieve_users')); + //Ajax to save user notification + add_action('wp_ajax_save_user_in_notification', array( $this, 'ajax_save_user_in_notification' )); } /** @@ -414,7 +416,7 @@ function ajax_retrieve_users(){ if ( ! is_array($selected)){ $selected = array(); } - + // Compile users with selected users on top of the list $users_with_selection = array(); @@ -437,6 +439,46 @@ function ajax_retrieve_users(){ } + function ajax_save_user_in_notification(){ + + check_ajax_referer('save_user_usergroups', 'nonce'); + + $post_id = isset( $_POST['post_id'] ) ? intval( $_POST['post_id'] ) : 0; + $post = get_post( $post_id ); + $user_id = isset( $_POST['user_id']) ? intval( $_POST['user_id'] ) : 0; + $follow = isset( $_POST['follow']) ? filter_var($_POST['follow'], FILTER_VALIDATE_BOOLEAN) : false; + + //// Add selected user, current user, and author to notification if they are set to receive notifications + $users = array(); + $users[] = $user_id; + + // Add current user to notified users + $current_user = wp_get_current_user(); + if ( $current_user && apply_filters( 'ef_notification_auto_subscribe_current_user', true, 'subscription_action' ) ) + $users[] = $current_user->ID; + + // Add post author to notified users + if ( apply_filters( 'ef_notification_auto_subscribe_post_author', true, 'subscription_action' ) ) + $users[] = $post->post_author; + + $users = array_unique( array_map( 'intval', $users ) ); + + // check if the post used for notification is valid + $valid_post = ! is_null( $post ) && ! wp_is_post_revision( $post_id ) && ! wp_is_post_autosave( $post_id ); + if ( ! $valid_post || ! current_user_can( $this->edit_post_subscriptions_cap ) ) { + die(); + } + + // do follow or unfollow based on checkbox in the frontend + if ( $follow ) { + $this->follow_post_user( $post, $users, true ); + } else { + $this->unfollow_post_user($post, $user_id); + } + + wp_send_json_success('change to notification list is saved'); + } + /** * Called when a notification editorial metadata checkbox is checked. Handles saving of a user/usergroup to a post. */ @@ -462,8 +504,7 @@ function ajax_save_post_subscriptions() { } if ( 'ef-selected-users[]' === $_POST['ef_notifications_name'] ) { - $follow = isset( $_POST['follow'] ) ? filter_var($_POST['follow'], FILTER_VALIDATE_BOOLEAN) : true; - $this->save_post_following_users( $post, $user_group_ids, $follow ); + $this->save_post_following_users( $post, $user_group_ids ); } $groups_enabled = $this->module_enabled( 'user_groups' ) && in_array( get_post_type( $post_id ), $this->get_post_types_for_module( $edit_flow->user_groups->module ) ); @@ -527,7 +568,7 @@ function save_post_subscriptions( $new_status, $old_status, $post ) { * * @param int $post ID of the post */ - function save_post_following_users( $post, $users = null, $follow = true ) { + function save_post_following_users( $post, $users = null ) { if( !is_array( $users ) ) $users = array(); @@ -542,11 +583,8 @@ function save_post_following_users( $post, $users = null, $follow = true ) { $users = array_unique( array_map( 'intval', $users ) ); - if ( $follow ) { - $this->follow_post_user( $post, $users, true ); - } else { - $this->unfollow_post_user($post, $users[0]); - } + $follow = $this->follow_post_user( $post, $users, false ); + } /** From 85411283d13bbc4f781aabbece09d524826652c0 Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Tue, 23 Oct 2018 21:08:48 +0700 Subject: [PATCH 25/34] fix spaces in notifications.php --- modules/notifications/notifications.php | 43 ++++++++++++------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/modules/notifications/notifications.php b/modules/notifications/notifications.php index 9214a816c..d8353135f 100644 --- a/modules/notifications/notifications.php +++ b/modules/notifications/notifications.php @@ -202,9 +202,7 @@ function enqueue_admin_scripts() { wp_localize_script( 'edit-flow-notifications-js', 'ajax_object', - array( 'ajax_url' => admin_url( 'admin-ajax.php' ), - 'ajax_nonce' => wp_create_nonce( "edit-flow-users-list-notifications-ajax" ) - ) + array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'ajax_nonce' => wp_create_nonce( "edit-flow-users-list-notifications-ajax" ) ) ); } } @@ -399,43 +397,42 @@ function ajax_retrieve_users(){ 'orderby' => 'display_name', 'search' => '*' . $search_keyword .'*', 'search_columns' => array('display_name', 'user_email'), - // 'include' => $selected ); $usersQuery = new WP_User_Query($args); - $count_users = isset( $_POST['count_users']) ? filter_var($_POST['count_users'], FILTER_VALIDATE_BOOLEAN) : false; - if($count_users){ - $users_count = $usersQuery->get_total(); - wp_send_json($users_count); - } + $count_users = isset( $_POST['count_users']) ? filter_var($_POST['count_users'], FILTER_VALIDATE_BOOLEAN) : false; + if($count_users){ + $users_count = $usersQuery->get_total(); + wp_send_json($users_count); + } - $users = $usersQuery->get_results(); + $users = $usersQuery->get_results(); if ( ! is_array($selected)){ $selected = array(); } - + // Compile users with selected users on top of the list $users_with_selection = array(); - foreach ($users as $user){ + foreach ($users as $user){ - $user_arr['user-item-id'] = $user->ID; - $user_arr['user-item-name'] = $user->display_name; - $user_arr['user-item-email'] = $user->user_email; + $user_arr['user-item-id'] = $user->ID; + $user_arr['user-item-name'] = $user->display_name; + $user_arr['user-item-email'] = $user->user_email; - if ( in_array($user->ID, $selected) ){ - $user_arr['user_checked'] = true; - } else { - $user_arr['user_checked'] = false; - } + if ( in_array($user->ID, $selected) ){ + $user_arr['user_checked'] = true; + } else { + $user_arr['user_checked'] = false; + } - array_push($users_with_selection, $user_arr); - } + array_push($users_with_selection, $user_arr); + } - wp_send_json(['users' => $users_with_selection, 'users_total' => $usersQuery->get_total()]); + wp_send_json(['users' => $users_with_selection, 'users_total' => $usersQuery->get_total()]); } From 34c91bd60c0b9b61c802685f3da2315dd130138d Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Tue, 23 Oct 2018 21:24:07 +0700 Subject: [PATCH 26/34] fix spaces in user-group.php --- modules/user-groups/user-groups.php | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/modules/user-groups/user-groups.php b/modules/user-groups/user-groups.php index b20004409..1edfee013 100644 --- a/modules/user-groups/user-groups.php +++ b/modules/user-groups/user-groups.php @@ -104,9 +104,9 @@ function init() { add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_styles' ) ); // Ajax for retrieving users - add_action( 'wp_ajax_retrieve_users_in_usergroup', array( $this, 'ajax_retrieve_users_in_usergroups')); + add_action( 'wp_ajax_retrieve_users_in_usergroup', array( $this, 'ajax_retrieve_users_in_usergroups')); - // Ajax for saving user to usergroup + // Ajax for saving user to usergroup add_action( 'wp_ajax_save_user_to_usergroup', array( $this, 'ajax_save_user_to_usergroup' ) ); } @@ -578,9 +578,9 @@ function print_configure_view() { 'input_id' => 'usergroup_users' ); ?> - users_list(); ?> - users_select_form( $usergroup->user_ids , $select_form_args ); ?> -
                  + users_list(); ?> + users_select_form( $usergroup->user_ids , $select_form_args ); ?> +
                  @@ -658,9 +658,9 @@ function print_configure_view() { */ function ajax_retrieve_users_in_usergroups(){ - check_ajax_referer('edit-flow-users-list-usergroups-ajax', 'nonce'); + check_ajax_referer('edit-flow-users-list-usergroups-ajax', 'nonce'); - // find user ids who are selected in the usergroup + // find user ids who are selected in the usergroup $usergroup_id = isset( $_POST['usergroup_id'] ) ? intval($_POST['usergroup_id']) : 0; $usergroup_by_id = $this->get_usergroup_by('id', $usergroup_id); $usergroup_by_id_arr = ($usergroup_by_id !== false) ? $usergroup_by_id->to_array() : array(); @@ -684,7 +684,7 @@ function ajax_retrieve_users_in_usergroups(){ 'orderby' => 'display_name', 'search' => '*' . $search_keyword .'*', 'search_columns' => array('display_name', 'user_email'), -// 'include' => $selected + // 'include' => $selected ); $usersQuery = new WP_User_Query($args); @@ -737,12 +737,12 @@ function ajax_save_user_to_usergroup(){ $usergroup_id = isset( $_POST['usergroup_id'] ) ? intval( $_POST['usergroup_id']) : 0; if($add){ - $this->add_user_to_usergroup($user_id, $usergroup_id); - } + $this->add_user_to_usergroup($user_id, $usergroup_id); + } - if($remove){ - $this->remove_user_from_usergroup($user_id, $usergroup_id); - } + if($remove){ + $this->remove_user_from_usergroup($user_id, $usergroup_id); + } } From e4186b41289b4f15c8ba244e8b9bfe22624d06aa Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Tue, 23 Oct 2018 23:29:50 +0700 Subject: [PATCH 27/34] changed the way users list initiated Put a total user count in hidden field inside the users list template. This then can be used to initialize users list in notifications.php and user-groups.php. Eliminating the need to do ajax request to initialize the users list. --- common/php/class-module.php | 14 ++++++++++ modules/notifications/lib/notifications.js | 31 +++------------------- modules/user-groups/lib/user-groups.js | 28 +++---------------- 3 files changed, 21 insertions(+), 52 deletions(-) diff --git a/common/php/class-module.php b/common/php/class-module.php index 557d6d7cb..c2c88ad6d 100755 --- a/common/php/class-module.php +++ b/common/php/class-module.php @@ -487,12 +487,26 @@ function users_select_form( $selected = null, $args = null ) { * Template for paginated users list */ function users_list(){ + + // Get the count of all authors, the count is used to initialize users list + + $args = array( + 'who' => 'authors', + 'fields' => array( + 'ID', + ), + ); + + $usersQuery = new WP_User_Query( array('who' => 'authors', 'fields' => 'ID') ); + $users_count = $usersQuery->get_total(); + ?>
                  + diff --git a/modules/notifications/lib/notifications.js b/modules/notifications/lib/notifications.js index 5c4e7355d..71ad72948 100644 --- a/modules/notifications/lib/notifications.js +++ b/modules/notifications/lib/notifications.js @@ -69,30 +69,7 @@ jQuery(document).ready(function($) { var userList = new List('users', options); var usersPerPage = 10; var totalUsers = 0; - - // Fill the initial users list on document load - function initiateUsersList() { - - //// Retrieve total user counts for pagination numbering - // Data sent to WP through ajax for user counts - var data_user_count = { - action: 'retrieve_users', - nonce: $("#ef_notifications_nonce").val(), - count_users: true - }; - - jQuery.post(ajax_object.ajax_url, data_user_count) - .done(function (response) { - totalUsers = parseInt(response); - fillPaginatedUsersList(totalUsers, usersPerPage, ''); - - }) - .fail(function (xhr, status, error) { - $('#ef-post_following_users_box').prev().append('

                  There was an error. Please reload the page.

                  '); - console.log(data_user_count); - }); - - } + var totalUsersCount = $('#total-users-count').val(); function fillPaginatedUsersList(totalUsers, usersPerPage, searchKeyword) { @@ -144,7 +121,7 @@ jQuery(document).ready(function($) { } function fillUsersListByKeyword(searchKeyword) { - //// Retrieve total user counts for pagination numbering + // Data sent to WP through ajax for user counts var data_user_count = { action: 'retrieve_users', @@ -237,10 +214,10 @@ jQuery(document).ready(function($) { $('#ef-post_following_users_box').prev().append('

                  There was an error. Please reload the page.

                  '); }); - }); - initiateUsersList(); + // Fill the initial users list on document load + fillPaginatedUsersList(totalUsersCount, usersPerPage, ''); }// checks post_id }); \ No newline at end of file diff --git a/modules/user-groups/lib/user-groups.js b/modules/user-groups/lib/user-groups.js index b55568347..eece07cbe 100644 --- a/modules/user-groups/lib/user-groups.js +++ b/modules/user-groups/lib/user-groups.js @@ -30,29 +30,7 @@ jQuery(document).ready(function ($) { var userList = new List('users', options); var usersPerPage = 10; var totalUsers = 0; - - // Fill the initial users list on document load - function initiateUsersList() { - - //// Retrieve total user counts for pagination numbering - // Data sent to WP through ajax for user counts - var data_user_count = { - action: 'retrieve_users_in_usergroup', - nonce: ajax_object.ajax_nonce, - count_users: true - }; - - jQuery.post(ajax_object.ajax_url, data_user_count) - .done(function (response) { - - totalUsers = parseInt(response); - fillPaginatedUsersList(totalUsers, usersPerPage, ''); - }) - .fail(function (xhr, status, error) { - $('#ef-usergroup-users').append('

                  There was an error. Please reload the page.

                  '); - }); - - } + var totalUsersCount = $('#total-users-count').val(); function fillPaginatedUsersList(totalUsers, usersPerPage, searchKeyword) { @@ -198,8 +176,8 @@ jQuery(document).ready(function ($) { }); - initiateUsersList(); - + // Fill the initial users list on document load + fillPaginatedUsersList(totalUsersCount, usersPerPage, ''); } // check on usergroup From ffa6f9764d9978c234383760a9668a0b9b92644d Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Tue, 23 Oct 2018 23:36:31 +0700 Subject: [PATCH 28/34] remove unused codes in class-module.php --- common/php/class-module.php | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/common/php/class-module.php b/common/php/class-module.php index c2c88ad6d..e38de5e8b 100755 --- a/common/php/class-module.php +++ b/common/php/class-module.php @@ -508,18 +508,6 @@ function users_list(){ - - - - - - - - - - - -
                  Total users From c862ca4852fedb9f6e5f4c495e49c95ec2d1de6a Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Wed, 24 Oct 2018 18:46:43 +0700 Subject: [PATCH 29/34] split the user counts logic in notifications Split the counts logic to its own separate function for code clarity and performance. The ajax_retrieve_users() which called everytime users page repopulated now use get_users() which doesn't include total_count. --- modules/notifications/lib/notifications.js | 4 +- modules/notifications/notifications.php | 44 +++++++++++++++------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/modules/notifications/lib/notifications.js b/modules/notifications/lib/notifications.js index 71ad72948..04c2bc5f6 100644 --- a/modules/notifications/lib/notifications.js +++ b/modules/notifications/lib/notifications.js @@ -96,7 +96,6 @@ jQuery(document).ready(function($) { users_per_page: usersPerPage, nonce: $("#ef_notifications_nonce").val(), search_keyword: searchKeyword, - count_users: false }; jQuery.post(ajax_object.ajax_url, data, function (response) { @@ -124,9 +123,8 @@ jQuery(document).ready(function($) { // Data sent to WP through ajax for user counts var data_user_count = { - action: 'retrieve_users', + action: 'retrieve_users_count_by_keyword', nonce: $("#ef_notifications_nonce").val(), - count_users: true, search_keyword: searchKeyword }; diff --git a/modules/notifications/notifications.php b/modules/notifications/notifications.php index d8353135f..c161ba19a 100644 --- a/modules/notifications/notifications.php +++ b/modules/notifications/notifications.php @@ -105,7 +105,9 @@ function init() { add_action('wp_ajax_retrieve_users', array($this, 'ajax_retrieve_users')); //Ajax to save user notification add_action('wp_ajax_save_user_in_notification', array( $this, 'ajax_save_user_in_notification' )); - } + //Ajax for retrieving total users count by search keyword + add_action('wp_ajax_retrieve_users_count_by_keyword', array( $this, 'ajax_retrieve_users_count_by_keyword' )); + } /** * Load the capabilities onto users the first time the module is run @@ -369,7 +371,32 @@ function notifications_meta_box() { 'authors', + 'fields' => array( + 'ID', + ), + 'search' => '*' . $search_keyword .'*', + 'search_columns' => array('display_name', 'user_email'), + 'count_total' => true + ); + + $usersQuery = new WP_User_Query( $args ); + $users_count = $usersQuery->get_total(); + wp_send_json($users_count); + + } + + /** * Ajax processing for retrieving users */ function ajax_retrieve_users(){ @@ -399,16 +426,7 @@ function ajax_retrieve_users(){ 'search_columns' => array('display_name', 'user_email'), ); - $usersQuery = new WP_User_Query($args); - - $count_users = isset( $_POST['count_users']) ? filter_var($_POST['count_users'], FILTER_VALIDATE_BOOLEAN) : false; - if($count_users){ - $users_count = $usersQuery->get_total(); - wp_send_json($users_count); - } - - $users = $usersQuery->get_results(); - + $users = get_users($args); if ( ! is_array($selected)){ $selected = array(); @@ -432,7 +450,7 @@ function ajax_retrieve_users(){ array_push($users_with_selection, $user_arr); } - wp_send_json(['users' => $users_with_selection, 'users_total' => $usersQuery->get_total()]); + wp_send_json(['users' => $users_with_selection]); } From 6b383dbb5f12703bd53b958748024219ba36cc74 Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Wed, 24 Oct 2018 19:50:11 +0700 Subject: [PATCH 30/34] changed the way users count on search retrieved in user-groups.php Split the logic for retrieving users count into its own ajax endpoint. The function ajax_retrieve_users_in_usergroups() now use get_users() which is more performant as it does note do total_count. So when doing search by keyword we only do total users calculation by keyword only once, in the beginning. --- modules/user-groups/lib/user-groups.js | 7 +- modules/user-groups/user-groups.php | 124 ++++++++++++++----------- 2 files changed, 74 insertions(+), 57 deletions(-) diff --git a/modules/user-groups/lib/user-groups.js b/modules/user-groups/lib/user-groups.js index eece07cbe..d3d583403 100644 --- a/modules/user-groups/lib/user-groups.js +++ b/modules/user-groups/lib/user-groups.js @@ -56,8 +56,7 @@ jQuery(document).ready(function ($) { page: page, users_per_page: usersPerPage, nonce: ajax_object.ajax_nonce, - search_keyword: searchKeyword, - count_users: false + search_keyword: searchKeyword }; jQuery.post(ajax_object.ajax_url, data, function (response) { @@ -86,12 +85,12 @@ jQuery(document).ready(function ($) { //// Retrieve total user counts for pagination numbering // Data sent to WP through ajax for user counts var data_user_count = { - action: 'retrieve_users_in_usergroup', + action: 'retrieve_users_count_in_usergroup_by_keyword', nonce: ajax_object.ajax_nonce, - count_users: true, search_keyword: searchKeyword }; + console.log(data_user_count); jQuery.post(ajax_object.ajax_url, data_user_count, function (response) { totalUsers = parseInt(response); diff --git a/modules/user-groups/user-groups.php b/modules/user-groups/user-groups.php index 1edfee013..73012c40d 100644 --- a/modules/user-groups/user-groups.php +++ b/modules/user-groups/user-groups.php @@ -108,6 +108,8 @@ function init() { // Ajax for saving user to usergroup add_action( 'wp_ajax_save_user_to_usergroup', array( $this, 'ajax_save_user_to_usergroup' ) ); + //Ajax for retrieving total users count by search keyword + add_action( 'wp_ajax_retrieve_users_count_in_usergroup_by_keyword', array( $this, 'ajax_retrieve_users_count_in_usergroup_by_keyword' )); } @@ -651,76 +653,92 @@ function print_configure_view() { 'authors', + 'fields' => array( + 'ID', + ), + 'search' => '*' . $search_keyword .'*', + 'search_columns' => array('display_name', 'user_email'), + 'count_total' => true + ); + + $usersQuery = new WP_User_Query( $args ); + $users_count = $usersQuery->get_total(); + + wp_send_json($users_count); + + } + + /** * Ajax processing for retrieving users in usergroups. - * It can return total number of users if $count_users flag is true - * and return the users if $count_users is false */ function ajax_retrieve_users_in_usergroups(){ - check_ajax_referer('edit-flow-users-list-usergroups-ajax', 'nonce'); + check_ajax_referer('edit-flow-users-list-usergroups-ajax', 'nonce'); - // find user ids who are selected in the usergroup - $usergroup_id = isset( $_POST['usergroup_id'] ) ? intval($_POST['usergroup_id']) : 0; - $usergroup_by_id = $this->get_usergroup_by('id', $usergroup_id); - $usergroup_by_id_arr = ($usergroup_by_id !== false) ? $usergroup_by_id->to_array() : array(); - $selected = $usergroup_by_id_arr['user_ids']; + // find user ids who are selected in the usergroup + $usergroup_id = isset( $_POST['usergroup_id'] ) ? intval($_POST['usergroup_id']) : 0; + $usergroup_by_id = $this->get_usergroup_by('id', $usergroup_id); + $usergroup_by_id_arr = ($usergroup_by_id !== false) ? $usergroup_by_id->to_array() : array(); + $selected = $usergroup_by_id_arr['user_ids']; - $search_keyword = isset( $_POST['search_keyword']) ? sanitize_text_field($_POST['search_keyword']) : ''; + $search_keyword = isset( $_POST['search_keyword']) ? sanitize_text_field($_POST['search_keyword']) : ''; - $users_per_page = isset( $_POST['users_per_page']) ? intval($_POST['users_per_page']) : 0; - $page = isset( $_POST['page']) ? intval($_POST['page']) : 0; - $offset = $users_per_page * ($page - 1); + $users_per_page = isset( $_POST['users_per_page']) ? intval($_POST['users_per_page']) : 0; + $page = isset( $_POST['page']) ? intval($_POST['page']) : 0; + $offset = $users_per_page * ($page - 1); - $args = array( - 'number' => $users_per_page, - 'offset' => $offset, - 'who' => 'authors', - 'fields' => array( - 'ID', - 'display_name', - 'user_email' - ), - 'orderby' => 'display_name', - 'search' => '*' . $search_keyword .'*', - 'search_columns' => array('display_name', 'user_email'), - // 'include' => $selected - ); + $args = array( + 'number' => $users_per_page, + 'offset' => $offset, + 'who' => 'authors', + 'fields' => array( + 'ID', + 'display_name', + 'user_email' + ), + 'orderby' => 'display_name', + 'search' => '*' . $search_keyword .'*', + 'search_columns' => array('display_name', 'user_email'), + // 'include' => $selected + ); - $usersQuery = new WP_User_Query($args); + $users = get_users($args); - $count_users = isset( $_POST['count_users']) ? filter_var($_POST['count_users'], FILTER_VALIDATE_BOOLEAN) : false; - if($count_users){ - $users_count = $usersQuery->get_total(); - wp_send_json($users_count); - } - $users = $usersQuery->get_results(); + if ( ! is_array($selected)){ + $selected = array(); + } + // Compile users with selected users on top of the list + $users_with_selection = array(); - if ( ! is_array($selected)){ - $selected = array(); - } + foreach ($users as $user){ - // Compile users with selected users on top of the list - $users_with_selection = array(); + $user_arr['user-item-id'] = $user->ID; + $user_arr['user-item-name'] = $user->display_name; + $user_arr['user-item-email'] = $user->user_email; - foreach ($users as $user){ + if ( in_array($user->ID, $selected) ){ + $user_arr['user_checked'] = true; + } else { + $user_arr['user_checked'] = false; + } - $user_arr['user-item-id'] = $user->ID; - $user_arr['user-item-name'] = $user->display_name; - $user_arr['user-item-email'] = $user->user_email; - - if ( in_array($user->ID, $selected) ){ - $user_arr['user_checked'] = true; - } else { - $user_arr['user_checked'] = false; - } - - array_push($users_with_selection, $user_arr); - } + array_push($users_with_selection, $user_arr); + } - wp_send_json(['users' => $users_with_selection, 'users_total' => $usersQuery->get_total()]); + wp_send_json(['users' => $users_with_selection]); } From 9eb6ee61f7a725e9699b7bc8ae857217411bf3a6 Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Wed, 24 Oct 2018 19:52:15 +0700 Subject: [PATCH 31/34] remove console.log --- modules/user-groups/lib/user-groups.js | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/user-groups/lib/user-groups.js b/modules/user-groups/lib/user-groups.js index d3d583403..c4ffc1dcf 100644 --- a/modules/user-groups/lib/user-groups.js +++ b/modules/user-groups/lib/user-groups.js @@ -90,7 +90,6 @@ jQuery(document).ready(function ($) { search_keyword: searchKeyword }; - console.log(data_user_count); jQuery.post(ajax_object.ajax_url, data_user_count, function (response) { totalUsers = parseInt(response); From 3d5550c8982d8f61e3bbbed54b513338f52cc9ad Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Wed, 24 Oct 2018 19:56:19 +0700 Subject: [PATCH 32/34] fix spacing in users_list() --- common/php/class-module.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/common/php/class-module.php b/common/php/class-module.php index e38de5e8b..45ab29682 100755 --- a/common/php/class-module.php +++ b/common/php/class-module.php @@ -488,25 +488,25 @@ function users_select_form( $selected = null, $args = null ) { */ function users_list(){ - // Get the count of all authors, the count is used to initialize users list + // Get the count of all authors, the count is used to initialize users list + $args = array( + 'who' => 'authors', + 'fields' => array( + 'ID', + ), + ); - $args = array( - 'who' => 'authors', - 'fields' => array( - 'ID', - ), - ); + $usersQuery = new WP_User_Query( array('who' => 'authors', 'fields' => 'ID') ); + $users_count = $usersQuery->get_total(); - $usersQuery = new WP_User_Query( array('who' => 'authors', 'fields' => 'ID') ); - $users_count = $usersQuery->get_total(); + ?> - ?>
                  - +
                  Total users @@ -517,8 +517,8 @@ function users_list(){
                    - Date: Wed, 24 Oct 2018 20:09:46 +0700 Subject: [PATCH 33/34] fix spacings --- modules/notifications/lib/notifications.js | 409 ++++++++++----------- modules/notifications/notifications.php | 4 +- modules/user-groups/lib/user-groups.js | 332 ++++++++--------- modules/user-groups/user-groups.php | 5 +- 4 files changed, 360 insertions(+), 390 deletions(-) diff --git a/modules/notifications/lib/notifications.js b/modules/notifications/lib/notifications.js index 04c2bc5f6..e4cd837b0 100644 --- a/modules/notifications/lib/notifications.js +++ b/modules/notifications/lib/notifications.js @@ -1,221 +1,208 @@ -jQuery(document).ready(function($) { +jQuery( document ).ready( function( $ ) { // $('#ef-post_following_users_box ul').listFilterizer(); - var post_id = $('#post_ID').val(); - - // check post_id, only run the following JS if it is in post page - if (post_id !== undefined) { - - var params = { - action: 'save_notifications', - post_id: post_id, - }; - - $(document).on('click', '.ef-post_following_list li input:checkbox, .ef-following_usergroups li input:checkbox', function () { - var user_group_ids = []; - var parent_this = $(this); - params.ef_notifications_name = $(this).attr('name'); - params._nonce = $("#ef_notifications_nonce").val(); - - $(this) - .parent() - .parent() - .parent() - .find('input:checked') - .map(function () { - user_group_ids.push($(this).val()); - }) - - params.user_group_ids = user_group_ids; - - $.ajax({ - type: 'POST', - url: (ajaxurl) ? ajaxurl : wpListL10n.url, - data: params, - success: function (x) { - - // This event is used to show an updated list of who will be notified of editorial comments and status updates. - $('#ef-post_following_box').trigger('following_list_updated'); - - var backgroundColor = parent_this.css('background-color'); - $(parent_this.parent().parent()) - .animate({'backgroundColor': '#CCEEBB'}, 200) - .animate({'backgroundColor': backgroundColor}, 200); - }, - error: function (r) { - $('#ef-post_following_users_box').prev().append('

                    There was an error. Please reload the page.

                    '); - } - }); - }); - - //// Users list for notifications meta - - // Options for the list - var options = { - // values used for filters - valueNames: ['user-item-name', 'user-item-email', { - name: 'user_checked', - attr: '' - }, {data: ['user-item-id']}], - - // searchClass is used for filtering values in the list - searchClass: 'filter-users', - - // item used for user list template - item: '
                  • ' - }; - - // Initialize the list.js, 'users' is the html class name to fill in the users list - var userList = new List('users', options); - var usersPerPage = 10; - var totalUsers = 0; - var totalUsersCount = $('#total-users-count').val(); - - function fillPaginatedUsersList(totalUsers, usersPerPage, searchKeyword) { - - // remove pagination if it existed - if ($('#users-pagination').data("twbs-pagination")) { - $('#users-pagination').twbsPagination('destroy'); - } - - $('#users-pagination').twbsPagination({ - totalPages: Math.ceil(totalUsers / usersPerPage), // The total number of user pages - visiblePages: usersPerPage, // Number of users displayed in a page - next: 'Next', - prev: 'Prev', - onPageClick: function (event, page) { - - // clear the users list when the page created - userList.clear(); - - // Data sent to WP through ajax for paginated users list - var data = { - action: 'retrieve_users', - post_id: $('#post_ID').val(), - page: page, - users_per_page: usersPerPage, - nonce: $("#ef_notifications_nonce").val(), - search_keyword: searchKeyword, - }; - - jQuery.post(ajax_object.ajax_url, data, function (response) { - // Add the users retrieved from wordpress db to list - for (var user of response.users) { - userList.add(user); - if (user.user_checked) { - $('li[data-user-item-id=' + user['user-item-id'] + '] input:checkbox').prop("checked", true); - } - } - - // Fill in users count info - $('.users-total-info-value').text(totalUsers); - if (searchKeyword !== '') { - $('.users-total-info-text').text('Totals users found'); - } - - }); - - } - }); - } - - function fillUsersListByKeyword(searchKeyword) { - - // Data sent to WP through ajax for user counts - var data_user_count = { - action: 'retrieve_users_count_by_keyword', - nonce: $("#ef_notifications_nonce").val(), - search_keyword: searchKeyword - }; - - jQuery.post(ajax_object.ajax_url, data_user_count, function (response) { - - totalUsers = parseInt(response); - - if (totalUsers > 0) { - fillPaginatedUsersList(totalUsers, usersPerPage, searchKeyword); - } else { - $('#users-pagination').twbsPagination('destroy'); - $('.users-total-info-text').text('Totals users found'); - $('.users-total-info-value').text(totalUsers); - - } - }); - } - - $('.search-users').bind('keypress', function (e) { - if (e.keyCode == 13) { - clearTimeout($.data(this, 'timer')); - - e.preventDefault(); - var searchKeyword = $('.search-users').val(); - userList.clear(); - - var wait = setTimeout(fillUsersListByKeyword(searchKeyword), 10000); - - $(this).data('timer', wait); - - } - }); - - $('.btn-search-users').click(function (e) { - clearTimeout($.data(this, 'timer')); - - e.preventDefault(); - var searchKeyword = $('.search-users').val(); - userList.clear(); - - var wait = setTimeout(fillUsersListByKeyword(searchKeyword), 10000); - - $(this).data('timer', wait); - - }); - - $(document).on('click', '.user-item', function (e) { - - var item_element = $(this); - var checkbox = item_element.find("input[type='checkbox']"); - - // check the checkbox when .user-item element is clicked - if (!$(e.target).is(':checkbox') && !checkbox.is(':checked')) { - checkbox.attr('checked', true); - } else if ((!$(e.target).is(':checkbox') && checkbox.is(':checked'))) { - checkbox.attr('checked', false); - } - - var data = { - action: 'save_user_in_notification', - post_id: post_id, - nonce: $("#ef_notifications_nonce").val(), - user_id: $(this).data('user-item-id') + var post_id = $( '#post_ID' ).val(); + + // check post_id, only run the following JS if it is in post page + if ( post_id !== undefined ) { + var params = { + action: 'save_notifications', + post_id: post_id, + }; + + $( document ).on( 'click', '.ef-post_following_list li input:checkbox, .ef-following_usergroups li input:checkbox', function() { + var user_group_ids = []; + var parent_this = $( this ); + params.ef_notifications_name = $( this ).attr( 'name' ); + params._nonce = $( '#ef_notifications_nonce' ).val(); + + $( this ) + .parent() + .parent() + .parent() + .find( 'input:checked' ) + .map( function() { + user_group_ids.push( $( this ).val() ); + } ); + + params.user_group_ids = user_group_ids; + + $.ajax( { + type: 'POST', + url: ( ajaxurl ) ? ajaxurl : wpListL10n.url, + data: params, + success: function( x ) { + // This event is used to show an updated list of who will be notified of editorial comments and status updates. + $( '#ef-post_following_box' ).trigger( 'following_list_updated' ); + + var backgroundColor = parent_this.css( 'background-color' ); + $( parent_this.parent().parent() ) + .animate( { backgroundColor: '#CCEEBB' }, 200 ) + .animate( { backgroundColor: backgroundColor }, 200 ); + }, + error: function( r ) { + $( '#ef-post_following_users_box' ).prev().append( '

                    There was an error. Please reload the page.

                    ' ); + }, + } ); + } ); + + //// Users list for notifications meta + + // Options for the list + var options = { + // values used for filters + valueNames: [ 'user-item-name', 'user-item-email', { + name: 'user_checked', + attr: '', + }, { data: [ 'user-item-id' ] } ], + + // searchClass is used for filtering values in the list + searchClass: 'filter-users', + + // item used for user list template + item: '
                  • ', + }; + + // Initialize the list.js, 'users' is the html class name to fill in the users list + var userList = new List( 'users', options ); + var usersPerPage = 10; + var totalUsers = 0; + var totalUsersCount = $( '#total-users-count' ).val(); + + function fillPaginatedUsersList( totalUsers, usersPerPage, searchKeyword ) { + // remove pagination if it existed + if ( $( '#users-pagination' ).data( 'twbs-pagination' ) ) { + $( '#users-pagination' ).twbsPagination( 'destroy' ); } - // add the user to notification if the checkbox checked or remove if unchecked - if (checkbox.is(':checked')) { - data.follow = true; - } else { - data.follow = false; + $( '#users-pagination' ).twbsPagination( { + totalPages: Math.ceil( totalUsers / usersPerPage ), // The total number of user pages + visiblePages: usersPerPage, // Number of users displayed in a page + next: 'Next', + prev: 'Prev', + onPageClick: function( event, page ) { + // clear the users list when the page created + userList.clear(); + + // Data sent to WP through ajax for paginated users list + var data = { + action: 'retrieve_users', + post_id: $( '#post_ID' ).val(), + page: page, + users_per_page: usersPerPage, + nonce: $( '#ef_notifications_nonce' ).val(), + search_keyword: searchKeyword, + }; + + jQuery.post( ajax_object.ajax_url, data, function( response ) { + // Add the users retrieved from wordpress db to list + for ( var user of response.users ) { + userList.add( user ); + if ( user.user_checked ) { + $( 'li[data-user-item-id=' + user[ 'user-item-id' ] + '] input:checkbox' ).prop( 'checked', true ); + } + } + + // Fill in users count info + $( '.users-total-info-value' ).text( totalUsers ); + if ( searchKeyword !== '' ) { + $( '.users-total-info-text' ).text( 'Totals users found' ); + } + } ); + }, + } ); + } + + function fillUsersListByKeyword( searchKeyword ) { + // Data sent to WP through ajax for user counts + var data_user_count = { + action: 'retrieve_users_count_by_keyword', + nonce: $( '#ef_notifications_nonce' ).val(), + // count_users: true, + search_keyword: searchKeyword, + }; + + jQuery.post( ajax_object.ajax_url, data_user_count, function( response ) { + totalUsers = parseInt( response ); + + if ( totalUsers > 0 ) { + fillPaginatedUsersList( totalUsers, usersPerPage, searchKeyword ); + } else { + $( '#users-pagination' ).twbsPagination( 'destroy' ); + $( '.users-total-info-text' ).text( 'Totals users found' ); + $( '.users-total-info-value' ).text( totalUsers ); + } + } ); + } + + $( '.search-users' ).bind( 'keypress', function( e ) { + if ( e.keyCode == 13 ) { + clearTimeout( $.data( this, 'timer' ) ); + + e.preventDefault(); + var searchKeyword = $( '.search-users' ).val(); + userList.clear(); + + var wait = setTimeout( fillUsersListByKeyword( searchKeyword ), 10000 ); + + $( this ).data( 'timer', wait ); } + } ); + + $( '.btn-search-users' ).click( function( e ) { + clearTimeout( $.data( this, 'timer' ) ); + + e.preventDefault(); + var searchKeyword = $( '.search-users' ).val(); + userList.clear(); + + var wait = setTimeout( fillUsersListByKeyword( searchKeyword ), 10000 ); - jQuery.post(ajaxurl, data) - .done(function (response) { - // This event is used to show an updated list of who will be notified of editorial comments and status updates. - $('#ef-post_following_box').trigger('following_list_updated'); + $( this ).data( 'timer', wait ); + } ); - // Trigger visual effect when ajax successful - var backgroundColor = item_element.parent().css('background-color'); - item_element - .animate({'backgroundColor': '#CCEEBB'}, 200) - .animate({'backgroundColor': backgroundColor}, 200); - }) - .fail(function (xhr, status, error) { - $('#ef-post_following_users_box').prev().append('

                    There was an error. Please reload the page.

                    '); - }); + $( document ).on( 'click', '.user-item', function( e ) { + var item_element = $( this ); + var checkbox = item_element.find( "input[type='checkbox']" ); - }); + // check the checkbox when .user-item element is clicked + if ( ! $( e.target ).is( ':checkbox' ) && ! checkbox.is( ':checked' ) ) { + checkbox.attr( 'checked', true ); + } else if ( ( ! $( e.target ).is( ':checkbox' ) && checkbox.is( ':checked' ) ) ) { + checkbox.attr( 'checked', false ); + } - // Fill the initial users list on document load - fillPaginatedUsersList(totalUsersCount, usersPerPage, ''); + var data = { + action: 'save_user_in_notification', + post_id: post_id, + nonce: $( '#ef_notifications_nonce' ).val(), + user_id: $( this ).data( 'user-item-id' ), + }; + + // add the user to notification if the checkbox checked or remove if unchecked + if ( checkbox.is( ':checked' ) ) { + data.follow = true; + } else { + data.follow = false; + } - }// checks post_id -}); \ No newline at end of file + jQuery.post( ajaxurl, data ) + .done( function( response ) { + // This event is used to show an updated list of who will be notified of editorial comments and status updates. + $( '#ef-post_following_box' ).trigger( 'following_list_updated' ); + + // Trigger visual effect when ajax successful + var backgroundColor = item_element.parent().css( 'background-color' ); + item_element + .animate( { backgroundColor: '#CCEEBB' }, 200 ) + .animate( { backgroundColor: backgroundColor }, 200 ); + } ) + .fail( function( xhr, status, error ) { + $( '#ef-post_following_users_box' ).prev().append( '

                    There was an error. Please reload the page.

                    ' ); + } ); + } ); + + // Fill the initial users list on document load + fillPaginatedUsersList( totalUsersCount, usersPerPage, '' ); + }// checks post_id +} ); diff --git a/modules/notifications/notifications.php b/modules/notifications/notifications.php index c161ba19a..3ba5c4aad 100644 --- a/modules/notifications/notifications.php +++ b/modules/notifications/notifications.php @@ -105,8 +105,8 @@ function init() { add_action('wp_ajax_retrieve_users', array($this, 'ajax_retrieve_users')); //Ajax to save user notification add_action('wp_ajax_save_user_in_notification', array( $this, 'ajax_save_user_in_notification' )); - //Ajax for retrieving total users count by search keyword - add_action('wp_ajax_retrieve_users_count_by_keyword', array( $this, 'ajax_retrieve_users_count_by_keyword' )); + //Ajax for retrieving total users count by search keyword + add_action('wp_ajax_retrieve_users_count_by_keyword', array( $this, 'ajax_retrieve_users_count_by_keyword' )); } /** diff --git a/modules/user-groups/lib/user-groups.js b/modules/user-groups/lib/user-groups.js index c4ffc1dcf..72463bd63 100644 --- a/modules/user-groups/lib/user-groups.js +++ b/modules/user-groups/lib/user-groups.js @@ -1,4 +1,4 @@ -jQuery(document).ready(function ($) { +jQuery( document ).ready( function( $ ) { // jQuery('ul#ef-post_following_users li').quicksearch({ // position: 'before', // attached: 'ul#ef-post_following_users', @@ -7,176 +7,160 @@ jQuery(document).ready(function ($) { // }) // jQuery('#ef-usergroup-users ul').listFilterizer(); - var usergroup_id = $('#usergroup_id').val(); - - if( usergroup_id !== undefined ){ - - // Options for the list - var options = { - // values used for filters - valueNames: ['user-item-name', 'user-item-email', { - name: 'user_checked', - attr: '' - }, {data: ['user-item-id']}], - - // searchClass is used for filtering values in the list - searchClass: 'filter-users', - - // item used for user list template - item: '
                  • ' - }; - - // Initialize the list.js, 'users' is the html class name to fill in the users list - var userList = new List('users', options); - var usersPerPage = 10; - var totalUsers = 0; - var totalUsersCount = $('#total-users-count').val(); - - function fillPaginatedUsersList(totalUsers, usersPerPage, searchKeyword) { - - // remove pagination if it existed - if ($('#users-pagination').data("twbs-pagination")) { - $('#users-pagination').twbsPagination('destroy'); - } - - $('#users-pagination').twbsPagination({ - totalPages: Math.ceil(totalUsers / usersPerPage), // The total number of user pages - visiblePages: usersPerPage, // Number of users displayed in a page - next: 'Next', - prev: 'Prev', - onPageClick: function (event, page) { - - // clear the users list when the page created - userList.clear(); - - // Data sent to WP through ajax for paginated users list - var data = { - action: 'retrieve_users_in_usergroup', - usergroup_id: usergroup_id, - page: page, - users_per_page: usersPerPage, - nonce: ajax_object.ajax_nonce, - search_keyword: searchKeyword - }; - - jQuery.post(ajax_object.ajax_url, data, function (response) { - - // Add the users retrieved from wordpress db to list - for (var user of response.users) { - userList.add(user); - if (user.user_checked) { - $('li[data-user-item-id=' + user['user-item-id'] + '] input:checkbox').prop("checked", true); - } - } - - // Fill in users count info - $('.users-total-info-value').text(totalUsers); - if (searchKeyword !== '') { - $('.users-total-info-text').text('Totals users found'); - } - - }); - - } - }); - } - - function fillUsersListByKeyword(searchKeyword) { - //// Retrieve total user counts for pagination numbering - // Data sent to WP through ajax for user counts - var data_user_count = { - action: 'retrieve_users_count_in_usergroup_by_keyword', - nonce: ajax_object.ajax_nonce, - search_keyword: searchKeyword - }; - - jQuery.post(ajax_object.ajax_url, data_user_count, function (response) { - - totalUsers = parseInt(response); - - if (totalUsers > 0) { - fillPaginatedUsersList(totalUsers, usersPerPage, searchKeyword); - } else { - $('#users-pagination').twbsPagination('destroy'); - $('.users-total-info-text').text('Totals users found'); - $('.users-total-info-value').text(totalUsers); - - } - }); - } - - $('.search-users').bind('keypress', function (e) { - if (e.keyCode == 13) { - clearTimeout($.data(this, 'timer')); - - e.preventDefault(); - var searchKeyword = $('.search-users').val(); - userList.clear(); - - var wait = setTimeout(fillUsersListByKeyword(searchKeyword), 10000); - - $(this).data('timer', wait); - - } - }); - - $('.btn-search-users').click(function (e) { - clearTimeout($.data(this, 'timer')); - - e.preventDefault(); - var searchKeyword = $('.search-users').val(); - userList.clear(); - - var wait = setTimeout(fillUsersListByKeyword(searchKeyword), 10000); - - $(this).data('timer', wait); - - }); - - $(document).on('click', '.user-item', function (e) { - - var item_element = $(this); - var checkbox = item_element.find("input[type='checkbox']"); - - // check the checkbox when .user-item element is clicked - if (!$(e.target).is(':checkbox') && !checkbox.is(':checked')) { - checkbox.attr('checked', true); - } else if ((!$(e.target).is(':checkbox') && checkbox.is(':checked'))) { - checkbox.attr('checked', false); - } - - var params = { - action: 'save_user_to_usergroup', - usergroup_id: usergroup_id, - nonce: ajax_object.ajax_nonce, - user_id: ($(this).data('user-item-id')), - }; - - if (checkbox.is(':checked')) { - params.add = true; - } else { - params.remove = true; - } - - jQuery.post(ajaxurl, params) - .done(function (response) { - - // Trigger visual effect when ajax successful - var backgroundColor = item_element.parent().css('background-color'); - item_element - .animate({'backgroundColor': '#CCEEBB'}, 200) - .animate({'backgroundColor': backgroundColor}, 200); - }) - .fail(function (xhr, status, error) { - $('#ef-post_following_users_box').prev().append('

                    There was an error. Please reload the page.

                    '); - }); - - - }); - - // Fill the initial users list on document load - fillPaginatedUsersList(totalUsersCount, usersPerPage, ''); - - } // check on usergroup - -}); \ No newline at end of file + var usergroup_id = $( '#usergroup_id' ).val(); + + if ( usergroup_id !== undefined ) { + // Options for the list + var options = { + // values used for filters + valueNames: [ 'user-item-name', 'user-item-email', { + name: 'user_checked', + attr: '', + }, { data: [ 'user-item-id' ] } ], + + // searchClass is used for filtering values in the list + searchClass: 'filter-users', + + // item used for user list template + item: '
                  • ', + }; + + // Initialize the list.js, 'users' is the html class name to fill in the users list + var userList = new List( 'users', options ); + var usersPerPage = 10; + var totalUsers = 0; + var totalUsersCount = $( '#total-users-count' ).val(); + + function fillPaginatedUsersList( totalUsers, usersPerPage, searchKeyword ) { + // remove pagination if it existed + if ( $( '#users-pagination' ).data( 'twbs-pagination' ) ) { + $( '#users-pagination' ).twbsPagination( 'destroy' ); + } + + $( '#users-pagination' ).twbsPagination( { + totalPages: Math.ceil( totalUsers / usersPerPage ), // The total number of user pages + visiblePages: usersPerPage, // Number of users displayed in a page + next: 'Next', + prev: 'Prev', + onPageClick: function( event, page ) { + // clear the users list when the page created + userList.clear(); + + // Data sent to WP through ajax for paginated users list + var data = { + action: 'retrieve_users_in_usergroup', + usergroup_id: usergroup_id, + page: page, + users_per_page: usersPerPage, + nonce: ajax_object.ajax_nonce, + search_keyword: searchKeyword, + }; + + jQuery.post( ajax_object.ajax_url, data, function( response ) { + // Add the users retrieved from wordpress db to list + for ( var user of response.users ) { + userList.add( user ); + if ( user.user_checked ) { + $( 'li[data-user-item-id=' + user[ 'user-item-id' ] + '] input:checkbox' ).prop( 'checked', true ); + } + } + + // Fill in users count info + $( '.users-total-info-value' ).text( totalUsers ); + if ( searchKeyword !== '' ) { + $( '.users-total-info-text' ).text( 'Totals users found' ); + } + } ); + }, + } ); + } + + function fillUsersListByKeyword( searchKeyword ) { + //// Retrieve total user counts for pagination numbering + // Data sent to WP through ajax for user counts + var data_user_count = { + action: 'retrieve_users_count_in_usergroup_by_keyword', + nonce: ajax_object.ajax_nonce, + search_keyword: searchKeyword, + }; + + jQuery.post( ajax_object.ajax_url, data_user_count, function( response ) { + totalUsers = parseInt( response ); + + if ( totalUsers > 0 ) { + fillPaginatedUsersList( totalUsers, usersPerPage, searchKeyword ); + } else { + $( '#users-pagination' ).twbsPagination( 'destroy' ); + $( '.users-total-info-text' ).text( 'Totals users found' ); + $( '.users-total-info-value' ).text( totalUsers ); + } + } ); + } + + $( '.search-users' ).bind( 'keypress', function( e ) { + if ( e.keyCode == 13 ) { + clearTimeout( $.data( this, 'timer' ) ); + + e.preventDefault(); + var searchKeyword = $( '.search-users' ).val(); + userList.clear(); + + var wait = setTimeout( fillUsersListByKeyword( searchKeyword ), 10000 ); + + $( this ).data( 'timer', wait ); + } + } ); + + $( '.btn-search-users' ).click( function( e ) { + clearTimeout( $.data( this, 'timer' ) ); + + e.preventDefault(); + var searchKeyword = $( '.search-users' ).val(); + userList.clear(); + + var wait = setTimeout( fillUsersListByKeyword( searchKeyword ), 10000 ); + + $( this ).data( 'timer', wait ); + } ); + + $( document ).on( 'click', '.user-item', function( e ) { + var item_element = $( this ); + var checkbox = item_element.find( "input[type='checkbox']" ); + + // check the checkbox when .user-item element is clicked + if ( ! $( e.target ).is( ':checkbox' ) && ! checkbox.is( ':checked' ) ) { + checkbox.attr( 'checked', true ); + } else if ( ( ! $( e.target ).is( ':checkbox' ) && checkbox.is( ':checked' ) ) ) { + checkbox.attr( 'checked', false ); + } + + var params = { + action: 'save_user_to_usergroup', + usergroup_id: usergroup_id, + nonce: ajax_object.ajax_nonce, + user_id: ( $( this ).data( 'user-item-id' ) ), + }; + + if ( checkbox.is( ':checked' ) ) { + params.add = true; + } else { + params.remove = true; + } + + jQuery.post( ajaxurl, params ) + .done( function( response ) { + // Trigger visual effect when ajax successful + var backgroundColor = item_element.parent().css( 'background-color' ); + item_element + .animate( { backgroundColor: '#CCEEBB' }, 200 ) + .animate( { backgroundColor: backgroundColor }, 200 ); + } ) + .fail( function( xhr, status, error ) { + $( '#ef-post_following_users_box' ).prev().append( '

                    There was an error. Please reload the page.

                    ' ); + } ); + } ); + + // Fill the initial users list on document load + fillPaginatedUsersList( totalUsersCount, usersPerPage, '' ); + } // check on usergroup +} ); diff --git a/modules/user-groups/user-groups.php b/modules/user-groups/user-groups.php index 73012c40d..67669fe80 100644 --- a/modules/user-groups/user-groups.php +++ b/modules/user-groups/user-groups.php @@ -108,8 +108,8 @@ function init() { // Ajax for saving user to usergroup add_action( 'wp_ajax_save_user_to_usergroup', array( $this, 'ajax_save_user_to_usergroup' ) ); - //Ajax for retrieving total users count by search keyword - add_action( 'wp_ajax_retrieve_users_count_in_usergroup_by_keyword', array( $this, 'ajax_retrieve_users_count_in_usergroup_by_keyword' )); + //Ajax for retrieving total users count by search keyword + add_action( 'wp_ajax_retrieve_users_count_in_usergroup_by_keyword', array( $this, 'ajax_retrieve_users_count_in_usergroup_by_keyword' )); } @@ -715,7 +715,6 @@ function ajax_retrieve_users_in_usergroups(){ $users = get_users($args); - if ( ! is_array($selected)){ $selected = array(); } From ccbc0ffd82472c7af2acbe748c9db44e85ae495e Mon Sep 17 00:00:00 2001 From: Indra Lukmana Date: Mon, 5 Nov 2018 20:13:58 +0700 Subject: [PATCH 34/34] Add comments Add additional comments fro explaining functions --- common/php/class-module.php | 2 +- modules/notifications/lib/notifications.js | 23 ++++++++++++++++++---- modules/notifications/notifications.php | 6 +++--- modules/user-groups/lib/user-groups.js | 22 ++++++++++++++++++--- modules/user-groups/user-groups.php | 5 ++--- 5 files changed, 44 insertions(+), 14 deletions(-) diff --git a/common/php/class-module.php b/common/php/class-module.php index 45ab29682..f6d9ec19b 100755 --- a/common/php/class-module.php +++ b/common/php/class-module.php @@ -484,7 +484,7 @@ function users_select_form( $selected = null, $args = null ) { } /* - * Template for paginated users list + * Template for displaying paginated users list in notification and user group */ function users_list(){ diff --git a/modules/notifications/lib/notifications.js b/modules/notifications/lib/notifications.js index e4cd837b0..fe873a772 100644 --- a/modules/notifications/lib/notifications.js +++ b/modules/notifications/lib/notifications.js @@ -46,8 +46,6 @@ jQuery( document ).ready( function( $ ) { } ); } ); - //// Users list for notifications meta - // Options for the list var options = { // values used for filters @@ -67,8 +65,16 @@ jQuery( document ).ready( function( $ ) { var userList = new List( 'users', options ); var usersPerPage = 10; var totalUsers = 0; - var totalUsersCount = $( '#total-users-count' ).val(); - + var totalUsersCount = $( '#total-users-count' ).val(); //embedded total users in the hidden html + + /** + * The function will show paginated users list. Each users page will show a number of users defined by the parameter. + * Total users pages will be calculated by dividing totalUsers with usersPerPage. Each users page retrieved using ajax. + * + * @param {number} totalUsers Total users related to the search keyword + * @param {number} usersPerPage Total user shown in a users page + * @param {string} searchKeyword The keyword for users to be shown in the page + */ function fillPaginatedUsersList( totalUsers, usersPerPage, searchKeyword ) { // remove pagination if it existed if ( $( '#users-pagination' ).data( 'twbs-pagination' ) ) { @@ -113,6 +119,12 @@ jQuery( document ).ready( function( $ ) { } ); } + /** + * This will populate users based on a keyword. First it will retrieve the count of users based on the keyword. + * The count then will be used as base to calculate pagination related variables in fillPaginatedUsersList + * + * @param {string} searchKeyword Text based on users for to be shown in the users list. Can contain wildcard. + */ function fillUsersListByKeyword( searchKeyword ) { // Data sent to WP through ajax for user counts var data_user_count = { @@ -135,6 +147,7 @@ jQuery( document ).ready( function( $ ) { } ); } + // jQuery bind to search users when pressing Enter key $( '.search-users' ).bind( 'keypress', function( e ) { if ( e.keyCode == 13 ) { clearTimeout( $.data( this, 'timer' ) ); @@ -149,6 +162,7 @@ jQuery( document ).ready( function( $ ) { } } ); + // jQuery binding search button click $( '.btn-search-users' ).click( function( e ) { clearTimeout( $.data( this, 'timer' ) ); @@ -161,6 +175,7 @@ jQuery( document ).ready( function( $ ) { $( this ).data( 'timer', wait ); } ); + // Ajax for saving checked/unchecked user $( document ).on( 'click', '.user-item', function( e ) { var item_element = $( this ); var checkbox = item_element.find( "input[type='checkbox']" ); diff --git a/modules/notifications/notifications.php b/modules/notifications/notifications.php index 3ba5c4aad..550f7a868 100644 --- a/modules/notifications/notifications.php +++ b/modules/notifications/notifications.php @@ -372,7 +372,7 @@ function notifications_meta_box() { } /** - * Ajax for retrieving the total count of users + * Ajax endpoint for retrieving the total count of users in notification */ function ajax_retrieve_users_count_by_keyword(){ @@ -397,7 +397,7 @@ function ajax_retrieve_users_count_by_keyword(){ } /** - * Ajax processing for retrieving users + * Ajax endpoint for retrieving users in notification */ function ajax_retrieve_users(){ @@ -463,7 +463,7 @@ function ajax_save_user_in_notification(){ $user_id = isset( $_POST['user_id']) ? intval( $_POST['user_id'] ) : 0; $follow = isset( $_POST['follow']) ? filter_var($_POST['follow'], FILTER_VALIDATE_BOOLEAN) : false; - //// Add selected user, current user, and author to notification if they are set to receive notifications + // Add selected user, current user, and author to notification if they are set to receive notifications $users = array(); $users[] = $user_id; diff --git a/modules/user-groups/lib/user-groups.js b/modules/user-groups/lib/user-groups.js index 72463bd63..48e671121 100644 --- a/modules/user-groups/lib/user-groups.js +++ b/modules/user-groups/lib/user-groups.js @@ -29,8 +29,16 @@ jQuery( document ).ready( function( $ ) { var userList = new List( 'users', options ); var usersPerPage = 10; var totalUsers = 0; - var totalUsersCount = $( '#total-users-count' ).val(); - + var totalUsersCount = $( '#total-users-count' ).val(); //embedded total users in the hidden html + + /** + * The function will show paginated users list. Each users page will show a number of users defined by the parameter. + * Total users pages will be calculated by dividing totalUsers with usersPerPage. Each users page retrieved using ajax. + * + * @param {number} totalUsers Total users related to the search keyword + * @param {number} usersPerPage Total user shown in a users page + * @param {string} searchKeyword The keyword for users to be shown in the page + */ function fillPaginatedUsersList( totalUsers, usersPerPage, searchKeyword ) { // remove pagination if it existed if ( $( '#users-pagination' ).data( 'twbs-pagination' ) ) { @@ -75,8 +83,13 @@ jQuery( document ).ready( function( $ ) { } ); } + /** + * This will populate users based on a keyword. First it will retrieve the count of users based on the keyword. + * The count then will be used as base to calculate pagination related variables in fillPaginatedUsersList + * + * @param {string} searchKeyword Text based on users for to be shown in the users list. Can contain wildcard. + */ function fillUsersListByKeyword( searchKeyword ) { - //// Retrieve total user counts for pagination numbering // Data sent to WP through ajax for user counts var data_user_count = { action: 'retrieve_users_count_in_usergroup_by_keyword', @@ -97,6 +110,7 @@ jQuery( document ).ready( function( $ ) { } ); } + // jQuery bind to search users when pressing Enter key $( '.search-users' ).bind( 'keypress', function( e ) { if ( e.keyCode == 13 ) { clearTimeout( $.data( this, 'timer' ) ); @@ -111,6 +125,7 @@ jQuery( document ).ready( function( $ ) { } } ); + // jQuery binding search button click $( '.btn-search-users' ).click( function( e ) { clearTimeout( $.data( this, 'timer' ) ); @@ -123,6 +138,7 @@ jQuery( document ).ready( function( $ ) { $( this ).data( 'timer', wait ); } ); + // Ajax for saving checked/unchecked user $( document ).on( 'click', '.user-item', function( e ) { var item_element = $( this ); var checkbox = item_element.find( "input[type='checkbox']" ); diff --git a/modules/user-groups/user-groups.php b/modules/user-groups/user-groups.php index 67669fe80..45438e7ac 100644 --- a/modules/user-groups/user-groups.php +++ b/modules/user-groups/user-groups.php @@ -654,7 +654,7 @@ function print_configure_view() { } /** - * Ajax for retrieving the total count of users + * Ajax endpoint for retrieving the total count of users */ function ajax_retrieve_users_count_in_usergroup_by_keyword(){ @@ -680,7 +680,7 @@ function ajax_retrieve_users_count_in_usergroup_by_keyword(){ } /** - * Ajax processing for retrieving users in usergroups. + * Ajax endpoint for retrieving users in usergroups. */ function ajax_retrieve_users_in_usergroups(){ @@ -719,7 +719,6 @@ function ajax_retrieve_users_in_usergroups(){ $selected = array(); } - // Compile users with selected users on top of the list $users_with_selection = array(); foreach ($users as $user){