diff options
Diffstat (limited to 'client/lib')
-rw-r--r-- | client/lib/accessibility.js | 5 | ||||
-rw-r--r-- | client/lib/cssEvents.js | 20 | ||||
-rw-r--r-- | client/lib/datepicker.js | 102 | ||||
-rw-r--r-- | client/lib/dropImage.js | 13 | ||||
-rw-r--r-- | client/lib/escapeActions.js | 48 | ||||
-rw-r--r-- | client/lib/filter.js | 434 | ||||
-rw-r--r-- | client/lib/i18n.js | 2 | ||||
-rw-r--r-- | client/lib/inlinedform.js | 50 | ||||
-rwxr-xr-x | client/lib/keyboard.js | 67 | ||||
-rw-r--r-- | client/lib/modal.js | 16 | ||||
-rw-r--r-- | client/lib/multiSelection.js | 48 | ||||
-rw-r--r-- | client/lib/pasteImage.js | 16 | ||||
-rw-r--r-- | client/lib/popup.js | 31 | ||||
-rw-r--r-- | client/lib/textComplete.js | 9 | ||||
-rw-r--r-- | client/lib/unsavedEdits.js | 6 | ||||
-rw-r--r-- | client/lib/utils.js | 78 |
16 files changed, 500 insertions, 445 deletions
diff --git a/client/lib/accessibility.js b/client/lib/accessibility.js index 52b771d4..3776e937 100644 --- a/client/lib/accessibility.js +++ b/client/lib/accessibility.js @@ -27,10 +27,7 @@ function copyTitleInAriaLabel(attributes) { // which is a little bit hacky -- but still reasonable with our ES6 usage. If we // end up switching to React we will probably create lower level small // components to handle that without overwriting any build-in function. -const { - A: superA, - I: superI, -} = HTML; +const { A: superA, I: superI } = HTML; HTML.A = (attributes, ...others) => { return superA(copyTitleInAriaLabel(enforceHref(attributes)), ...others); diff --git a/client/lib/cssEvents.js b/client/lib/cssEvents.js index 04f5707e..1cf6b8e8 100644 --- a/client/lib/cssEvents.js +++ b/client/lib/cssEvents.js @@ -3,11 +3,11 @@ function whichTransitionEvent() { const el = document.createElement('fakeelement'); const transitions = { - transition:'transitionend', - OTransition:'oTransitionEnd', - MSTransition:'msTransitionEnd', - MozTransition:'transitionend', - WebkitTransition:'webkitTransitionEnd', + transition: 'transitionend', + OTransition: 'oTransitionEnd', + MSTransition: 'msTransitionEnd', + MozTransition: 'transitionend', + WebkitTransition: 'webkitTransitionEnd', }; for (const t in transitions) { @@ -21,11 +21,11 @@ function whichTransitionEvent() { function whichAnimationEvent() { const el = document.createElement('fakeelement'); const transitions = { - animation:'animationend', - OAnimation:'oAnimationEnd', - MSTransition:'msAnimationEnd', - MozAnimation:'animationend', - WebkitAnimation:'webkitAnimationEnd', + animation: 'animationend', + OAnimation: 'oAnimationEnd', + MSTransition: 'msAnimationEnd', + MozAnimation: 'animationend', + WebkitAnimation: 'webkitAnimationEnd', }; for (const t in transitions) { diff --git a/client/lib/datepicker.js b/client/lib/datepicker.js index ab2da0bd..eb5b60b8 100644 --- a/client/lib/datepicker.js +++ b/client/lib/datepicker.js @@ -10,15 +10,20 @@ DatePicker = BlazeComponent.extendComponent({ }, onRendered() { - const $picker = this.$('.js-datepicker').datepicker({ - todayHighlight: true, - todayBtn: 'linked', - language: TAPi18n.getLanguage(), - }).on('changeDate', function(evt) { - this.find('#date').value = moment(evt.date).format('L'); - this.error.set(''); - this.find('#time').focus(); - }.bind(this)); + const $picker = this.$('.js-datepicker') + .datepicker({ + todayHighlight: true, + todayBtn: 'linked', + language: TAPi18n.getLanguage(), + }) + .on( + 'changeDate', + function(evt) { + this.find('#date').value = moment(evt.date).format('L'); + this.error.set(''); + this.find('#time').focus(); + }.bind(this), + ); if (this.date.get().isValid()) { $picker.datepicker('update', this.date.get().toDate()); @@ -26,13 +31,11 @@ DatePicker = BlazeComponent.extendComponent({ }, showDate() { - if (this.date.get().isValid()) - return this.date.get().format('L'); + if (this.date.get().isValid()) return this.date.get().format('L'); return ''; }, showTime() { - if (this.date.get().isValid()) - return this.date.get().format('LT'); + if (this.date.get().isValid()) return this.date.get().format('LT'); return ''; }, dateFormat() { @@ -43,44 +46,47 @@ DatePicker = BlazeComponent.extendComponent({ }, events() { - return [{ - 'keyup .js-date-field'() { - // parse for localized date format in strict mode - const dateMoment = moment(this.find('#date').value, 'L', true); - if (dateMoment.isValid()) { - this.error.set(''); - this.$('.js-datepicker').datepicker('update', dateMoment.toDate()); - } - }, - 'keyup .js-time-field'() { - // parse for localized time format in strict mode - const dateMoment = moment(this.find('#time').value, 'LT', true); - if (dateMoment.isValid()) { - this.error.set(''); - } - }, - 'submit .edit-date'(evt) { - evt.preventDefault(); + return [ + { + 'keyup .js-date-field'() { + // parse for localized date format in strict mode + const dateMoment = moment(this.find('#date').value, 'L', true); + if (dateMoment.isValid()) { + this.error.set(''); + this.$('.js-datepicker').datepicker('update', dateMoment.toDate()); + } + }, + 'keyup .js-time-field'() { + // parse for localized time format in strict mode + const dateMoment = moment(this.find('#time').value, 'LT', true); + if (dateMoment.isValid()) { + this.error.set(''); + } + }, + 'submit .edit-date'(evt) { + evt.preventDefault(); - // if no time was given, init with 12:00 - const time = evt.target.time.value || moment(new Date().setHours(12, 0, 0)).format('LT'); + // if no time was given, init with 12:00 + const time = + evt.target.time.value || + moment(new Date().setHours(12, 0, 0)).format('LT'); - const dateString = `${evt.target.date.value} ${time}`; - const newDate = moment(dateString, 'L LT', true); - if (newDate.isValid()) { - this._storeDate(newDate.toDate()); + const dateString = `${evt.target.date.value} ${time}`; + const newDate = moment(dateString, 'L LT', true); + if (newDate.isValid()) { + this._storeDate(newDate.toDate()); + Popup.close(); + } else { + this.error.set('invalid-date'); + evt.target.date.focus(); + } + }, + 'click .js-delete-date'(evt) { + evt.preventDefault(); + this._deleteDate(); Popup.close(); - } - else { - this.error.set('invalid-date'); - evt.target.date.focus(); - } - }, - 'click .js-delete-date'(evt) { - evt.preventDefault(); - this._deleteDate(); - Popup.close(); + }, }, - }]; + ]; }, }); diff --git a/client/lib/dropImage.js b/client/lib/dropImage.js index 592d5c8f..f4e1d8ab 100644 --- a/client/lib/dropImage.js +++ b/client/lib/dropImage.js @@ -11,7 +11,10 @@ $.event.fix = (function(originalFix) { return function(event) { event = originalFix.apply(this, arguments); - if (event.type.indexOf('drag') === 0 || event.type.indexOf('drop') === 0) { + if ( + event.type.indexOf('drag') === 0 || + event.type.indexOf('drop') === 0 + ) { event.dataTransfer = event.originalEvent.dataTransfer; } return event; @@ -23,7 +26,7 @@ matchType: /image.*/, }; - return $.fn.dropImageReader = function(options) { + return ($.fn.dropImageReader = function(options) { if (typeof options === 'function') { options = { callback: options, @@ -40,9 +43,9 @@ return $(element).bind('drop', function(event) { stopFn(event); const files = event.dataTransfer.files; - for(let i=0; i<files.length; i++) { + for (let i = 0; i < files.length; i++) { const f = files[i]; - if(f.type.match(options.matchType)) { + if (f.type.match(options.matchType)) { const reader = new FileReader(); reader.onload = function(evt) { return options.callback.call(element, { @@ -58,5 +61,5 @@ } }); }); - }; + }); })(jQuery); diff --git a/client/lib/escapeActions.js b/client/lib/escapeActions.js index 0757ae46..1bf32a7d 100644 --- a/client/lib/escapeActions.js +++ b/client/lib/escapeActions.js @@ -33,13 +33,19 @@ EscapeActions = { const noClickEscapeOn = options.noClickEscapeOn; - this._actions = _.sortBy([...this._actions, { - priority, - condition, - action, - noClickEscapeOn, - enabledOnClick, - }], (action) => action.priority); + this._actions = _.sortBy( + [ + ...this._actions, + { + priority, + condition, + action, + noClickEscapeOn, + enabledOnClick, + }, + ], + action => action.priority, + ); }, executeLowest() { @@ -80,10 +86,8 @@ EscapeActions = { }, _stopClick(action, clickTarget) { - if (!_.isString(action.noClickEscapeOn)) - return false; - else - return $(clickTarget).closest(action.noClickEscapeOn).length > 0; + if (!_.isString(action.noClickEscapeOn)) return false; + else return $(clickTarget).closest(action.noClickEscapeOn).length > 0; }, _execute(options) { @@ -95,14 +99,11 @@ EscapeActions = { let executedAtLeastOne = false; let maxPriority; - if (!maxLabel) - maxPriority = Infinity; - else - maxPriority = this.hierarchy.indexOf(maxLabel); + if (!maxLabel) maxPriority = Infinity; + else maxPriority = this.hierarchy.indexOf(maxLabel); for (const currentAction of this._actions) { - if (currentAction.priority > maxPriority) - return executedAtLeastOne; + if (currentAction.priority > maxPriority) return executedAtLeastOne; if (isClick && this._stopClick(currentAction, clickTarget)) return executedAtLeastOne; @@ -111,8 +112,7 @@ EscapeActions = { if (isEnabled && currentAction.condition()) { currentAction.action(); executedAtLeastOne = true; - if (!multipleActions) - return executedAtLeastOne; + if (!multipleActions) return executedAtLeastOne; } } return executedAtLeastOne; @@ -128,13 +128,15 @@ Mousetrap.bindGlobal('esc', () => { // On a left click on the document, we try to exectute one escape action (eg, // close the popup). We don't execute any action if the user has clicked on a // link or a button. -$(document).on('click', (evt) => { - if (evt.button === 0 && - $(evt.target).closest('a,button,.is-editable').length === 0) { +$(document).on('click', evt => { + if ( + evt.button === 0 && + $(evt.target).closest('a,button,.is-editable').length === 0 + ) { EscapeActions.clickExecute(evt.target, 'multiselection'); } }); -$(document).on('click', 'a[href=\\#]', (evt) => { +$(document).on('click', 'a[href=\\#]', evt => { evt.preventDefault(); }); diff --git a/client/lib/filter.js b/client/lib/filter.js index c3c1b070..f19dc617 100644 --- a/client/lib/filter.js +++ b/client/lib/filter.js @@ -71,18 +71,19 @@ class SetFilter { _getEmptySelector() { this._dep.depend(); let includeEmpty = false; - this._selectedElements.forEach((el) => { + this._selectedElements.forEach(el => { if (el === undefined) { includeEmpty = true; } }); - return includeEmpty ? { - $eq: [], - } : null; + return includeEmpty + ? { + $eq: [], + } + : null; } } - // Advanced filter forms a MongoSelector from a users String. // Build by: Ignatz 19.05.2018 (github feuerball11) class AdvancedFilter { @@ -128,7 +129,8 @@ class AdvancedFilter { current += char; continue; } - if (char === '\'') { + // eslint-disable-next-line quotes + if (char === "'") { string = !string; if (string) wasString = true; continue; @@ -139,8 +141,8 @@ class AdvancedFilter { } if (char === ' ' && !string) { commands.push({ - 'cmd': current, - 'string': wasString, + cmd: current, + string: wasString, regex, }); wasString = false; @@ -151,8 +153,8 @@ class AdvancedFilter { } if (current !== '') { commands.push({ - 'cmd': current, - 'string': wasString, + cmd: current, + string: wasString, regex, }); } @@ -161,16 +163,19 @@ class AdvancedFilter { _fieldNameToId(field) { const found = CustomFields.findOne({ - 'name': field, + name: field, }); return found._id; } _fieldValueToId(field, value) { const found = CustomFields.findOne({ - 'name': field, + name: field, }); - if (found.settings.dropdownItems && found.settings.dropdownItems.length > 0) { + if ( + found.settings.dropdownItems && + found.settings.dropdownItems.length > 0 + ) { for (let i = 0; i < found.settings.dropdownItems.length; i++) { if (found.settings.dropdownItems[i].name === value) { return found.settings.dropdownItems[i]._id; @@ -202,37 +207,32 @@ class AdvancedFilter { for (let i = 0; i < commands.length; i++) { if (commands[i].cmd) { switch (commands[i].cmd) { - case '(': - { - level++; - if (start === -1) start = i; - continue; - } - case ')': - { - level--; - commands.splice(i, 1); - i--; - continue; - } - default: - { - if (level > 0) { - subcommands.push(commands[i]); + case '(': { + level++; + if (start === -1) start = i; + continue; + } + case ')': { + level--; commands.splice(i, 1); i--; continue; } - } + default: { + if (level > 0) { + subcommands.push(commands[i]); + commands.splice(i, 1); + i--; + continue; + } + } } } } if (start !== -1) { this._processSubCommands(subcommands); - if (subcommands.length === 1) - commands.splice(start, 0, subcommands[0]); - else - commands.splice(start, 0, subcommands); + if (subcommands.length === 1) commands.splice(start, 0, subcommands[0]); + else commands.splice(start, 0, subcommands); } this._processConditions(commands); this._processLogicalOperators(commands); @@ -242,149 +242,139 @@ class AdvancedFilter { for (let i = 0; i < commands.length; i++) { if (!commands[i].string && commands[i].cmd) { switch (commands[i].cmd) { - case '=': - case '==': - case '===': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - if (commands[i + 1].regex) { - const match = str.match(new RegExp('^/(.*?)/([gimy]*)$')); - let regex = null; - if (match.length > 2) - regex = new RegExp(match[1], match[2]); - else - regex = new RegExp(match[1]); + case '=': + case '==': + case '===': { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; + if (commands[i + 1].regex) { + const match = str.match(new RegExp('^/(.*?)/([gimy]*)$')); + let regex = null; + if (match.length > 2) regex = new RegExp(match[1], match[2]); + else regex = new RegExp(match[1]); + commands[i] = { + 'customFields._id': this._fieldNameToId(field), + 'customFields.value': regex, + }; + } else { + commands[i] = { + 'customFields._id': this._fieldNameToId(field), + 'customFields.value': { + $in: [this._fieldValueToId(field, str), parseInt(str, 10)], + }, + }; + } + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; + } + case '!=': + case '!==': { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; + if (commands[i + 1].regex) { + const match = str.match(new RegExp('^/(.*?)/([gimy]*)$')); + let regex = null; + if (match.length > 2) regex = new RegExp(match[1], match[2]); + else regex = new RegExp(match[1]); + commands[i] = { + 'customFields._id': this._fieldNameToId(field), + 'customFields.value': { + $not: regex, + }, + }; + } else { + commands[i] = { + 'customFields._id': this._fieldNameToId(field), + 'customFields.value': { + $not: { + $in: [this._fieldValueToId(field, str), parseInt(str, 10)], + }, + }, + }; + } + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; + } + case '>': + case 'gt': + case 'Gt': + case 'GT': { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; commands[i] = { 'customFields._id': this._fieldNameToId(field), - 'customFields.value': regex, + 'customFields.value': { + $gt: parseInt(str, 10), + }, }; - } else { + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; + } + case '>=': + case '>==': + case 'gte': + case 'Gte': + case 'GTE': { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { - $in: [this._fieldValueToId(field, str), parseInt(str, 10)], + $gte: parseInt(str, 10), }, }; + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; } - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } - case '!=': - case '!==': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - if (commands[i + 1].regex) { - const match = str.match(new RegExp('^/(.*?)/([gimy]*)$')); - let regex = null; - if (match.length > 2) - regex = new RegExp(match[1], match[2]); - else - regex = new RegExp(match[1]); + case '<': + case 'lt': + case 'Lt': + case 'LT': { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { - $not: regex, + $lt: parseInt(str, 10), }, }; - } else { + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; + } + case '<=': + case '<==': + case 'lte': + case 'Lte': + case 'LTE': { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { - $not: { - $in: [this._fieldValueToId(field, str), parseInt(str, 10)], - }, + $lte: parseInt(str, 10), }, }; + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; } - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } - case '>': - case 'gt': - case 'Gt': - case 'GT': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - commands[i] = { - 'customFields._id': this._fieldNameToId(field), - 'customFields.value': { - $gt: parseInt(str, 10), - }, - }; - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } - case '>=': - case '>==': - case 'gte': - case 'Gte': - case 'GTE': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - commands[i] = { - 'customFields._id': this._fieldNameToId(field), - 'customFields.value': { - $gte: parseInt(str, 10), - }, - }; - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } - case '<': - case 'lt': - case 'Lt': - case 'LT': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - commands[i] = { - 'customFields._id': this._fieldNameToId(field), - 'customFields.value': { - $lt: parseInt(str, 10), - }, - }; - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } - case '<=': - case '<==': - case 'lte': - case 'Lte': - case 'LTE': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - commands[i] = { - 'customFields._id': this._fieldNameToId(field), - 'customFields.value': { - $lte: parseInt(str, 10), - }, - }; - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } } } } @@ -394,54 +384,51 @@ class AdvancedFilter { for (let i = 0; i < commands.length; i++) { if (!commands[i].string && commands[i].cmd) { switch (commands[i].cmd) { - case 'or': - case 'Or': - case 'OR': - case '|': - case '||': - { - const op1 = commands[i - 1]; - const op2 = commands[i + 1]; - commands[i] = { - $or: [op1, op2], - }; - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } - case 'and': - case 'And': - case 'AND': - case '&': - case '&&': - { - const op1 = commands[i - 1]; - const op2 = commands[i + 1]; - commands[i] = { - $and: [op1, op2], - }; - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } - case 'not': - case 'Not': - case 'NOT': - case '!': - { - const op1 = commands[i + 1]; - commands[i] = { - $not: op1, - }; - commands.splice(i + 1, 1); - //changed = true; - i--; - break; - } + case 'or': + case 'Or': + case 'OR': + case '|': + case '||': { + const op1 = commands[i - 1]; + const op2 = commands[i + 1]; + commands[i] = { + $or: [op1, op2], + }; + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; + } + case 'and': + case 'And': + case 'AND': + case '&': + case '&&': { + const op1 = commands[i - 1]; + const op2 = commands[i + 1]; + commands[i] = { + $and: [op1, op2], + }; + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; + } + case 'not': + case 'Not': + case 'NOT': + case '!': { + const op1 = commands[i + 1]; + commands[i] = { + $not: op1, + }; + commands.splice(i + 1, 1); + //changed = true; + i--; + break; + } } } } @@ -452,7 +439,6 @@ class AdvancedFilter { const commands = this._filterToCommands(); return this._arrayToSelector(commands); } - } // The global Filter object. @@ -477,23 +463,26 @@ Filter = { _exceptionsDep: new Tracker.Dependency(), isActive() { - return _.any(this._fields, (fieldName) => { - return this[fieldName]._isActive(); - }) || this.advanced._isActive(); + return ( + _.any(this._fields, fieldName => { + return this[fieldName]._isActive(); + }) || this.advanced._isActive() + ); }, _getMongoSelector() { - if (!this.isActive()) - return {}; + if (!this.isActive()) return {}; const filterSelector = {}; const emptySelector = {}; let includeEmptySelectors = false; - this._fields.forEach((fieldName) => { + this._fields.forEach(fieldName => { const filter = this[fieldName]; if (filter._isActive()) { if (filter.subField !== '') { - filterSelector[`${fieldName}.${filter.subField}`] = filter._getMongoSelector(); + filterSelector[ + `${fieldName}.${filter.subField}` + ] = filter._getMongoSelector(); } else { filterSelector[fieldName] = filter._getMongoSelector(); } @@ -513,11 +502,15 @@ Filter = { const selectors = [exceptionsSelector]; - if (_.any(this._fields, (fieldName) => { - return this[fieldName]._isActive(); - })) selectors.push(filterSelector); + if ( + _.any(this._fields, fieldName => { + return this[fieldName]._isActive(); + }) + ) + selectors.push(filterSelector); if (includeEmptySelectors) selectors.push(emptySelector); - if (this.advanced._isActive()) selectors.push(this.advanced._getMongoSelector()); + if (this.advanced._isActive()) + selectors.push(this.advanced._getMongoSelector()); return { $or: selectors, @@ -526,8 +519,7 @@ Filter = { mongoSelector(additionalSelector) { const filterSelector = this._getMongoSelector(); - if (_.isUndefined(additionalSelector)) - return filterSelector; + if (_.isUndefined(additionalSelector)) return filterSelector; else return { $and: [filterSelector, additionalSelector], @@ -535,7 +527,7 @@ Filter = { }, reset() { - this._fields.forEach((fieldName) => { + this._fields.forEach(fieldName => { const filter = this[fieldName]; filter.reset(); }); diff --git a/client/lib/i18n.js b/client/lib/i18n.js index 97a91375..b4a95eae 100644 --- a/client/lib/i18n.js +++ b/client/lib/i18n.js @@ -12,7 +12,7 @@ Meteor.startup(() => { } if (!language) { - if(navigator.languages) { + if (navigator.languages) { language = navigator.languages[0]; } else { language = navigator.language || navigator.userLanguage; diff --git a/client/lib/inlinedform.js b/client/lib/inlinedform.js index d33786ae..f2ebe31e 100644 --- a/client/lib/inlinedform.js +++ b/client/lib/inlinedform.js @@ -48,35 +48,43 @@ InlinedForm = BlazeComponent.extendComponent({ }, events() { - return [{ - 'click .js-close-inlined-form': this.close, - 'click .js-open-inlined-form': this.open, + return [ + { + 'click .js-close-inlined-form': this.close, + 'click .js-open-inlined-form': this.open, - // Pressing Ctrl+Enter should submit the form - 'keydown form textarea'(evt) { - if (evt.keyCode === 13 && (evt.metaKey || evt.ctrlKey)) { - this.find('button[type=submit]').click(); - } - }, + // Pressing Ctrl+Enter should submit the form + 'keydown form textarea'(evt) { + if (evt.keyCode === 13 && (evt.metaKey || evt.ctrlKey)) { + this.find('button[type=submit]').click(); + } + }, - // Close the inlined form when after its submission - submit() { - if (this.currentData().autoclose !== false) { - Tracker.afterFlush(() => { - this.close(); - }); - } + // Close the inlined form when after its submission + submit() { + if (this.currentData().autoclose !== false) { + Tracker.afterFlush(() => { + this.close(); + }); + } + }, }, - }]; + ]; }, }).register('inlinedForm'); // Press escape to close the currently opened inlinedForm -EscapeActions.register('inlinedForm', - () => { currentlyOpenedForm.get().close(); }, - () => { return currentlyOpenedForm.get() !== null; }, { +EscapeActions.register( + 'inlinedForm', + () => { + currentlyOpenedForm.get().close(); + }, + () => { + return currentlyOpenedForm.get() !== null; + }, + { enabledOnClick: false, - } + }, ); // submit on click outside diff --git a/client/lib/keyboard.js b/client/lib/keyboard.js index 7abfa88d..d3f974be 100755 --- a/client/lib/keyboard.js +++ b/client/lib/keyboard.js @@ -40,8 +40,10 @@ Mousetrap.bind(['down', 'up'], (evt, key) => { return; } - const nextFunc = (key === 'down' ? 'next' : 'prev'); - const nextCard = $('.js-minicard.is-selected')[nextFunc]('.js-minicard').get(0); + const nextFunc = key === 'down' ? 'next' : 'prev'; + const nextCard = $('.js-minicard.is-selected') + [nextFunc]('.js-minicard') + .get(0); if (nextCard) { const nextCardId = Blaze.getData(nextCard)._id; Utils.goCardId(nextCardId); @@ -49,7 +51,7 @@ Mousetrap.bind(['down', 'up'], (evt, key) => { }); // XXX This shortcut should also work when hovering over a card in board view -Mousetrap.bind('space', (evt) => { +Mousetrap.bind('space', evt => { if (!Session.get('currentCard')) { return; } @@ -69,29 +71,38 @@ Mousetrap.bind('space', (evt) => { }); Template.keyboardShortcuts.helpers({ - mapping: [{ - keys: ['W'], - action: 'shortcut-toggle-sidebar', - }, { - keys: ['Q'], - action: 'shortcut-filter-my-cards', - }, { - keys: ['F'], - action: 'shortcut-toggle-filterbar', - }, { - keys: ['X'], - action: 'shortcut-clear-filters', - }, { - keys: ['?'], - action: 'shortcut-show-shortcuts', - }, { - keys: ['ESC'], - action: 'shortcut-close-dialog', - }, { - keys: ['@'], - action: 'shortcut-autocomplete-members', - }, { - keys: ['SPACE'], - action: 'shortcut-assign-self', - }], + mapping: [ + { + keys: ['W'], + action: 'shortcut-toggle-sidebar', + }, + { + keys: ['Q'], + action: 'shortcut-filter-my-cards', + }, + { + keys: ['F'], + action: 'shortcut-toggle-filterbar', + }, + { + keys: ['X'], + action: 'shortcut-clear-filters', + }, + { + keys: ['?'], + action: 'shortcut-show-shortcuts', + }, + { + keys: ['ESC'], + action: 'shortcut-close-dialog', + }, + { + keys: ['@'], + action: 'shortcut-autocomplete-members', + }, + { + keys: ['SPACE'], + action: 'shortcut-assign-self', + }, + ], }); diff --git a/client/lib/modal.js b/client/lib/modal.js index 3c27a179..1086734e 100644 --- a/client/lib/modal.js +++ b/client/lib/modal.js @@ -1,6 +1,6 @@ const closedValue = null; -window.Modal = new class { +window.Modal = new (class { constructor() { this._currentModal = new ReactiveVar(closedValue); this._onCloseGoTo = ''; @@ -21,7 +21,7 @@ window.Modal = new class { return this.getTemplateName() !== closedValue; } - isWide(){ + isWide() { return this._isWideModal; } @@ -32,23 +32,23 @@ window.Modal = new class { } } - openWide(modalName, { header = '', onCloseGoTo = ''} = {}) { + openWide(modalName, { header = '', onCloseGoTo = '' } = {}) { this._currentModal.set({ header, modalName }); this._onCloseGoTo = onCloseGoTo; this._isWideModal = true; } - open(modalName, { header = '', onCloseGoTo = ''} = {}) { + open(modalName, { header = '', onCloseGoTo = '' } = {}) { this._currentModal.set({ header, modalName }); this._onCloseGoTo = onCloseGoTo; - } -}(); +})(); Blaze.registerHelper('Modal', Modal); -EscapeActions.register('modalWindow', +EscapeActions.register( + 'modalWindow', () => Modal.close(), () => Modal.isOpen(), - { noClickEscapeOn: '.modal-container' } + { noClickEscapeOn: '.modal-container' }, ); diff --git a/client/lib/multiSelection.js b/client/lib/multiSelection.js index 30577fd4..ab6a046f 100644 --- a/client/lib/multiSelection.js +++ b/client/lib/multiSelection.js @@ -1,6 +1,4 @@ - function getCardsBetween(idA, idB) { - function pluckId(doc) { return doc._id; } @@ -15,7 +13,7 @@ function getCardsBetween(idA, idB) { }).map(pluckId); } - const cards = _.sortBy([Cards.findOne(idA), Cards.findOne(idB)], (c) => { + const cards = _.sortBy([Cards.findOne(idA), Cards.findOne(idB)], c => { return c.sort; }); @@ -31,17 +29,21 @@ function getCardsBetween(idA, idB) { }; } else { selector = { - $or: [{ - listId: cards[0].listId, - sort: { $lte: cards[0].sort }, - }, { - listId: { - $in: getListsStrictlyBetween(cards[0].listId, cards[1].listId), + $or: [ + { + listId: cards[0].listId, + sort: { $lte: cards[0].sort }, + }, + { + listId: { + $in: getListsStrictlyBetween(cards[0].listId, cards[1].listId), + }, }, - }, { - listId: cards[1].listId, - sort: { $gte: cards[1].sort }, - }], + { + listId: cards[1].listId, + sort: { $gte: cards[1].sort }, + }, + ], archived: false, }; } @@ -133,14 +135,12 @@ MultiSelection = { const selectedCards = this._selectedCards.get(); - cardIds.forEach((cardId) => { + cardIds.forEach(cardId => { const indexOfCard = selectedCards.indexOf(cardId); if (options.remove && indexOfCard > -1) selectedCards.splice(indexOfCard, 1); - - else if (options.add) - selectedCards.push(cardId); + else if (options.add) selectedCards.push(cardId); }); this._selectedCards.set(selectedCards); @@ -153,9 +153,15 @@ MultiSelection = { Blaze.registerHelper('MultiSelection', MultiSelection); -EscapeActions.register('multiselection', - () => { MultiSelection.disable(); }, - () => { return MultiSelection.isActive(); }, { +EscapeActions.register( + 'multiselection', + () => { + MultiSelection.disable(); + }, + () => { + return MultiSelection.isActive(); + }, + { noClickEscapeOn: '.js-minicard,.js-board-sidebar-content', - } + }, ); diff --git a/client/lib/pasteImage.js b/client/lib/pasteImage.js index 264d77ac..e6f8c6c2 100644 --- a/client/lib/pasteImage.js +++ b/client/lib/pasteImage.js @@ -11,7 +11,10 @@ $.event.fix = (function(originalFix) { return function(event) { event = originalFix.apply(this, arguments); - if (event.type.indexOf('copy') === 0 || event.type.indexOf('paste') === 0) { + if ( + event.type.indexOf('copy') === 0 || + event.type.indexOf('paste') === 0 + ) { event.clipboardData = event.originalEvent.clipboardData; } return event; @@ -23,7 +26,7 @@ matchType: /image.*/, }; - return $.fn.pasteImageReader = function(options) { + return ($.fn.pasteImageReader = function(options) { if (typeof options === 'function') { options = { callback: options, @@ -35,8 +38,11 @@ return $(element).bind('paste', function(event) { const types = event.clipboardData.types; const items = event.clipboardData.items; - for(let i=0; i<types.length; i++) { - if(types[i].match(options.matchType) || items[i].type.match(options.matchType)) { + for (let i = 0; i < types.length; i++) { + if ( + types[i].match(options.matchType) || + items[i].type.match(options.matchType) + ) { const f = items[i].getAsFile(); const reader = new FileReader(); reader.onload = function(evt) { @@ -53,5 +59,5 @@ } }); }); - }; + }); })(jQuery); diff --git a/client/lib/popup.js b/client/lib/popup.js index 9abe48aa..6c294d32 100644 --- a/client/lib/popup.js +++ b/client/lib/popup.js @@ -1,4 +1,4 @@ -window.Popup = new class { +window.Popup = new (class { constructor() { // The template we use to render popups this.template = Template.popup; @@ -67,7 +67,7 @@ window.Popup = new class { title: self._getTitle(popupName), depth: self._stack.length, offset: self._getOffset(openerElement), - dataContext: this.currentData && this.currentData() || this, + dataContext: (this.currentData && this.currentData()) || this, }); // If there are no popup currently opened we use the Blaze API to render @@ -80,11 +80,14 @@ window.Popup = new class { // our internal dependency, and since we just changed the top element of // our internal stack, the popup will be updated with the new data. if (!self.isOpen()) { - self.current = Blaze.renderWithData(self.template, () => { - self._dep.depend(); - return { ...self._getTopStack(), stack: self._stack }; - }, document.body); - + self.current = Blaze.renderWithData( + self.template, + () => { + self._dep.depend(); + return { ...self._getTopStack(), stack: self._stack }; + }, + document.body, + ); } else { self._dep.changed(); } @@ -101,7 +104,7 @@ window.Popup = new class { const self = this; return function(evt, tpl) { - const context = this.currentData && this.currentData() || this; + const context = (this.currentData && this.currentData()) || this; context.__afterConfirmAction = action; self.open(name).call(context, evt, tpl); }; @@ -136,7 +139,6 @@ window.Popup = new class { const openerElement = this._getTopStack().openerElement; $(openerElement).removeClass('is-active'); - this._stack = []; } } @@ -159,7 +161,7 @@ window.Popup = new class { return () => { Utils.windowResizeDep.depend(); - if(Utils.isMiniScreen()) return { left:0, top:0 }; + if (Utils.isMiniScreen()) return { left: 0, top: 0 }; const offset = $element.offset(); const popupWidth = 300 + 15; @@ -188,18 +190,19 @@ window.Popup = new class { return title !== translationKey ? title : defaultTitle; }; } -}(); +})(); // We close a potential opened popup on any left click on the document, or go // one step back by pressing escape. const escapeActions = ['back', 'close']; -escapeActions.forEach((actionName) => { - EscapeActions.register(`popup-${actionName}`, +escapeActions.forEach(actionName => { + EscapeActions.register( + `popup-${actionName}`, () => Popup[actionName](), () => Popup.isOpen(), { noClickEscapeOn: '.js-pop-over,.js-open-card-title-popup', enabledOnClick: actionName === 'close', - } + }, ); }); diff --git a/client/lib/textComplete.js b/client/lib/textComplete.js index 69820514..0261d7f6 100644 --- a/client/lib/textComplete.js +++ b/client/lib/textComplete.js @@ -47,9 +47,6 @@ $.fn.escapeableTextComplete = function(strategies, options, ...otherArgs) { }); }; -EscapeActions.register('textcomplete', - () => {}, - () => dropdownMenuIsOpened, { - noClickEscapeOn: '.textcomplete-dropdown', - } -); +EscapeActions.register('textcomplete', () => {}, () => dropdownMenuIsOpened, { + noClickEscapeOn: '.textcomplete-dropdown', +}); diff --git a/client/lib/unsavedEdits.js b/client/lib/unsavedEdits.js index 9c02eb84..a67d0eef 100644 --- a/client/lib/unsavedEdits.js +++ b/client/lib/unsavedEdits.js @@ -34,13 +34,13 @@ UnsavedEdits = { }, has({ fieldName, docId }) { - return Boolean(this.get({fieldName, docId})); + return Boolean(this.get({ fieldName, docId })); }, set({ fieldName, docId }, value) { const currentDoc = this._getCollectionDocument(fieldName, docId); if (currentDoc) { - UnsavedEditCollection.update(currentDoc._id, { $set: { value }}); + UnsavedEditCollection.update(currentDoc._id, { $set: { value } }); } else { UnsavedEditCollection.insert({ fieldName, @@ -58,7 +58,7 @@ UnsavedEdits = { }, _getCollectionDocument(fieldName, docId) { - return UnsavedEditCollection.findOne({fieldName, docId}); + return UnsavedEditCollection.findOne({ fieldName, docId }); }, }; diff --git a/client/lib/utils.js b/client/lib/utils.js index e2339763..5681273e 100644 --- a/client/lib/utils.js +++ b/client/lib/utils.js @@ -2,20 +2,26 @@ Utils = { // XXX We should remove these two methods goBoardId(_id) { const board = Boards.findOne(_id); - return board && FlowRouter.go('board', { - id: board._id, - slug: board.slug, - }); + return ( + board && + FlowRouter.go('board', { + id: board._id, + slug: board.slug, + }) + ); }, goCardId(_id) { const card = Cards.findOne(_id); const board = Boards.findOne(card.boardId); - return board && FlowRouter.go('card', { - cardId: card._id, - boardId: board._id, - slug: board.slug, - }); + return ( + board && + FlowRouter.go('card', { + cardId: card._id, + boardId: board._id, + slug: board.slug, + }) + ); }, capitalize(string) { @@ -104,13 +110,21 @@ Utils = { return window.matchMedia(query).matches; }; - if (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch) { + if ( + 'ontouchstart' in window || + (window.DocumentTouch && document instanceof window.DocumentTouch) + ) { return true; } // include the 'heartz' as a way to have a non matching MQ to help terminate the join // https://git.io/vznFH - const query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join(''); + const query = [ + '(', + prefixes.join('touch-enabled),('), + 'heartz', + ')', + ].join(''); return mq(query); })(); Utils.isTouchDevice = () => isTouchable; @@ -120,7 +134,7 @@ Utils = { calculateTouchDistance(touchA, touchB) { return Math.sqrt( Math.pow(touchA.screenX - touchB.screenX, 2) + - Math.pow(touchA.screenY - touchB.screenY, 2) + Math.pow(touchA.screenY - touchB.screenY, 2), ); }, @@ -136,7 +150,11 @@ Utils = { lastTouch = touches[touches.length - 1]; }); $(document).on('touchend', selector, function(e) { - if (touchStart && lastTouch && Utils.calculateTouchDistance(touchStart, lastTouch) <= 20) { + if ( + touchStart && + lastTouch && + Utils.calculateTouchDistance(touchStart, lastTouch) <= 20 + ) { e.preventDefault(); const clickEvent = document.createEvent('MouseEvents'); clickEvent.initEvent('click', true, true); @@ -145,30 +163,30 @@ Utils = { }); }, - manageCustomUI(){ + manageCustomUI() { Meteor.call('getCustomUI', (err, data) => { - if (err && err.error[0] === 'var-not-exist'){ + if (err && err.error[0] === 'var-not-exist') { Session.set('customUI', false); // siteId || address server not defined } - if (!err){ + if (!err) { Utils.setCustomUI(data); } }); }, - setCustomUI(data){ + setCustomUI(data) { const currentBoard = Boards.findOne(Session.get('currentBoard')); if (currentBoard) { - DocHead.setTitle(`${currentBoard.title } - ${ data.productName}`); + DocHead.setTitle(`${currentBoard.title} - ${data.productName}`); } else { DocHead.setTitle(`${data.productName}`); } }, - setMatomo(data){ + setMatomo(data) { window._paq = window._paq || []; window._paq.push(['setDoNotTrack', data.doNotTrack]); - if (data.withUserName){ + if (data.withUserName) { window._paq.push(['setUserId', Meteor.user().username]); } window._paq.push(['trackPageView']); @@ -196,12 +214,12 @@ Utils = { manageMatomo() { const matomo = Session.get('matomo'); - if (matomo === undefined){ + if (matomo === undefined) { Meteor.call('getMatomoConf', (err, data) => { - if (err && err.error[0] === 'var-not-exist'){ + if (err && err.error[0] === 'var-not-exist') { Session.set('matomo', false); // siteId || address server not defined } - if (!err){ + if (!err) { Utils.setMatomo(data); } }); @@ -220,15 +238,21 @@ Utils = { finalString += element.text().toLowerCase(); } else if (element.hasClass('user-details')) { let username = element.find('input').val(); - if(username === undefined || username === ''){ + if (username === undefined || username === '') { username = '*'; } - finalString += `${element.find('.trigger-text').text().toLowerCase() } ${ username}`; + finalString += `${element + .find('.trigger-text') + .text() + .toLowerCase()} ${username}`; } else if (element.find('select').length > 0) { - finalString += element.find('select option:selected').text().toLowerCase(); + finalString += element + .find('select option:selected') + .text() + .toLowerCase(); } else if (element.find('input').length > 0) { let inputvalue = element.find('input').val(); - if(inputvalue === undefined || inputvalue === ''){ + if (inputvalue === undefined || inputvalue === '') { inputvalue = '*'; } finalString += inputvalue; |