Add eslint with lodash checking and apply its suggestions

This commit is contained in:
JC Brand 2017-01-26 14:49:02 +00:00
parent 343e5777d1
commit 081f075aa9
32 changed files with 531 additions and 257 deletions

264
.eslintrc.json Normal file
View File

@ -0,0 +1,264 @@
{
"env": {
"browser": true,
"jasmine": true
},
"plugins": ["lodash"],
"extends": ["eslint:recommended", "plugin:lodash/canonical"],
"globals": {
"window": true,
"sinon": true,
"define": true
},
"rules": {
"lodash/prefer-lodash-method": [2, {
"ignoreMethods": ["find", "endsWith", "startsWith", "filter", "map"]
}],
"lodash/prefer-startswith": "off",
"lodash/prefer-constant": "off",
"lodash/prefer-noop": "off",
"lodash/prefer-lodash-typecheck": "off",
"lodash/preferred-alias": "off",
"accessor-pairs": "error",
"array-bracket-spacing": "off",
"array-callback-return": "error",
"arrow-body-style": "error",
"arrow-parens": "error",
"arrow-spacing": "error",
"block-scoped-var": "off",
"block-spacing": "off",
"brace-style": "off",
"callback-return": "off",
"camelcase": "off",
"capitalized-comments": "off",
"class-methods-use-this": "error",
"comma-dangle": "off",
"comma-spacing": "off",
"comma-style": "off",
"complexity": "off",
"computed-property-spacing": [
"error",
"never"
],
"consistent-return": "off",
"consistent-this": "off",
"curly": "off",
"default-case": "off",
"dot-location": [
"error",
"property"
],
"dot-notation": [
"error",
{
"allowKeywords": false
}
],
"eol-last": "error",
"eqeqeq": "off",
"func-call-spacing": "off",
"no-spaced-func": "off",
"func-name-matching": "error",
"func-names": "off",
"func-style": "off",
"generator-star-spacing": "error",
"global-require": "off",
"guard-for-in": "error",
"handle-callback-err": "error",
"id-blacklist": "error",
"id-length": "off",
"id-match": "error",
"indent": "off",
"init-declarations": "off",
"jsx-quotes": "error",
"key-spacing": "off",
"keyword-spacing": "off",
"line-comment-position": "off",
"linebreak-style": [
"error",
"unix"
],
"lines-around-comment": "off",
"lines-around-directive": "off",
"max-depth": "error",
"max-len": "off",
"max-lines": "off",
"max-nested-callbacks": "error",
"max-params": "off",
"max-statements": "off",
"max-statements-per-line": "off",
"multiline-ternary": "off",
"new-parens": "error",
"newline-after-var": "off",
"newline-before-return": "off",
"newline-per-chained-call": "off",
"no-alert": "off",
"no-array-constructor": "error",
"no-await-in-loop": "error",
"no-bitwise": "off",
"no-caller": "error",
"no-console": "off",
"no-catch-shadow": "error",
"no-cond-assign": [
"error",
"except-parens"
],
"no-confusing-arrow": "error",
"no-continue": "off",
"no-div-regex": "error",
"no-duplicate-imports": "error",
"no-else-return": "off",
"no-empty-function": "off",
"no-eq-null": "error",
"no-eval": "error",
"no-extend-native": "off",
"no-extra-bind": "off",
"no-extra-label": "error",
"no-extra-parens": "off",
"no-floating-decimal": "error",
"no-implicit-globals": "off",
"no-implied-eval": "error",
"no-inline-comments": "off",
"no-inner-declarations": [
"error",
"functions"
],
"no-invalid-this": "off",
"no-iterator": "error",
"no-label-var": "error",
"no-labels": "error",
"no-lone-blocks": "error",
"no-lonely-if": "off",
"no-loop-func": "error",
"no-magic-numbers": "off",
"no-mixed-operators": "off",
"no-mixed-requires": "error",
"no-multi-assign": "off",
"no-multi-spaces": "off",
"no-multi-str": "error",
"no-multiple-empty-lines": "error",
"no-native-reassign": "error",
"no-negated-condition": "off",
"no-negated-in-lhs": "error",
"no-nested-ternary": "off",
"no-new": "error",
"no-new-func": "error",
"no-new-object": "error",
"no-new-require": "error",
"no-new-wrappers": "error",
"no-octal-escape": "error",
"no-param-reassign": "off",
"no-path-concat": "error",
"no-plusplus": "off",
"no-process-env": "error",
"no-process-exit": "error",
"no-proto": "error",
"no-prototype-builtins": "error",
"no-restricted-globals": "error",
"no-restricted-imports": "error",
"no-restricted-modules": "error",
"no-restricted-properties": "error",
"no-restricted-syntax": "error",
"no-return-assign": "error",
"no-return-await": "error",
"no-script-url": "error",
"no-self-compare": "error",
"no-sequences": "error",
"no-shadow": "off",
"no-shadow-restricted-names": "error",
"no-sync": "error",
"no-tabs": "error",
"no-template-curly-in-string": "error",
"no-ternary": "off",
"no-throw-literal": "error",
"no-trailing-spaces": "off",
"no-undef-init": "error",
"no-undefined": "off",
"no-underscore-dangle": "off",
"no-unmodified-loop-condition": "error",
"no-unneeded-ternary": "off",
"no-unused-vars": "off",
"no-unused-expressions": "off",
"no-use-before-define": "off",
"no-useless-call": "error",
"no-useless-computed-key": "error",
"no-useless-concat": "error",
"no-useless-constructor": "error",
"no-useless-escape": "off",
"no-useless-rename": "error",
"no-useless-return": "off",
"no-var": "off",
"no-void": "error",
"no-warning-comments": "off",
"no-whitespace-before-property": "error",
"no-with": "error",
"object-curly-newline": "off",
"object-curly-spacing": "off",
"object-property-newline": [
"error",
{
"allowMultiplePropertiesPerLine": true
}
],
"object-shorthand": "off",
"one-var": "off",
"one-var-declaration-per-line": "off",
"operator-assignment": "off",
"operator-linebreak": [
"error",
"after"
],
"padded-blocks": "off",
"prefer-arrow-callback": "off",
"prefer-const": "error",
"prefer-destructuring": [
"error",
{
"array": false,
"object": false
}
],
"prefer-numeric-literals": "error",
"prefer-promise-reject-errors": "error",
"prefer-reflect": "off",
"prefer-rest-params": "off",
"prefer-spread": "off",
"prefer-template": "off",
"quote-props": "off",
"quotes": "off",
"radix": [
"error",
"always"
],
"require-await": "error",
"require-jsdoc": "off",
"rest-spread-spacing": "error",
"semi": "off",
"semi-spacing": "off",
"sort-imports": "error",
"sort-keys": "off",
"sort-vars": "off",
"space-before-blocks": "off",
"space-before-function-paren": "off",
"space-in-parens": "off",
"space-infix-ops": "off",
"space-unary-ops": "off",
"spaced-comment": "off",
"strict": "off",
"symbol-description": "error",
"template-curly-spacing": "error",
"unicode-bom": [
"error",
"never"
],
"valid-jsdoc": "error",
"vars-on-top": "off",
"wrap-iife": [
"error",
"any"
],
"wrap-regex": "error",
"yield-star-spacing": "error",
"yoda": "off"
}
}

View File

@ -3,11 +3,12 @@ BOWER ?= node_modules/.bin/bower
BUILDDIR = ./docs BUILDDIR = ./docs
BUNDLE ?= ./.bundle/bin/bundle BUNDLE ?= ./.bundle/bin/bundle
GRUNT ?= ./node_modules/.bin/grunt GRUNT ?= ./node_modules/.bin/grunt
HTTPSERVE ?= ./node_modules/.bin/http-server HTTPSERVE ?= ./node_modules/.bin/http-server
JSHINT ?= ./node_modules/.bin/jshint JSHINT ?= ./node_modules/.bin/jshint
ESLINT ?= ./node_modules/.bin/eslint
PAPER = PAPER =
PHANTOMJS ?= ./node_modules/.bin/phantomjs PHANTOMJS ?= ./node_modules/.bin/phantomjs
RJS ?= ./node_modules/.bin/r.js RJS ?= ./node_modules/.bin/r.js
PO2JSON ?= ./node_modules/.bin/po2json PO2JSON ?= ./node_modules/.bin/po2json
SASS ?= ./.bundle/bin/sass SASS ?= ./.bundle/bin/sass
CLEANCSS ?= ./node_modules/.bin/cleancss CLEANCSS ?= ./node_modules/.bin/cleancss
@ -16,16 +17,13 @@ SPHINXOPTS =
# Internal variables. # Internal variables.
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) ./docs/source ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) ./docs/source
SOURCES = $(wildcard *.js) $(wildcard spec/*.js) $(wildcard src/*.js) SOURCES = $(wildcard *.js) $(wildcard spec/*.js) $(wildcard src/*.js)
JSHINTEXCEPTIONS = $(GENERATED) \ JSHINTEXCEPTIONS = $(GENERATED) \
src/otr.js \ src/build-mobile.js \
src/crypto.js \ src/build-no-jquery.js \
src/build-mobile.js \ src/build-no-dependencies.js \
src/build-no-jquery.js \ src/build.js \
src/build-no-dependencies.js \ CHECKSOURCES = $(filter-out $(JSHINTEXCEPTIONS),$(SOURCES))
src/build.js \
src/bigint.js
CHECKSOURCES = $(filter-out $(JSHINTEXCEPTIONS),$(SOURCES))
.PHONY: all .PHONY: all
all: dev dist all: dev dist
@ -189,8 +187,13 @@ build:: stamp-bundler stamp-bower css
jshint: stamp-bower jshint: stamp-bower
$(JSHINT) --config jshintrc $(CHECKSOURCES) $(JSHINT) --config jshintrc $(CHECKSOURCES)
.PHONY: eslint
eslint: stamp-npm
$(ESLINT) src/
$(ESLINT) spec/
.PHONY: check .PHONY: check
check: stamp-bower jshint check: stamp-bower jshint eslint
$(PHANTOMJS) node_modules/phantom-jasmine/lib/run_jasmine_test.coffee tests.html $(PHANTOMJS) node_modules/phantom-jasmine/lib/run_jasmine_test.coffee tests.html
######################################################################## ########################################################################

View File

@ -39,19 +39,22 @@
"bower": "latest", "bower": "latest",
"clean-css": "^3.4.19", "clean-css": "^3.4.19",
"crypto-js": "3.1.2-5", "crypto-js": "3.1.2-5",
"eslint": "^3.14.1",
"eslint-plugin-lodash": "^2.3.3",
"greenkeeper": "^4.1.0", "greenkeeper": "^4.1.0",
"grunt": "^1.0.1", "grunt": "^1.0.1",
"grunt-cli": "^1.1.0", "grunt-cli": "^1.1.0",
"grunt-json": "^0.2.0", "grunt-json": "^0.2.0",
"http-server": "^0.9.0", "http-server": "^0.9.0",
"install": "^0.8.4",
"jed": "0.5.4", "jed": "0.5.4",
"jquery": "2.2.3", "jquery": "2.2.3",
"jquery-easing": "0.0.1", "jquery-easing": "0.0.1",
"jquery.browser": ">=0.1.0", "jquery.browser": ">=0.1.0",
"jshint": "^2.9.4", "jshint": "^2.9.4",
"lodash": "^4.17.4", "lodash": "^4.17.4",
"lodash-cli": "^4.17.4",
"moment": "~2.13.0", "moment": "~2.13.0",
"npm": "^4.1.1",
"otr": "0.2.16", "otr": "0.2.16",
"phantom-jasmine": "0.1.8", "phantom-jasmine": "0.1.8",
"phantomjs": "~1.9.7-1", "phantomjs": "~1.9.7-1",

View File

@ -154,8 +154,8 @@
var attrs = ['id', 'box_id', 'visible']; var attrs = ['id', 'box_id', 'visible'];
var new_attrs, old_attrs; var new_attrs, old_attrs;
for (var i=0; i<attrs.length; i++) { for (var i=0; i<attrs.length; i++) {
new_attrs = _.pluck(_.pluck(newchatboxes.models, 'attributes'), attrs[i]); new_attrs = _.map(_.map(newchatboxes.models, 'attributes'), attrs[i]);
old_attrs = _.pluck(_.pluck(converse.chatboxes.models, 'attributes'), attrs[i]); old_attrs = _.map(_.map(converse.chatboxes.models, 'attributes'), attrs[i]);
expect(_.isEqual(new_attrs, old_attrs)).toEqual(true); expect(_.isEqual(new_attrs, old_attrs)).toEqual(true);
} }
converse.rosterview.render(); converse.rosterview.render();
@ -739,7 +739,7 @@
sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
msg = $msg({ msg = $msg({
from: sender_jid, from: sender_jid,
to: converse.bare_jid+'/'+"some-other-resource", to: converse.bare_jid+"/some-other-resource",
type: 'chat', type: 'chat',
id: (new Date()).getTime() id: (new Date()).getTime()
}).c('body').t("This message will not be shown").up() }).c('body').t("This message will not be shown").up()
@ -758,7 +758,7 @@
message = "This message sent to a different resource will be shown"; message = "This message sent to a different resource will be shown";
msg = $msg({ msg = $msg({
from: sender_jid, from: sender_jid,
to: converse.bare_jid+'/'+"some-other-resource", to: converse.bare_jid+"/some-other-resource",
type: 'chat', type: 'chat',
id: '134234623462346' id: '134234623462346'
}).c('body').t(message).up() }).c('body').t(message).up()
@ -1571,7 +1571,7 @@
test_utils.openChatBoxFor(converse, sender_jid); test_utils.openChatBoxFor(converse, sender_jid);
var view = converse.chatboxviews.get(sender_jid); var view = converse.chatboxviews.get(sender_jid);
expect(view.$el.find('.chat-event').length).toBe(0); expect(view.$el.find('.chat-event').length).toBe(0);
view.showStatusNotification(sender_jid+' '+'is typing'); view.showStatusNotification(sender_jid+' is typing');
expect(view.$el.find('.chat-event').length).toBe(1); expect(view.$el.find('.chat-event').length).toBe(1);
var msg = $msg({ var msg = $msg({
from: sender_jid, from: sender_jid,

View File

@ -331,8 +331,8 @@
.c('x', { 'xmlns': 'jabber:x:data', 'type': 'form'}) .c('x', { 'xmlns': 'jabber:x:data', 'type': 'form'})
.c('title').t('Configuration for "coven" Room').up() .c('title').t('Configuration for "coven" Room').up()
.c('instructions').t('Complete this form to modify the configuration of your room.').up() .c('instructions').t('Complete this form to modify the configuration of your room.').up()
.c('field', {'type': 'hidden', 'var': 'FORM_TYPE'}). .c('field', {'type': 'hidden', 'var': 'FORM_TYPE'})
c('value').t('http://jabber.org/protocol/muc#roomconfig').up().up() .c('value').t('http://jabber.org/protocol/muc#roomconfig').up().up()
.c('field', { .c('field', {
'label': 'Natural-Language Room Name', 'label': 'Natural-Language Room Name',
'type': 'text-single', 'type': 'text-single',
@ -1078,8 +1078,8 @@
var attrs = ['id', 'box_id', 'visible']; var attrs = ['id', 'box_id', 'visible'];
var new_attrs, old_attrs; var new_attrs, old_attrs;
for (var i=0; i<attrs.length; i++) { for (var i=0; i<attrs.length; i++) {
new_attrs = _.pluck(_.pluck(newchatboxes.models, 'attributes'), attrs[i]); new_attrs = _.map(_.map(newchatboxes.models, 'attributes'), attrs[i]);
old_attrs = _.pluck(_.pluck(converse.chatboxes.models, 'attributes'), attrs[i]); old_attrs = _.map(_.map(converse.chatboxes.models, 'attributes'), attrs[i]);
// FIXME: should have have to sort here? Order must // FIXME: should have have to sort here? Order must
// probably be the same... // probably be the same...
// This should be fixed once the controlbox always opens // This should be fixed once the controlbox always opens

View File

@ -1031,7 +1031,7 @@
var stanza = $pres({from: 'data@enterprise/resource', type: 'subscribe'}); var stanza = $pres({from: 'data@enterprise/resource', type: 'subscribe'});
converse.connection._dataRecv(test_utils.createRequest(stanza)); converse.connection._dataRecv(test_utils.createRequest(stanza));
expect(converse.roster.pluck('jid').length).toBe(1); expect(converse.roster.pluck('jid').length).toBe(1);
expect(_.contains(converse.roster.pluck('jid'), 'data@enterprise')).toBeTruthy(); expect(_.includes(converse.roster.pluck('jid'), 'data@enterprise')).toBeTruthy();
// Taken from the spec // Taken from the spec
// http://xmpp.org/rfcs/rfc3921.html#rfc.section.7.3 // http://xmpp.org/rfcs/rfc3921.html#rfc.section.7.3
@ -1057,7 +1057,7 @@
subscription:'both' subscription:'both'
}).c('group').t('Friends'); }).c('group').t('Friends');
converse.roster.onReceivedFromServer(stanza.tree()); converse.roster.onReceivedFromServer(stanza.tree());
expect(_.contains(converse.roster.pluck('jid'), 'data@enterprise')).toBeTruthy(); expect(_.includes(converse.roster.pluck('jid'), 'data@enterprise')).toBeTruthy();
})); }));
}); });
@ -1083,8 +1083,8 @@
// have the same attributes values as the original ones. // have the same attributes values as the original ones.
attrs = ['jid', 'fullname', 'subscription', 'ask']; attrs = ['jid', 'fullname', 'subscription', 'ask'];
for (var i=0; i<attrs.length; i++) { for (var i=0; i<attrs.length; i++) {
new_attrs = _.pluck(_.pluck(new_roster.models, 'attributes'), attrs[i]); new_attrs = _.map(_.map(new_roster.models, 'attributes'), attrs[i]);
old_attrs = _.pluck(_.pluck(converse.roster.models, 'attributes'), attrs[i]); old_attrs = _.map(_.map(converse.roster.models, 'attributes'), attrs[i]);
// Roster items in storage are not necessarily sorted, // Roster items in storage are not necessarily sorted,
// so we have to sort them here to do a proper // so we have to sort them here to do a proper
// comparison // comparison

View File

@ -219,7 +219,7 @@
// You can retrieve multiple contacts by passing in an array // You can retrieve multiple contacts by passing in an array
var jid2 = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost'; var jid2 = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost';
var list = converse_api.contacts.get([jid, jid2]); var list = converse_api.contacts.get([jid, jid2]);
expect(Array.isArray(list)).toBeTruthy(); expect(_.isArray(list)).toBeTruthy();
expect(list[0].fullname).toBe(mock.cur_names[0]); expect(list[0].fullname).toBe(mock.cur_names[0]);
expect(list[1].fullname).toBe(mock.cur_names[1]); expect(list[1].fullname).toBe(mock.cur_names[1]);
// Check that all JIDs are returned if you call without any parameters // Check that all JIDs are returned if you call without any parameters
@ -262,7 +262,7 @@
var jid2 = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost'; var jid2 = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(converse, jid2); test_utils.openChatBoxFor(converse, jid2);
var list = converse_api.chats.get([jid, jid2]); var list = converse_api.chats.get([jid, jid2]);
expect(Array.isArray(list)).toBeTruthy(); expect(_.isArray(list)).toBeTruthy();
expect(list[0].get('box_id')).toBe(b64_sha1(jid)); expect(list[0].get('box_id')).toBe(b64_sha1(jid));
expect(list[1].get('box_id')).toBe(b64_sha1(jid2)); expect(list[1].get('box_id')).toBe(b64_sha1(jid2));
})); }));
@ -279,7 +279,7 @@
expect(box instanceof Object).toBeTruthy(); expect(box instanceof Object).toBeTruthy();
expect(box.get('box_id')).toBe(b64_sha1(jid)); expect(box.get('box_id')).toBe(b64_sha1(jid));
expect( expect(
Object.keys(box), _.keys(box),
['close', 'endOTR', 'focus', 'get', 'initiateOTR', 'is_chatroom', 'maximize', 'minimize', 'open', 'set'] ['close', 'endOTR', 'focus', 'get', 'initiateOTR', 'is_chatroom', 'maximize', 'minimize', 'open', 'set']
); );
chatboxview = converse.chatboxviews.get(jid); chatboxview = converse.chatboxviews.get(jid);
@ -287,7 +287,7 @@
// Test for multiple JIDs // Test for multiple JIDs
var jid2 = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost'; var jid2 = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost';
var list = converse_api.chats.open([jid, jid2]); var list = converse_api.chats.open([jid, jid2]);
expect(Array.isArray(list)).toBeTruthy(); expect(_.isArray(list)).toBeTruthy();
expect(list[0].get('box_id')).toBe(b64_sha1(jid)); expect(list[0].get('box_id')).toBe(b64_sha1(jid));
expect(list[1].get('box_id')).toBe(b64_sha1(jid2)); expect(list[1].get('box_id')).toBe(b64_sha1(jid2));
}); });
@ -296,7 +296,7 @@
describe("The \"settings\" API", function() { describe("The \"settings\" API", function() {
it("has methods 'get' and 'set' to set configuration settings", mock.initConverse(function (converse) { it("has methods 'get' and 'set' to set configuration settings", mock.initConverse(function (converse) {
expect(Object.keys(converse_api.settings)).toEqual(["get", "set"]); expect(_.keys(converse_api.settings)).toEqual(["get", "set"]);
expect(converse_api.settings.get("play_sounds")).toBe(false); expect(converse_api.settings.get("play_sounds")).toBe(false);
converse_api.settings.set("play_sounds", true); converse_api.settings.set("play_sounds", true);
expect(converse_api.settings.get("play_sounds")).toBe(true); expect(converse_api.settings.get("play_sounds")).toBe(true);

View File

@ -86,7 +86,7 @@
waits(250); waits(250);
runs(function () { runs(function () {
expect( expect(
_.contains( _.includes(
converse.chatboxviews.keys(), converse.chatboxviews.keys(),
'notify.example.com') 'notify.example.com')
).toBeTruthy(); ).toBeTruthy();

View File

@ -447,7 +447,7 @@
.c('never').up(); .c('never').up();
converse.connection._dataRecv(test_utils.createRequest(stanza)); converse.connection._dataRecv(test_utils.createRequest(stanza));
expect(feature.save).toHaveBeenCalled(); expect(feature.save).toHaveBeenCalled();
expect(feature.get('preferences').default).toBe('never'); expect(feature.get('preferences')['default']).toBe('never');
// Restore // Restore
converse.message_archiving = 'never'; converse.message_archiving = 'never';

View File

@ -39,7 +39,7 @@
expect(chatview.model.get('minimized')).toBeTruthy(); expect(chatview.model.get('minimized')).toBeTruthy();
expect(converse.minimized_chats.$el.is(':visible')).toBeTruthy(); expect(converse.minimized_chats.$el.is(':visible')).toBeTruthy();
expect(converse.minimized_chats.keys().length).toBe(2); expect(converse.minimized_chats.keys().length).toBe(2);
expect(_.contains(converse.minimized_chats.keys(), contact_jid)).toBeTruthy(); expect(_.includes(converse.minimized_chats.keys(), contact_jid)).toBeTruthy();
})); }));
it("can be toggled to hide or show minimized chats", mock.initConverse(function (converse) { it("can be toggled to hide or show minimized chats", mock.initConverse(function (converse) {

View File

@ -1,15 +1,16 @@
/*global converse */ /*global converse */
(function (root, factory) { (function (root, factory) {
define([ define([
"jquery", "converse-api",
"mock", "mock",
"test_utils", "test_utils",
"utils", "utils",
"transcripts" "transcripts"
], factory ], factory
); );
} (this, function ($, mock, test_utils, utils, transcripts) { } (this, function (converse_api, mock, test_utils, utils, transcripts) {
var _ = converse_api.env._; var _ = converse_api.env._;
var $ = converse_api.env.jQuery;
var Strophe = converse_api.env.Strophe; var Strophe = converse_api.env.Strophe;
var IGNORED_TAGS = [ var IGNORED_TAGS = [
'stream:features', 'stream:features',
@ -63,7 +64,7 @@
if (el.nodeType === 3) { if (el.nodeType === 3) {
return; // Ignore text return; // Ignore text
} }
if (_.contains(IGNORED_TAGS, el.nodeName.toLowerCase())) { if (_.includes(IGNORED_TAGS, el.nodeName.toLowerCase())) {
return; return;
} }
var _stanza = traverseElement(el); var _stanza = traverseElement(el);

View File

@ -43,7 +43,7 @@
expect(context.show_toolbar).toBeFalsy(); expect(context.show_toolbar).toBeFalsy();
expect(context.chatview_avatar_width).toBe(32); expect(context.chatview_avatar_width).toBe(32);
expect(context.chatview_avatar_height).toBe(48); expect(context.chatview_avatar_height).toBe(48);
expect(Object.keys(context.visible_toolbar_buttons)).toEqual(Object.keys(settings.visible_toolbar_buttons)); expect(_.keys(context.visible_toolbar_buttons)).toEqual(_.keys(settings.visible_toolbar_buttons));
expect(context.visible_toolbar_buttons.emoticons).toBeFalsy(); expect(context.visible_toolbar_buttons.emoticons).toBeFalsy();
expect(context.visible_toolbar_buttons.call).toBeFalsy(); expect(context.visible_toolbar_buttons.call).toBeFalsy();
expect(context.visible_toolbar_buttons.toggle_occupants).toBeFalsy(); expect(context.visible_toolbar_buttons.toggle_occupants).toBeFalsy();
@ -57,7 +57,7 @@
} }
}; };
utils.applyUserSettings(context, settings, user_settings); utils.applyUserSettings(context, settings, user_settings);
expect(Object.keys(context.visible_toolbar_buttons)).toEqual(Object.keys(settings.visible_toolbar_buttons)); expect(_.keys(context.visible_toolbar_buttons)).toEqual(_.keys(settings.visible_toolbar_buttons));
expect(context.visible_toolbar_buttons.toggle_occupants).toBeTruthy(); expect(context.visible_toolbar_buttons.toggle_occupants).toBeTruthy();
}); });
}); });

View File

@ -47,10 +47,10 @@
}, },
'set': function (value, message) { 'set': function (value, message) {
var data = {'status': value}; var data = {'status': value};
if (!_.contains(_.keys(converse.STATUS_WEIGHTS), value)) { if (!_.includes(_.keys(converse.STATUS_WEIGHTS), value)) {
throw new Error('Invalid availability value. See https://xmpp.org/rfcs/rfc3921.html#rfc.section.2.2.2.1'); throw new Error('Invalid availability value. See https://xmpp.org/rfcs/rfc3921.html#rfc.section.2.2.2.1');
} }
if (typeof message === "string") { if (_.isString(message)) {
data.status_message = message; data.status_message = message;
} }
converse.xmppstatus.sendPresence(value); converse.xmppstatus.sendPresence(value);
@ -68,17 +68,17 @@
}, },
'settings': { 'settings': {
'get': function (key) { 'get': function (key) {
if (_.contains(Object.keys(converse.default_settings), key)) { if (_.includes(_.keys(converse.default_settings), key)) {
return converse[key]; return converse[key];
} }
}, },
'set': function (key, val) { 'set': function (key, val) {
var o = {}; var o = {};
if (typeof key === "object") { if (_.isObject(key)) {
_.assignIn(converse, _.pick(key, Object.keys(converse.default_settings))); _.assignIn(converse, _.pick(key, _.keys(converse.default_settings)));
} else if (typeof key === "string") { } else if (_.isString("string")) {
o[key] = val; o[key] = val;
_.assignIn(converse, _.pick(o, Object.keys(converse.default_settings))); _.assignIn(converse, _.pick(o, _.keys(converse.default_settings)));
} }
} }
}, },
@ -91,15 +91,15 @@
} }
return null; return null;
}; };
if (typeof jids === "undefined") { if (_.isUndefined(jids)) {
jids = converse.roster.pluck('jid'); jids = converse.roster.pluck('jid');
} else if (typeof jids === "string") { } else if (_.isString(jids)) {
return _transform(jids); return _transform(jids);
} }
return _.map(jids, _transform); return _.map(jids, _transform);
}, },
'add': function (jid, name) { 'add': function (jid, name) {
if (typeof jid !== "string" || jid.indexOf('@') < 0) { if (!_.isString(jid) || !_.includes(jid, '@')) {
throw new TypeError('contacts.add: invalid jid'); throw new TypeError('contacts.add: invalid jid');
} }
converse.roster.addAndSubscribe(jid, _.isEmpty(name)? jid: name); converse.roster.addAndSubscribe(jid, _.isEmpty(name)? jid: name);
@ -108,10 +108,10 @@
'chats': { 'chats': {
'open': function (jids) { 'open': function (jids) {
var chatbox; var chatbox;
if (typeof jids === "undefined") { if (_.isUndefined(jids)) {
converse.log("chats.open: You need to provide at least one JID", "error"); converse.log("chats.open: You need to provide at least one JID", "error");
return null; return null;
} else if (typeof jids === "string") { } else if (_.isString(jids)) {
chatbox = converse.wrappedChatBox( chatbox = converse.wrappedChatBox(
converse.chatboxes.getChatBox(jids, true).trigger('show') converse.chatboxes.getChatBox(jids, true).trigger('show')
); );
@ -125,7 +125,7 @@
}); });
}, },
'get': function (jids) { 'get': function (jids) {
if (typeof jids === "undefined") { if (_.isUndefined(jids)) {
var result = []; var result = [];
converse.chatboxes.each(function (chatbox) { converse.chatboxes.each(function (chatbox) {
// FIXME: Leaky abstraction from MUC. We need to add a // FIXME: Leaky abstraction from MUC. We need to add a
@ -135,13 +135,14 @@
} }
}); });
return result; return result;
} else if (typeof jids === "string") { } else if (_.isString(jids)) {
return converse.wrappedChatBox(converse.chatboxes.getChatBox(jids)); return converse.wrappedChatBox(converse.chatboxes.getChatBox(jids));
} }
return _.map(jids, return _.map(jids,
_.partial( _.partial(
_.compose( _.flow(
converse.wrappedChatBox.bind(converse), converse.chatboxes.getChatBox.bind(converse.chatboxes) converse.chatboxes.getChatBox.bind(converse.chatboxes),
converse.wrappedChatBox.bind(converse)
), _, true ), _, true
) )
); );
@ -149,7 +150,7 @@
}, },
'tokens': { 'tokens': {
'get': function (id) { 'get': function (id) {
if (!converse.expose_rid_and_sid || typeof converse.connection === "undefined") { if (!converse.expose_rid_and_sid || _.isUndefined(converse.connection)) {
return null; return null;
} }
if (id.toLowerCase() === 'rid') { if (id.toLowerCase() === 'rid') {
@ -170,7 +171,7 @@
converse.off(evt, handler); converse.off(evt, handler);
}, },
'stanza': function (name, options, handler) { 'stanza': function (name, options, handler) {
if (typeof options === 'function') { if (_.isFunction(options)) {
handler = options; handler = options;
options = {}; options = {};
} else { } else {

View File

@ -207,7 +207,7 @@
model: converse.Bookmark, model: converse.Bookmark,
initialize: function () { initialize: function () {
this.on('add', _.compose(this.markRoomAsBookmarked, this.openBookmarkedRoom)); this.on('add', _.flow(this.openBookmarkedRoom, this.markRoomAsBookmarked));
this.on('remove', this.markRoomAsUnbookmarked, this); this.on('remove', this.markRoomAsUnbookmarked, this);
this.on('remove', this.sendBookmarkStanza, this); this.on('remove', this.sendBookmarkStanza, this);
@ -369,7 +369,7 @@
this.render(); this.render();
}, },
render: function (cfg) { render: function () {
this.$el.html(converse.templates.bookmarks_list({ this.$el.html(converse.templates.bookmarks_list({
'toggle_state': this.list_model.get('toggle-state'), 'toggle_state': this.list_model.get('toggle-state'),
'desc_bookmarks': __('Click to toggle the bookmarks list'), 'desc_bookmarks': __('Click to toggle the bookmarks list'),
@ -378,7 +378,7 @@
if (this.list_model.get('toggle-state') !== converse.OPENED) { if (this.list_model.get('toggle-state') !== converse.OPENED) {
this.$('.bookmarks').hide(); this.$('.bookmarks').hide();
} }
this.model.each(this.renderBookmarkListElement, this); this.model.each(this.renderBookmarkListElement.bind(this));
var controlboxview = converse.chatboxviews.get('controlbox'); var controlboxview = converse.chatboxviews.get('controlbox');
if (!_.isUndefined(controlboxview)) { if (!_.isUndefined(controlboxview)) {
this.$el.prependTo(controlboxview.$('#chatrooms')); this.$el.prependTo(controlboxview.$('#chatrooms'));

View File

@ -221,12 +221,12 @@
*/ */
var that = this; var that = this;
var insert = prepend ? this.$content.prepend : this.$content.append; var insert = prepend ? this.$content.prepend : this.$content.append;
_.compose( _.flow(
this.scrollDownMessageHeight.bind(this),
function ($el) { function ($el) {
insert.call(that.$content, $el); insert.call(that.$content, $el);
return $el; return $el;
} },
this.scrollDownMessageHeight.bind(this)
)(this.renderMessage(attrs)); )(this.renderMessage(attrs));
}, },
@ -282,18 +282,22 @@
msg_dates.push(current_msg_date); msg_dates.push(current_msg_date);
msg_dates.sort(); msg_dates.sort();
idx = msg_dates.indexOf(current_msg_date)-1; idx = msg_dates.indexOf(current_msg_date)-1;
_.compose( _.flow(
this.scrollDownMessageHeight.bind(this), function ($el) {
function ($el) { $el.insertAfter(this.$content.find('.chat-message[data-isodate="'+msg_dates[idx]+'"]'));
$el.insertAfter(this.$content.find('.chat-message[data-isodate="'+msg_dates[idx]+'"]')); return $el;
return $el; }.bind(this),
}.bind(this) this.scrollDownMessageHeight.bind(this)
)(this.renderMessage(attrs)); )(this.renderMessage(attrs));
}, },
getExtraMessageTemplateAttributes: function (attrs) { getExtraMessageTemplateAttributes: function () {
// Provides a hook for sending more attributes to the /* Provides a hook for sending more attributes to the
// message template. * message template.
*
* Parameters:
* (Object) attrs: An object containing message attributes.
*/
return {}; return {};
}, },
@ -373,7 +377,7 @@
this.clear_status_timeout = window.setTimeout(this.clearStatusNotification.bind(this), 30000); this.clear_status_timeout = window.setTimeout(this.clearStatusNotification.bind(this), 30000);
} else if (message.get('chat_state') === converse.PAUSED) { } else if (message.get('chat_state') === converse.PAUSED) {
this.showStatusNotification(message.get('fullname')+' '+__('has stopped typing')); this.showStatusNotification(message.get('fullname')+' '+__('has stopped typing'));
} else if (_.contains([converse.INACTIVE, converse.ACTIVE], message.get('chat_state'))) { } else if (_.includes([converse.INACTIVE, converse.ACTIVE], message.get('chat_state'))) {
this.$content.find('div.chat-event').remove(); this.$content.find('div.chat-event').remove();
} else if (message.get('chat_state') === converse.GONE) { } else if (message.get('chat_state') === converse.GONE) {
this.showStatusNotification(message.get('fullname')+' '+__('has gone away')); this.showStatusNotification(message.get('fullname')+' '+__('has gone away'));
@ -435,7 +439,7 @@
* Parameters: * Parameters:
* (Object) message - The message Backbone object that was added. * (Object) message - The message Backbone object that was added.
*/ */
if (typeof this.clear_status_timeout !== 'undefined') { if (!_.isUndefined(this.clear_status_timeout)) {
window.clearTimeout(this.clear_status_timeout); window.clearTimeout(this.clear_status_timeout);
delete this.clear_status_timeout; delete this.clear_status_timeout;
} }
@ -544,7 +548,7 @@
* (string) state - The chat state (consts ACTIVE, COMPOSING, PAUSED, INACTIVE, GONE) * (string) state - The chat state (consts ACTIVE, COMPOSING, PAUSED, INACTIVE, GONE)
* (Boolean) no_save - Just do the cleanup or setup but don't actually save the state. * (Boolean) no_save - Just do the cleanup or setup but don't actually save the state.
*/ */
if (typeof this.chat_state_timeout !== 'undefined') { if (!_.isUndefined(this.chat_state_timeout)) {
window.clearTimeout(this.chat_state_timeout); window.clearTimeout(this.chat_state_timeout);
delete this.chat_state_timeout; delete this.chat_state_timeout;
} }
@ -649,7 +653,7 @@
showStatusMessage: function (msg) { showStatusMessage: function (msg) {
msg = msg || this.model.get('status'); msg = msg || this.model.get('status');
if (typeof msg === "string") { if (_.isString(msg)) {
this.$el.find('p.user-custom-message').text(msg).attr('title', msg); this.$el.find('p.user-custom-message').text(msg).attr('title', msg);
} }
return this; return this;
@ -757,12 +761,12 @@
}, },
show: function (focus) { show: function (focus) {
if (typeof this.debouncedShow === 'undefined') { if (_.isUndefined(this.debouncedShow)) {
/* We wrap the method in a debouncer and set it on the /* We wrap the method in a debouncer and set it on the
* instance, so that we have it debounced per instance. * instance, so that we have it debounced per instance.
* Debouncing it on the class-level is too broad. * Debouncing it on the class-level is too broad.
*/ */
this.debouncedShow = _.debounce(this._show, 250, true); this.debouncedShow = _.debounce(this._show, 250, {'leading': true});
} }
this.debouncedShow.apply(this, arguments); this.debouncedShow.apply(this, arguments);
return this; return this;

View File

@ -120,7 +120,7 @@
onChatBoxesFetched: function (collection, resp) { onChatBoxesFetched: function (collection, resp) {
this.__super__.onChatBoxesFetched.apply(this, arguments); this.__super__.onChatBoxesFetched.apply(this, arguments);
if (!_.include(_.pluck(resp, 'id'), 'controlbox')) { if (!_.includes(_.map(resp, 'id'), 'controlbox')) {
this.add({ this.add({
id: 'controlbox', id: 'controlbox',
box_id: 'controlbox' box_id: 'controlbox'
@ -363,8 +363,12 @@
return this; return this;
}, },
showHelpMessages: function (msgs) { showHelpMessages: function () {
// Override showHelpMessages in ChatBoxView, for now do nothing. /* Override showHelpMessages in ChatBoxView, for now do nothing.
*
* Parameters:
* (Array) msgs: Array of messages
*/
return; return;
} }
}); });
@ -431,7 +435,7 @@
if (errors) { return; } if (errors) { return; }
if (converse.locked_domain) { if (converse.locked_domain) {
jid = Strophe.escapeNode(jid) + '@' + converse.locked_domain; jid = Strophe.escapeNode(jid) + '@' + converse.locked_domain;
} else if (converse.default_domain && jid.indexOf('@') === -1) { } else if (converse.default_domain && !_.includes(jid, '@')) {
jid = jid + '@' + converse.default_domain; jid = jid + '@' + converse.default_domain;
} }
this.connect($form, jid, password); this.connect($form, jid, password);
@ -723,7 +727,7 @@
}, },
updateOnlineCount: _.debounce(function () { updateOnlineCount: _.debounce(function () {
if (typeof converse.roster === 'undefined') { if (_.isUndefined(converse.roster)) {
return; return;
} }
var $count = this.$('#online-count'); var $count = this.$('#online-count');

View File

@ -117,8 +117,8 @@
converse.log = function (txt, level) { converse.log = function (txt, level) {
var logger; var logger;
if (typeof console === "undefined" || typeof console.log === "undefined") { if (_.isUndefined(console) || _.isUndefined(console.log)) {
logger = { log: function () {}, error: function () {} }; logger = { log: _.noop, error: _.noop };
} else { } else {
logger = console; logger = console;
} }
@ -134,11 +134,11 @@
converse.initialize = function (settings, callback) { converse.initialize = function (settings, callback) {
"use strict"; "use strict";
settings = typeof settings !== "undefined" ? settings : {}; settings = !_.isUndefined(settings) ? settings : {};
var init_deferred = new $.Deferred(); var init_deferred = new $.Deferred();
var converse = this; var converse = this;
if (typeof converse.chatboxes !== 'undefined') { if (!_.isUndefined(converse.chatboxes)) {
// Looks like converse.initialized was called again without logging // Looks like converse.initialized was called again without logging
// out or disconnecting in the previous session. // out or disconnecting in the previous session.
// This happens in tests. // This happens in tests.
@ -190,8 +190,8 @@
// Detect support for the user's locale // Detect support for the user's locale
// ------------------------------------ // ------------------------------------
var locales = typeof locales === "undefined" ? {} : locales; var locales = _.isUndefined(locales) ? {} : locales;
this.isConverseLocale = function (locale) { return typeof locales[locale] !== "undefined"; }; this.isConverseLocale = function (locale) { return !_.isUndefined(locales[locale]); };
this.isMomentLocale = function (locale) { return moment.locale() !== moment.locale(locale); }; this.isMomentLocale = function (locale) { return moment.locale() !== moment.locale(locale); };
if (!moment.locale) { //moment.lang is deprecated after 2.8.1, use moment.locale instead if (!moment.locale) { //moment.lang is deprecated after 2.8.1, use moment.locale instead
moment.locale = moment.lang; moment.locale = moment.lang;
@ -248,7 +248,7 @@
}; };
_.assignIn(this, this.default_settings); _.assignIn(this, this.default_settings);
// Allow only whitelisted configuration attributes to be overwritten // Allow only whitelisted configuration attributes to be overwritten
_.assignIn(this, _.pick(settings, Object.keys(this.default_settings))); _.assignIn(this, _.pick(settings, _.keys(this.default_settings)));
// BBB // BBB
if (this.prebind === true) { this.authentication = converse.PREBIND; } if (this.prebind === true) { this.authentication = converse.PREBIND; }
@ -265,7 +265,7 @@
// Module-level variables // Module-level variables
// ---------------------- // ----------------------
this.callback = callback || function () {}; this.callback = callback || _.noop;
/* When reloading the page: /* When reloading the page:
* For new sessions, we need to send out a presence stanza to notify * For new sessions, we need to send out a presence stanza to notify
* the server/network that we're online. * the server/network that we're online.
@ -300,11 +300,14 @@
}; };
this.sendCSI = function (stat) { this.sendCSI = function (stat) {
/* Send out a Chat Status Notification (XEP-0352) */ /* Send out a Chat Status Notification (XEP-0352)
if (converse.features[Strophe.NS.CSI] || true) { *
converse.connection.send($build(stat, {xmlns: Strophe.NS.CSI})); * Parameters:
converse.inactive = (stat === converse.INACTIVE) ? true : false; * (String) stat: The user's chat status
} */
// XXX if (converse.features[Strophe.NS.CSI] || true) {
converse.connection.send($build(stat, {xmlns: Strophe.NS.CSI}));
converse.inactive = (stat === converse.INACTIVE) ? true : false;
}; };
this.onUserActivity = function () { this.onUserActivity = function () {
@ -400,7 +403,7 @@
}; };
this.reconnect = _.debounce(function (condition) { this.reconnect = _.debounce(function () {
converse.log('The connection has dropped, attempting to reconnect.'); converse.log('The connection has dropped, attempting to reconnect.');
converse.giveFeedback( converse.giveFeedback(
__("Reconnecting"), __("Reconnecting"),
@ -547,7 +550,7 @@
this.logOut = function () { this.logOut = function () {
converse.setDisconnectionCause(converse.LOGOUT, undefined, true); converse.setDisconnectionCause(converse.LOGOUT, undefined, true);
if (typeof converse.connection !== 'undefined') { if (!_.isUndefined(converse.connection)) {
converse.connection.disconnect(); converse.connection.disconnect();
} }
converse.chatboxviews.closeAllChatBoxes(); converse.chatboxviews.closeAllChatBoxes();
@ -659,7 +662,7 @@
}; };
this.unregisterPresenceHandler = function () { this.unregisterPresenceHandler = function () {
if (typeof converse.presence_ref !== 'undefined') { if (!_.isUndefined(converse.presence_ref)) {
converse.connection.deleteHandler(converse.presence_ref); converse.connection.deleteHandler(converse.presence_ref);
delete converse.presence_ref; delete converse.presence_ref;
} }
@ -748,7 +751,7 @@
this.RosterContact = Backbone.Model.extend({ this.RosterContact = Backbone.Model.extend({
initialize: function (attributes, options) { initialize: function (attributes) {
var jid = attributes.jid; var jid = attributes.jid;
var bare_jid = Strophe.getBareJidFromJid(jid); var bare_jid = Strophe.getBareJidFromJid(jid);
var resource = Strophe.getResourceFromJid(jid); var resource = Strophe.getResourceFromJid(jid);
@ -804,7 +807,7 @@
})); }));
}, },
ackUnsubscribe: function (jid) { ackUnsubscribe: function () {
/* Upon receiving the presence stanza of type "unsubscribed", /* Upon receiving the presence stanza of type "unsubscribed",
* the user SHOULD acknowledge receipt of that subscription state * the user SHOULD acknowledge receipt of that subscription state
* notification by sending a presence stanza of type "unsubscribe" * notification by sending a presence stanza of type "unsubscribe"
@ -919,7 +922,7 @@
}, },
subscribeToSuggestedItems: function (msg) { subscribeToSuggestedItems: function (msg) {
$(msg).find('item').each(function (i, items) { $(msg).find('item').each(function () {
if (this.getAttribute('action') === 'add') { if (this.getAttribute('action') === 'add') {
converse.roster.addAndSubscribe( converse.roster.addAndSubscribe(
this.getAttribute('jid'), null, converse.xmppstatus.get('fullname')); this.getAttribute('jid'), null, converse.xmppstatus.get('fullname'));
@ -964,7 +967,7 @@
var iq = $iq({type: 'set'}) var iq = $iq({type: 'set'})
.c('query', {xmlns: Strophe.NS.ROSTER}) .c('query', {xmlns: Strophe.NS.ROSTER})
.c('item', { jid: jid, name: name }); .c('item', { jid: jid, name: name });
_.map(groups, function (group) { iq.c('group').t(group).up(); }); _.each(groups, function (group) { iq.c('group').t(group).up(); });
converse.connection.sendIQ(iq, callback, errback); converse.connection.sendIQ(iq, callback, errback);
}, },
@ -984,7 +987,7 @@
groups = groups || []; groups = groups || [];
name = _.isEmpty(name)? jid: name; name = _.isEmpty(name)? jid: name;
this.sendContactAddIQ(jid, name, groups, this.sendContactAddIQ(jid, name, groups,
function (iq) { function () {
var contact = this.create(_.assignIn({ var contact = this.create(_.assignIn({
ask: undefined, ask: undefined,
fullname: name, fullname: name,
@ -1010,7 +1013,7 @@
if (item) { if (item) {
resources = item.get('resources'); resources = item.get('resources');
if (resources) { if (resources) {
if (_.indexOf(resources, resource) === -1) { if (!_.includes(resources, resource)) {
resources.push(resource); resources.push(resource);
item.set({'resources': resources}); item.set({'resources': resources});
} }
@ -1044,7 +1047,7 @@
ignored = _.union(ignored, ['dnd', 'xa', 'away']); ignored = _.union(ignored, ['dnd', 'xa', 'away']);
} }
for (i=0; i<models_length; i++) { for (i=0; i<models_length; i++) {
if (_.indexOf(ignored, models[i].get('chat_status')) === -1) { if (!_.includes(ignored, models[i].get('chat_status'))) {
count++; count++;
} }
} }
@ -1107,13 +1110,10 @@
*/ */
var jid = item.getAttribute('jid'); var jid = item.getAttribute('jid');
if (this.isSelf(jid)) { return; } if (this.isSelf(jid)) { return; }
var groups = [], var groups = _.map(item.getElementsByTagName('group'), Strophe.getText),
contact = this.get(jid), contact = this.get(jid),
ask = item.getAttribute("ask"), ask = item.getAttribute("ask"),
subscription = item.getAttribute("subscription"); subscription = item.getAttribute("subscription");
$.map(item.getElementsByTagName('group'), function (group) {
groups.push(Strophe.getText(group));
});
if (!contact) { if (!contact) {
if ((subscription === "none" && ask === null) || (subscription === "remove")) { if ((subscription === "none" && ask === null) || (subscription === "remove")) {
return; // We're lazy when adding contacts. return; // We're lazy when adding contacts.
@ -1245,7 +1245,7 @@
this.RosterGroup = Backbone.Model.extend({ this.RosterGroup = Backbone.Model.extend({
initialize: function (attributes, options) { initialize: function (attributes) {
this.set(_.assignIn({ this.set(_.assignIn({
description: DESC_GROUP_TOGGLE, description: DESC_GROUP_TOGGLE,
state: converse.OPENED state: converse.OPENED
@ -1360,7 +1360,7 @@
}; };
}, },
createMessage: function ($message, $delay, original_stanza) { createMessage: function () {
return this.messages.create(this.getMessageAttributes.apply(this, arguments)); return this.messages.create(this.getMessageAttributes.apply(this, arguments));
} }
}); });
@ -1617,8 +1617,8 @@
constructPresence: function (type, status_message) { constructPresence: function (type, status_message) {
var presence; var presence;
type = typeof type === 'string' ? type : (this.get('status') || converse.default_state); type = _.isString(type) ? type : (this.get('status') || converse.default_state);
status_message = typeof status_message === 'string' ? status_message : undefined; status_message = _.isString(status_message) ? status_message : undefined;
// Most of these presence types are actually not explicitly sent, // Most of these presence types are actually not explicitly sent,
// but I add all of them here for reference and future proofing. // but I add all of them here for reference and future proofing.
if ((type === 'unavailable') || if ((type === 'unavailable') ||

View File

@ -110,7 +110,7 @@
* We need this information for the drag-resizing feature. * We need this information for the drag-resizing feature.
*/ */
var $flyout = this.$el.find('.box-flyout'); var $flyout = this.$el.find('.box-flyout');
if (typeof this.model.get('height') === 'undefined') { if (_.isUndefined(this.model.get('height'))) {
var height = $flyout.height(); var height = $flyout.height();
var width = $flyout.width(); var width = $flyout.width();
this.model.set('height', height); this.model.set('height', height);
@ -212,7 +212,7 @@
this.setChatBoxHeight(this.height); this.setChatBoxHeight(this.height);
} }
} }
if (converse.resizing.direction.indexOf('left') !== -1) { if (_.includes(converse.resizing.direction, 'left')) {
diff = this.prev_pageX - ev.pageX; diff = this.prev_pageX - ev.pageX;
if (diff) { if (diff) {
this.width = ((this.width+diff) > (this.model.get('min_width') || 0)) ? (this.width+diff) : this.model.get('min_width'); this.width = ((this.width+diff) > (this.model.get('min_width') || 0)) ? (this.width+diff) : this.model.get('min_width');
@ -292,9 +292,9 @@
* default_value. If value is close enough to * default_value. If value is close enough to
* default_value, then default_value is returned instead. * default_value, then default_value is returned instead.
*/ */
if (typeof value === 'undefined') { if (_.isUndefined(value)) {
return undefined; return undefined;
} else if (typeof default_value === 'undefined') { } else if (_.isUndefined(default_value)) {
return value; return value;
} }
var resistance = 10; var resistance = 10;

View File

@ -76,7 +76,7 @@
}, },
initialize: function () { initialize: function () {
if (typeof this.setDimensions !== "undefined") { if (!_.isUndefined(this.setDimensions)) {
// setDimensions is defined for dragresize // setDimensions is defined for dragresize
$(window).on('resize', _.debounce(this.setDimensions.bind(this), 100)); $(window).on('resize', _.debounce(this.setDimensions.bind(this), 100));
} }
@ -103,7 +103,7 @@
) )
) )
); );
if (typeof this.setWidth !== "undefined") { if (!_.isUndefined(this.setWidth)) {
// setWidth is defined for dragresize // setWidth is defined for dragresize
$(window).on('resize', _.debounce(this.setWidth.bind(this), 100)); $(window).on('resize', _.debounce(this.setWidth.bind(this), 100));
} }

View File

@ -99,7 +99,7 @@
converse.queryForArchivedMessages(options, function (messages) { converse.queryForArchivedMessages(options, function (messages) {
this.clearSpinner(); this.clearSpinner();
if (messages.length) { if (messages.length) {
_.map(messages, converse.chatboxes.onMessage.bind(converse.chatboxes)); _.each(messages, converse.chatboxes.onMessage.bind(converse.chatboxes));
} }
}.bind(this), }.bind(this),
function () { function () {
@ -163,7 +163,7 @@
* get the next or previous page in the result set. * get the next or previous page in the result set.
*/ */
var date, messages = []; var date, messages = [];
if (typeof options === "function") { if (_.isFunction(options)) {
callback = options; callback = options;
errback = callback; errback = callback;
} }
@ -176,14 +176,14 @@
*/ */
var queryid = converse.connection.getUniqueId(); var queryid = converse.connection.getUniqueId();
var attrs = {'type':'set'}; var attrs = {'type':'set'};
if (typeof options !== "undefined" && options.groupchat) { if (!_.isUndefined(options) && options.groupchat) {
if (!options['with']) { if (!options['with']) {
throw new Error('You need to specify a "with" value containing the chat room JID, when querying groupchat messages.'); throw new Error('You need to specify a "with" value containing the chat room JID, when querying groupchat messages.');
} }
attrs.to = options['with']; attrs.to = options['with'];
} }
var stanza = $iq(attrs).c('query', {'xmlns':Strophe.NS.MAM, 'queryid':queryid}); var stanza = $iq(attrs).c('query', {'xmlns':Strophe.NS.MAM, 'queryid':queryid});
if (typeof options !== "undefined") { if (!_.isUndefined(options)) {
stanza.c('x', {'xmlns':Strophe.NS.XFORM, 'type': 'submit'}) stanza.c('x', {'xmlns':Strophe.NS.XFORM, 'type': 'submit'})
.c('field', {'var':'FORM_TYPE', 'type': 'hidden'}) .c('field', {'var':'FORM_TYPE', 'type': 'hidden'})
.c('value').t(Strophe.NS.MAM).up().up(); .c('value').t(Strophe.NS.MAM).up().up();
@ -209,7 +209,7 @@
} }
} }
if (typeof callback === "function") { if (_.isFunction(callback)) {
converse.connection.addHandler(function (message) { converse.connection.addHandler(function (message) {
var $msg = $(message), rsm, var $msg = $(message), rsm,
$fin = $msg.find('fin[xmlns="'+Strophe.NS.MAM+'"]'); $fin = $msg.find('fin[xmlns="'+Strophe.NS.MAM+'"]');

View File

@ -255,7 +255,7 @@
} }
var oldest_chat, boxes_width, view, var oldest_chat, boxes_width, view,
$minimized = converse.minimized_chats.$el, $minimized = converse.minimized_chats.$el,
minimized_width = _.contains(this.model.pluck('minimized'), true) ? $minimized.outerWidth(true) : 0, minimized_width = _.includes(this.model.pluck('minimized'), true) ? $minimized.outerWidth(true) : 0,
new_id = newchat ? newchat.model.get('id') : null; new_id = newchat ? newchat.model.get('id') : null;
boxes_width = _.reduce(this.xget(new_id), function (memo, view) { boxes_width = _.reduce(this.xget(new_id), function (memo, view) {
@ -283,7 +283,7 @@
exclude_ids.push('controlbox'); exclude_ids.push('controlbox');
var i = 0; var i = 0;
var model = this.model.sort().at(i); var model = this.model.sort().at(i);
while (_.contains(exclude_ids, model.get('id')) || while (_.includes(exclude_ids, model.get('id')) ||
model.get('minimized') === true) { model.get('minimized') === true) {
i++; i++;
model = this.model.at(i); model = this.model.at(i);
@ -370,7 +370,7 @@
this.model.messages.off('add',null,this); this.model.messages.off('add',null,this);
this.remove(); this.remove();
this.model.maximize(); this.model.maximize();
}, 200, true) }, 200, {'leading': true})
}); });
converse.MinimizedChats = Backbone.Overview.extend({ converse.MinimizedChats = Backbone.Overview.extend({

View File

@ -496,13 +496,15 @@
this.insertIntoTextArea(ev.target.textContent); this.insertIntoTextArea(ev.target.textContent);
}, },
requestMemberList: function (affiliation) { requestMemberList: function (chatroom_jid, affiliation) {
/* Send an IQ stanza to the server, asking it for the /* Send an IQ stanza to the server, asking it for the
* member-list of this room. * member-list of this room.
* *
* See: http://xmpp.org/extensions/xep-0045.html#modifymember * See: http://xmpp.org/extensions/xep-0045.html#modifymember
* *
* Parameters: * Parameters:
* (String) chatroom_jid: The JID of the chatroom for
* which the member-list is being requested
* (String) affiliation: The specific member list to * (String) affiliation: The specific member list to
* fetch. 'admin', 'owner' or 'member'. * fetch. 'admin', 'owner' or 'member'.
* *
@ -512,7 +514,7 @@
*/ */
var deferred = new $.Deferred(); var deferred = new $.Deferred();
affiliation = affiliation || 'member'; affiliation = affiliation || 'member';
var iq = $iq({to: this.model.get('jid'), type: "get"}) var iq = $iq({to: chatroom_jid, type: "get"})
.c("query", {xmlns: Strophe.NS.MUC_ADMIN}) .c("query", {xmlns: Strophe.NS.MUC_ADMIN})
.c("item", {'affiliation': affiliation}); .c("item", {'affiliation': affiliation});
converse.connection.sendIQ(iq, deferred.resolve, deferred.reject); converse.connection.sendIQ(iq, deferred.resolve, deferred.reject);
@ -561,8 +563,8 @@
* (Array) new_list: Array containing the new affiliations * (Array) new_list: Array containing the new affiliations
* (Array) old_list: Array containing the old affiliations * (Array) old_list: Array containing the old affiliations
*/ */
var new_jids = _.pluck(new_list, 'jid'); var new_jids = _.map(new_list, 'jid');
var old_jids = _.pluck(old_list, 'jid'); var old_jids = _.map(old_list, 'jid');
// Get the new affiliations // Get the new affiliations
var delta = _.map(_.difference(new_jids, old_jids), function (jid) { var delta = _.map(_.difference(new_jids, old_jids), function (jid) {
@ -587,6 +589,30 @@
return delta; return delta;
}, },
sendAffiliationIQ: function (chatroom_jid, affiliation, member) {
/* Send an IQ stanza specifying an affiliation change.
*
* Paremeters:
* (String) chatroom_jid: JID of the relevant room
* (String) affiliation: affiliation (could also be stored
* on the member object).
* (Object) member: Map containing the member's jid and
* optionally a reason and affiliation.
*/
var deferred = new $.Deferred();
var iq = $iq({to: chatroom_jid, type: "set"})
.c("query", {xmlns: Strophe.NS.MUC_ADMIN})
.c("item", {
'affiliation': member.affiliation || affiliation,
'jid': member.jid
});
if (!_.isUndefined(member.reason)) {
iq.c("reason", member.reason);
}
converse.connection.sendIQ(iq, deferred.resolve, deferred.reject);
return deferred;
},
setAffiliation: function (affiliation, members) { setAffiliation: function (affiliation, members) {
/* Send IQ stanzas to the server to set an affiliation for /* Send IQ stanzas to the server to set an affiliation for
* the provided JIDs. * the provided JIDs.
@ -599,6 +625,7 @@
* Related ticket: https://prosody.im/issues/issue/795 * Related ticket: https://prosody.im/issues/issue/795
* *
* Parameters: * Parameters:
* (String) affiliation: The affiliation
* (Object) members: A map of jids, affiliations and * (Object) members: A map of jids, affiliations and
* optionally reasons. Only those entries with the * optionally reasons. Only those entries with the
* same affiliation as being currently set will be * same affiliation as being currently set will be
@ -615,21 +642,11 @@
return _.isUndefined(member.affiliation) || return _.isUndefined(member.affiliation) ||
member.affiliation === affiliation; member.affiliation === affiliation;
}); });
var promises = _.map(members, function (member) { var promises = _.map(
var deferred = new $.Deferred(); members,
var iq = $iq({to: this.model.get('jid'), type: "set"}) _.partial(this.sendAffiliationIQ, this.model.get('jid'), affiliation)
.c("query", {xmlns: Strophe.NS.MUC_ADMIN}) );
.c("item", { return $.when.apply($, promises);
'affiliation': member.affiliation || affiliation,
'jid': member.jid
});
if (!_.isUndefined(member.reason)) {
iq.c("reason", member.reason);
}
converse.connection.sendIQ(iq, deferred.resolve, deferred.reject);
return deferred;
}, this);
return $.when.apply($, promises);
}, },
setAffiliations: function (members, onSuccess, onError) { setAffiliations: function (members, onSuccess, onError) {
@ -648,8 +665,8 @@
onSuccess(null); onSuccess(null);
return; return;
} }
var affiliations = _.uniq(_.pluck(members, 'affiliation')); var affiliations = _.uniq(_.map(members, 'affiliation'));
var promises = _.map(affiliations, _.partial(this.setAffiliation, _, members), this); var promises = _.map(affiliations, _.partial(this.setAffiliation.bind(this), _, members));
$.when.apply($, promises).done(onSuccess).fail(onError); $.when.apply($, promises).done(onSuccess).fail(onError);
}, },
@ -661,24 +678,20 @@
* Any amount of XMLElement objects, representing the IQ * Any amount of XMLElement objects, representing the IQ
* stanzas. * stanzas.
*/ */
return _.flatten(_.map(arguments, this.parseMemberListIQ)); return _.flatMap(arguments, this.parseMemberListIQ);
}, },
getJidsWithAffiliations: function (affiliations) { getJidsWithAffiliations: function (affiliations) {
/* Returns a map of JIDs that have the affiliations /* Returns a map of JIDs that have the affiliations
* as provided. * as provided.
*/ */
if (typeof affiliations === "string") { if (_.isString(affiliations)) {
affiliations = [affiliations]; affiliations = [affiliations];
} }
var that = this;
var deferred = new $.Deferred(); var deferred = new $.Deferred();
var promises = []; var promises = _.map(affiliations, _.partial(this.requestMemberList, this.model.get('jid')));
_.each(affiliations, function (affiliation) {
promises.push(that.requestMemberList(affiliation));
});
$.when.apply($, promises).always( $.when.apply($, promises).always(
_.compose(deferred.resolve, this.marshallAffiliationIQs.bind(this)) _.flow(this.marshallAffiliationIQs.bind(this), deferred.resolve)
); );
return deferred.promise(); return deferred.promise();
}, },
@ -838,7 +851,7 @@
clearChatRoomMessages: function (ev) { clearChatRoomMessages: function (ev) {
/* Remove all messages from the chat room UI. /* Remove all messages from the chat room UI.
*/ */
if (typeof ev !== "undefined") { ev.stopPropagation(); } if (!_.isUndefined(ev)) { ev.stopPropagation(); }
var result = confirm(__("Are you sure you want to clear the messages from this room?")); var result = confirm(__("Are you sure you want to clear the messages from this room?"));
if (result === true) { if (result === true) {
this.$content.empty(); this.$content.empty();
@ -995,7 +1008,7 @@
room_no_longer_anon || room_now_semi_anon || room_now_fully_anon) { room_no_longer_anon || room_now_semi_anon || room_now_fully_anon) {
this.getRoomFeatures(); this.getRoomFeatures();
} }
_.compose(this.onChatRoomMessage.bind(this), this.showStatusMessages.bind(this))(stanza); _.flow(this.showStatusMessages.bind(this), this.onChatRoomMessage.bind(this))(stanza);
return true; return true;
}, },
@ -1354,7 +1367,7 @@
if (_.isUndefined(ev) && this.model.get('auto_configure')) { if (_.isUndefined(ev) && this.model.get('auto_configure')) {
this.fetchRoomConfiguration().then(that.autoConfigureChatRoom.bind(that)); this.fetchRoomConfiguration().then(that.autoConfigureChatRoom.bind(that));
} else { } else {
if (typeof ev !== 'undefined' && ev.preventDefault) { if (!_.isUndefined(ev) && ev.preventDefault) {
ev.preventDefault(); ev.preventDefault();
} }
this.showSpinner(); this.showSpinner();
@ -1472,7 +1485,7 @@
*/ */
this.$('.chatroom-body').children().addClass('hidden'); this.$('.chatroom-body').children().addClass('hidden');
this.$('span.centered.spinner').remove(); this.$('span.centered.spinner').remove();
if (typeof message !== "string") { if (!_.isString(message)) {
message = ''; message = '';
} }
this.$('.chatroom-body').append( this.$('.chatroom-body').append(
@ -1583,7 +1596,7 @@
'messages': _.reject(_.map(statuses, mapper), _.isUndefined), 'messages': _.reject(_.map(statuses, mapper), _.isUndefined),
}; };
// 2. Get disconnection messages based on the <status> elements // 2. Get disconnection messages based on the <status> elements
var codes = _.map(statuses, function (stat) { return stat.getAttribute('code'); }); var codes = _.invokeMap(statuses, Element.prototype.getAttribute, 'code');
var disconnection_codes = _.intersection(codes, _.keys(converse.muc.disconnect_messages)); var disconnection_codes = _.intersection(codes, _.keys(converse.muc.disconnect_messages));
var disconnected = is_self && disconnection_codes.length > 0; var disconnected = is_self && disconnection_codes.length > 0;
if (disconnected) { if (disconnected) {
@ -1649,10 +1662,12 @@
// Unfortunately this doesn't work (returns empty list) // Unfortunately this doesn't work (returns empty list)
// var elements = stanza.querySelectorAll('x[xmlns="'+Strophe.NS.MUC_USER+'"]'); // var elements = stanza.querySelectorAll('x[xmlns="'+Strophe.NS.MUC_USER+'"]');
var elements = _.chain(stanza.querySelectorAll('x')).filter(function (x) { var elements = _.filter(
return x.getAttribute('xmlns') === Strophe.NS.MUC_USER; stanza.querySelectorAll('x'),
}).value(); function (x) {
return x.getAttribute('xmlns') === Strophe.NS.MUC_USER;
}
);
var notifications = _.map( var notifications = _.map(
elements, elements,
_.partial(this.parseXUserElement.bind(this), _, stanza, is_self) _.partial(this.parseXUserElement.bind(this), _, stanza, is_self)
@ -1845,7 +1860,7 @@
function (messages) { function (messages) {
that.clearSpinner(); that.clearSpinner();
if (messages.length) { if (messages.length) {
_.map(messages, that.onChatRoomMessage.bind(that)); _.each(messages, that.onChatRoomMessage.bind(that));
} }
}, },
function () { function () {
@ -2027,11 +2042,12 @@
}, { }, {
name: 'contacts-dataset', name: 'contacts-dataset',
source: function (q, cb) { source: function (q, cb) {
var results = []; cb(_.map(
_.each(converse.roster.filter(utils.contains(['fullname', 'jid'], q)), function (n) { converse.roster.filter(utils.contains(['fullname', 'jid'], q)),
results.push({value: n.get('fullname'), jid: n.get('jid')}); function (n) {
}); return {value: n.get('fullname'), jid: n.get('jid')};
cb(results); }
));
}, },
templates: { templates: {
suggestion: _.template('<p data-jid="{{jid}}">{{value}}</p>') suggestion: _.template('<p data-jid="{{jid}}">{{value}}</p>')
@ -2331,7 +2347,7 @@
'box_id': b64_sha1(room_jid), 'box_id': b64_sha1(room_jid),
'password': $x.attr('password') 'password': $x.attr('password')
}); });
if (!_.contains( if (!_.includes(
[Strophe.Status.CONNECTING, Strophe.Status.CONNECTED], [Strophe.Status.CONNECTING, Strophe.Status.CONNECTED],
chatroom.get('connection_status')) chatroom.get('connection_status'))
) { ) {
@ -2359,9 +2375,9 @@
* settings). * settings).
*/ */
_.each(converse.auto_join_rooms, function (room) { _.each(converse.auto_join_rooms, function (room) {
if (typeof room === 'string') { if (_.isString(room)) {
converse_api.rooms.open(room); converse_api.rooms.open(room);
} else if (typeof room === 'object') { } else if (_.isObject(room)) {
converse_api.rooms.open(room.jid, room.nick); converse_api.rooms.open(room.jid, room.nick);
} else { } else {
converse.log('Invalid room criteria specified for "auto_join_rooms"', 'error'); converse.log('Invalid room criteria specified for "auto_join_rooms"', 'error');
@ -2388,26 +2404,26 @@
_.extend(converse_api, { _.extend(converse_api, {
'rooms': { 'rooms': {
'close': function (jids) { 'close': function (jids) {
if (typeof jids === "undefined") { if (_.isUndefined(jids)) {
converse.chatboxviews.each(function (view) { converse.chatboxviews.each(function (view) {
if (view.is_chatroom && view.model) { if (view.is_chatroom && view.model) {
view.close(); view.close();
} }
}); });
} else if (typeof jids === "string") { } else if (_.isString(jids)) {
var view = converse.chatboxviews.get(jids); var view = converse.chatboxviews.get(jids);
if (view) { view.close(); } if (view) { view.close(); }
} else { } else {
_.map(jids, function (jid) { _.each(jids, function (jid) {
var view = converse.chatboxviews.get(jid); var view = converse.chatboxviews.get(jid);
if (view) { view.close(); } if (view) { view.close(); }
}); });
} }
}, },
'open': function (jids, attrs) { 'open': function (jids, attrs) {
if (typeof attrs === "string") { if (_.isString(attrs)) {
attrs = {'nick': attrs}; attrs = {'nick': attrs};
} else if (typeof attrs === "undefined") { } else if (_.isUndefined(attrs)) {
attrs = {}; attrs = {};
} }
if (_.isUndefined(attrs.maximize)) { if (_.isUndefined(attrs.maximize)) {
@ -2416,20 +2432,20 @@
if (!attrs.nick && converse.muc_nickname_from_jid) { if (!attrs.nick && converse.muc_nickname_from_jid) {
attrs.nick = Strophe.getNodeFromJid(converse.bare_jid); attrs.nick = Strophe.getNodeFromJid(converse.bare_jid);
} }
if (typeof jids === "undefined") { if (_.isUndefined(jids)) {
throw new TypeError('rooms.open: You need to provide at least one JID'); throw new TypeError('rooms.open: You need to provide at least one JID');
} else if (typeof jids === "string") { } else if (_.isString(jids)) {
return converse.getWrappedChatRoom(jids, attrs, converse.createChatRoom); return converse.getWrappedChatRoom(jids, attrs, converse.createChatRoom);
} }
return _.map(jids, _.partial(converse.getWrappedChatRoom, _, attrs, converse.createChatRoom)); return _.map(jids, _.partial(converse.getWrappedChatRoom, _, attrs, converse.createChatRoom));
}, },
'get': function (jids, attrs, create) { 'get': function (jids, attrs, create) {
if (typeof attrs === "string") { if (_.isString(attrs)) {
attrs = {'nick': attrs}; attrs = {'nick': attrs};
} else if (typeof attrs === "undefined") { } else if (_.isUndefined(attrs)) {
attrs = {}; attrs = {};
} }
if (typeof jids === "undefined") { if (_.isUndefined(jids)) {
var result = []; var result = [];
converse.chatboxes.each(function (chatbox) { converse.chatboxes.each(function (chatbox) {
if (chatbox.get('type') === 'chatroom') { if (chatbox.get('type') === 'chatroom') {
@ -2442,7 +2458,7 @@
if (!attrs.nick) { if (!attrs.nick) {
attrs.nick = Strophe.getNodeFromJid(converse.bare_jid); attrs.nick = Strophe.getNodeFromJid(converse.bare_jid);
} }
if (typeof jids === "string") { if (_.isString(jids)) {
return converse.getWrappedChatRoom(jids, attrs, fetcher); return converse.getWrappedChatRoom(jids, attrs, fetcher);
} }
return _.map(jids, _.partial(converse.getWrappedChatRoom, _, attrs, fetcher)); return _.map(jids, _.partial(converse.getWrappedChatRoom, _, attrs, fetcher));

View File

@ -68,7 +68,7 @@
return false; return false;
} }
var mentioned = (new RegExp("\\b"+room.get('nick')+"\\b")).test($body.text()); var mentioned = (new RegExp("\\b"+room.get('nick')+"\\b")).test($body.text());
notify_all = notify_all === true || (_.isArray(notify_all) && _.contains(notify_all, room_jid)); notify_all = notify_all === true || (_.isArray(notify_all) && _.includes(notify_all, room_jid));
if (sender === room.get('nick') || (!notify_all && !mentioned)) { if (sender === room.get('nick') || (!notify_all && !mentioned)) {
return false; return false;
} }
@ -102,7 +102,7 @@
// feature, but no browser currently supports it. // feature, but no browser currently supports it.
// https://developer.mozilla.org/en-US/docs/Web/API/notification/sound // https://developer.mozilla.org/en-US/docs/Web/API/notification/sound
var audio; var audio;
if (converse.play_sounds && typeof Audio !== "undefined") { if (converse.play_sounds && !_.isUndefined(Audio)) {
audio = new Audio(converse.sounds_path+"msg_received.ogg"); audio = new Audio(converse.sounds_path+"msg_received.ogg");
if (audio.canPlayType('/audio/ogg')) { if (audio.canPlayType('/audio/ogg')) {
audio.play(); audio.play();
@ -130,7 +130,7 @@
*/ */
var n, title, contact_jid, roster_item, var n, title, contact_jid, roster_item,
from_jid = $message.attr('from'); from_jid = $message.attr('from');
if ($message.attr('type') === 'headline' || from_jid.indexOf('@') === -1) { if ($message.attr('type') === 'headline' || !_.includes(from_jid, '@')) {
// XXX: 2nd check is workaround for Prosody which doesn't // XXX: 2nd check is workaround for Prosody which doesn't
// give type "headline" // give type "headline"
title = __(___("Notification from %1$s"), from_jid); title = __(___("Notification from %1$s"), from_jid);
@ -138,7 +138,7 @@
if ($message.attr('type') === 'groupchat') { if ($message.attr('type') === 'groupchat') {
title = __(___("%1$s says"), Strophe.getResourceFromJid(from_jid)); title = __(___("%1$s says"), Strophe.getResourceFromJid(from_jid));
} else { } else {
if (typeof converse.roster === 'undefined') { if (_.isUndefined(converse.roster)) {
converse.log("Could not send notification, because roster is undefined", "error"); converse.log("Could not send notification, because roster is undefined", "error");
return; return;
} }
@ -159,7 +159,7 @@
/* Creates an HTML5 Notification to inform of a change in a /* Creates an HTML5 Notification to inform of a change in a
* contact's chat state. * contact's chat state.
*/ */
if (_.contains(converse.chatstate_notification_blacklist, contact.jid)) { if (_.includes(converse.chatstate_notification_blacklist, contact.jid)) {
// Don't notify if the user is being ignored. // Don't notify if the user is being ignored.
return; return;
} }
@ -243,7 +243,7 @@
converse.requestPermission = function (evt) { converse.requestPermission = function (evt) {
if (converse.supports_html5_notification && if (converse.supports_html5_notification &&
! _.contains(['denied', 'granted'], Notification.permission)) { ! _.includes(['denied', 'granted'], Notification.permission)) {
// Ask user to enable HTML5 notifications // Ask user to enable HTML5 notifications
Notification.requestPermission(); Notification.requestPermission();
} }

View File

@ -30,14 +30,13 @@
// For translations // For translations
var __ = utils.__.bind(converse); var __ = utils.__.bind(converse);
var HAS_CSPRNG = ((typeof crypto !== 'undefined') && var HAS_CSPRNG = ((!_.isUndefined(crypto)) &&
((typeof crypto.randomBytes === 'function') || ((_.isFunction(crypto.randomBytes)) || (_.isFunction(crypto.getRandomValues))
(typeof crypto.getRandomValues === 'function')
)); ));
var HAS_CRYPTO = HAS_CSPRNG && ( var HAS_CRYPTO = HAS_CSPRNG && (
(typeof CryptoJS !== "undefined") && (!_.isUndefined(CryptoJS)) &&
(typeof otr.OTR !== "undefined") && (!_.isUndefined(otr.OTR)) &&
(typeof otr.DSA !== "undefined") (!_.isUndefined(otr.DSA))
); );
var UNENCRYPTED = 0; var UNENCRYPTED = 0;
@ -105,7 +104,7 @@
* "visible" OTR messages being exchanged. * "visible" OTR messages being exchanged.
*/ */
return this.__super__.shouldPlayNotification.apply(this, arguments) && return this.__super__.shouldPlayNotification.apply(this, arguments) &&
!(utils.isOTRMessage($message[0]) && !_.contains([UNVERIFIED, VERIFIED], this.get('otr_status'))); !(utils.isOTRMessage($message[0]) && !_.includes([UNVERIFIED, VERIFIED], this.get('otr_status')));
}, },
createMessage: function ($message, $delay, original_stanza) { createMessage: function ($message, $delay, original_stanza) {
@ -119,7 +118,7 @@
if (text.match(/^\?OTRv23?/)) { if (text.match(/^\?OTRv23?/)) {
this.initiateOTR(text); this.initiateOTR(text);
} else { } else {
if (_.contains([UNVERIFIED, VERIFIED], this.get('otr_status'))) { if (_.includes([UNVERIFIED, VERIFIED], this.get('otr_status'))) {
this.otr.receiveMsg(text); this.otr.receiveMsg(text);
} else { } else {
if (text.match(/^\?OTR/)) { if (text.match(/^\?OTR/)) {
@ -142,11 +141,11 @@
var pass, instance_tag, saved_key, pass_check; var pass, instance_tag, saved_key, pass_check;
if (converse.cache_otr_key) { if (converse.cache_otr_key) {
pass = converse.otr.getSessionPassphrase(); pass = converse.otr.getSessionPassphrase();
if (typeof pass !== "undefined") { if (!_.isUndefined(pass)) {
instance_tag = window.sessionStorage[b64_sha1(this.id+'instance_tag')]; instance_tag = window.sessionStorage[b64_sha1(this.id+'instance_tag')];
saved_key = window.sessionStorage[b64_sha1(this.id+'priv_key')]; saved_key = window.sessionStorage[b64_sha1(this.id+'priv_key')];
pass_check = window.sessionStorage[b64_sha1(this.connection.jid+'pass_check')]; pass_check = window.sessionStorage[b64_sha1(this.connection.jid+'pass_check')];
if (saved_key && instance_tag && typeof pass_check !== 'undefined') { if (saved_key && instance_tag && !_.isUndefined(pass_check)) {
var decrypted = cipher.decrypt(CryptoJS.algo.AES, saved_key, pass); var decrypted = cipher.decrypt(CryptoJS.algo.AES, saved_key, pass);
var key = otr.DSA.parsePrivate(decrypted.toString(CryptoJS.enc.Latin1)); var key = otr.DSA.parsePrivate(decrypted.toString(CryptoJS.enc.Latin1));
if (cipher.decrypt(CryptoJS.algo.AES, pass_check, pass).toString(CryptoJS.enc.Latin1) === 'match') { if (cipher.decrypt(CryptoJS.algo.AES, pass_check, pass).toString(CryptoJS.enc.Latin1) === 'match') {
@ -285,7 +284,7 @@
this.model.on('showReceivedOTRMessage', function (text) { this.model.on('showReceivedOTRMessage', function (text) {
this.showMessage({'message': text, 'sender': 'them'}); this.showMessage({'message': text, 'sender': 'them'});
}, this); }, this);
if ((_.contains([UNVERIFIED, VERIFIED], this.model.get('otr_status'))) || converse.use_otr_by_default) { if ((_.includes([UNVERIFIED, VERIFIED], this.model.get('otr_status'))) || converse.use_otr_by_default) {
this.model.initiateOTR(); this.model.initiateOTR();
} }
}, },
@ -319,7 +318,7 @@
return this.model.initiateOTR(); return this.model.initiateOTR();
} }
} }
if (_.contains([UNVERIFIED, VERIFIED], this.model.get('otr_status'))) { if (_.includes([UNVERIFIED, VERIFIED], this.model.get('otr_status'))) {
// Off-the-record encryption is active // Off-the-record encryption is active
this.model.otr.sendMsg(text); this.model.otr.sendMsg(text);
this.model.trigger('showSentOTRMessage', text); this.model.trigger('showSentOTRMessage', text);
@ -372,7 +371,7 @@
}, },
endOTR: function (ev) { endOTR: function (ev) {
if (typeof ev !== "undefined") { if (!_.isUndefined(ev)) {
ev.preventDefault(); ev.preventDefault();
ev.stopPropagation(); ev.stopPropagation();
} }
@ -485,7 +484,7 @@
}; };
_.extend(converse.default_settings, settings); _.extend(converse.default_settings, settings);
_.extend(converse, settings); _.extend(converse, settings);
_.extend(converse, _.pick(converse.user_settings, Object.keys(settings))); _.extend(converse, _.pick(converse.user_settings, _.keys(settings)));
// Only allow OTR if we have the capability // Only allow OTR if we have the capability
converse.allow_otr = converse.allow_otr && HAS_CRYPTO; converse.allow_otr = converse.allow_otr && HAS_CRYPTO;
@ -500,7 +499,7 @@
if (converse.authentication === 'prebind') { if (converse.authentication === 'prebind') {
var key = b64_sha1(converse.connection.jid), var key = b64_sha1(converse.connection.jid),
pass = window.sessionStorage[key]; pass = window.sessionStorage[key];
if (typeof pass === 'undefined') { if (_.isUndefined(pass)) {
pass = Math.floor(Math.random()*4294967295).toString(); pass = Math.floor(Math.random()*4294967295).toString();
window.sessionStorage[key] = pass; window.sessionStorage[key] = pass;
} }
@ -516,7 +515,7 @@
if (converse.cache_otr_key) { if (converse.cache_otr_key) {
var cipher = CryptoJS.lib.PasswordBasedCipher; var cipher = CryptoJS.lib.PasswordBasedCipher;
var pass = this.getSessionPassphrase(); var pass = this.getSessionPassphrase();
if (typeof pass !== "undefined") { if (!_.isUndefined(pass)) {
// Encrypt the key and set in sessionStorage. Also store instance tag. // Encrypt the key and set in sessionStorage. Also store instance tag.
window.sessionStorage[b64_sha1(jid+'priv_key')] = window.sessionStorage[b64_sha1(jid+'priv_key')] =
cipher.encrypt(CryptoJS.algo.AES, key.packPrivate(), pass).toString(); cipher.encrypt(CryptoJS.algo.AES, key.packPrivate(), pass).toString();

View File

@ -42,12 +42,12 @@
// //
// var feature = converse.features.findWhere({'var': Strophe.NS.PING}); // var feature = converse.features.findWhere({'var': Strophe.NS.PING});
converse.lastStanzaDate = new Date(); converse.lastStanzaDate = new Date();
if (typeof jid === 'undefined' || jid === null) { if (_.isNil(jid)) {
jid = Strophe.getDomainFromJid(converse.bare_jid); jid = Strophe.getDomainFromJid(converse.bare_jid);
} }
if (typeof timeout === 'undefined' ) { timeout = null; } if (_.isUndefined(timeout) ) { timeout = null; }
if (typeof success === 'undefined' ) { success = null; } if (_.isUndefined(success) ) { success = null; }
if (typeof error === 'undefined' ) { error = null; } if (_.isUndefined(error) ) { error = null; }
if (converse.connection) { if (converse.connection) {
converse.connection.ping.ping(jid, success, error, timeout); converse.connection.ping.ping(jid, success, error, timeout);
return true; return true;

View File

@ -51,7 +51,7 @@
// Add Strophe Statuses // Add Strophe Statuses
var i = 0; var i = 0;
Object.keys(Strophe.Status).forEach(function (key) { _.each(_.keys(Strophe.Status), function (key) {
i = Math.max(i, Strophe.Status[key]); i = Math.max(i, Strophe.Status[key]);
}); });
Strophe.Status.REGIFAIL = i + 1; Strophe.Status.REGIFAIL = i + 1;
@ -211,7 +211,7 @@
}; };
_.extend(this, defaults); _.extend(this, defaults);
if (settings) { if (settings) {
_.extend(this, _.pick(settings, Object.keys(defaults))); _.extend(this, _.pick(settings, _.keys(defaults)));
} }
}, },
@ -254,7 +254,7 @@
onRegistering: function (status, error) { onRegistering: function (status, error) {
var that; var that;
converse.log('onRegistering'); converse.log('onRegistering');
if (_.contains([ if (_.includes([
Strophe.Status.DISCONNECTED, Strophe.Status.DISCONNECTED,
Strophe.Status.CONNFAIL, Strophe.Status.CONNFAIL,
Strophe.Status.REGIFAIL, Strophe.Status.REGIFAIL,
@ -320,7 +320,7 @@
}.bind(this)); }.bind(this));
} else { } else {
// Show fields // Show fields
_.each(Object.keys(this.fields), function (key) { _.each(_.keys(this.fields), function (key) {
if (key === "username") { if (key === "username") {
$input = converse.templates.form_username({ $input = converse.templates.form_username({
domain: ' @'+this.domain, domain: ' @'+this.domain,

View File

@ -110,8 +110,8 @@
a = a.get('name'); a = a.get('name');
b = b.get('name'); b = b.get('name');
var special_groups = _.keys(HEADER_WEIGHTS); var special_groups = _.keys(HEADER_WEIGHTS);
var a_is_special = _.contains(special_groups, a); var a_is_special = _.includes(special_groups, a);
var b_is_special = _.contains(special_groups, b); var b_is_special = _.includes(special_groups, b);
if (!a_is_special && !b_is_special ) { if (!a_is_special && !b_is_special ) {
return a.toLowerCase() < b.toLowerCase() ? -1 : (a.toLowerCase() > b.toLowerCase() ? 1 : 0); return a.toLowerCase() < b.toLowerCase() ? -1 : (a.toLowerCase() > b.toLowerCase() ? 1 : 0);
} else if (a_is_special && b_is_special) { } else if (a_is_special && b_is_special) {
@ -345,7 +345,7 @@
query = query.toLowerCase(); query = query.toLowerCase();
if (type === 'groups') { if (type === 'groups') {
_.each(this.getAll(), function (view, idx) { _.each(this.getAll(), function (view, idx) {
if (view.model.get('name').toLowerCase().indexOf(query.toLowerCase()) === -1) { if (!_.includes(view.model.get('name').toLowerCase(), query.toLowerCase())) {
view.hide(); view.hide();
} else if (view.model.contacts.length > 0) { } else if (view.model.contacts.length > 0) {
view.show(); view.show();
@ -407,7 +407,7 @@
if (_.has(contact.changed, 'subscription')) { if (_.has(contact.changed, 'subscription')) {
if (contact.changed.subscription === 'from') { if (contact.changed.subscription === 'from') {
this.addContactToGroup(contact, HEADER_PENDING_CONTACTS); this.addContactToGroup(contact, HEADER_PENDING_CONTACTS);
} else if (_.contains(['both', 'to'], contact.get('subscription'))) { } else if (_.includes(['both', 'to'], contact.get('subscription'))) {
this.addExistingContact(contact); this.addExistingContact(contact);
} }
} }
@ -550,6 +550,7 @@
}, },
render: function () { render: function () {
var that = this;
if (!this.mayBeShown()) { if (!this.mayBeShown()) {
this.$el.hide(); this.$el.hide();
return this; return this;
@ -568,10 +569,10 @@
_.each(classes_to_remove, _.each(classes_to_remove,
function (cls) { function (cls) {
if (this.el.className.indexOf(cls) !== -1) { if (_.includes(that.el.className, cls)) {
this.$el.removeClass(cls); that.$el.removeClass(cls);
} }
}, this); });
this.$el.addClass(chat_status).data('status', chat_status); this.$el.addClass(chat_status).data('status', chat_status);
if ((ask === 'subscribe') || (subscription === 'from')) { if ((ask === 'subscribe') || (subscription === 'from')) {
@ -861,7 +862,7 @@
}, },
onContactGroupChange: function (contact) { onContactGroupChange: function (contact) {
var in_this_group = _.contains(contact.get('groups'), this.model.get('name')); var in_this_group = _.includes(contact.get('groups'), this.model.get('name'));
var cid = contact.get('id'); var cid = contact.get('id');
var in_this_overview = !this.get(cid); var in_this_overview = !this.get(cid);
if (in_this_group && !in_this_overview) { if (in_this_group && !in_this_overview) {

View File

@ -3,6 +3,7 @@
* This file is used to tell require.js which components (or plugins) to load * This file is used to tell require.js which components (or plugins) to load
* when it generates a build. * when it generates a build.
*/ */
/*global define */
if (typeof define !== 'undefined') { if (typeof define !== 'undefined') {
/* When running tests, define is not defined. */ /* When running tests, define is not defined. */

View File

@ -1,3 +1,4 @@
/*global define */
define(['jquery'], function (jq) { define(['jquery'], function (jq) {
return jq.noConflict( true ); return jq.noConflict( true );
}); });

View File

@ -1,25 +0,0 @@
/*global $ */
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define("converse", ["jquery"], function($) {
return factory($);
});
} else {
factory($);
}
}(this, function ($) {
$.eventEmitter = {
emit: function(evt, data) {
$(this).trigger(evt, data);
},
once: function(evt, handler) {
$(this).one(evt, handler);
},
on: function(evt, handler) {
$(this).bind(evt, handler);
},
off: function(evt, handler) {
$(this).unbind(evt, handler);
}
};
}));

View File

@ -6,6 +6,7 @@
* *
* See also src/moment_locales.js * See also src/moment_locales.js
*/ */
/*global define */
(function (root, factory) { (function (root, factory) {
define("locales", ['jed', define("locales", ['jed',
'text!af', 'text!af',

View File

@ -1,4 +1,4 @@
/*global escape, locales, Jed */ /*global define, escape, locales, Jed */
(function (root, factory) { (function (root, factory) {
define([ define([
"jquery", "jquery",
@ -244,8 +244,8 @@
// check if an @ signal is included, and if not, we assume it's // check if an @ signal is included, and if not, we assume it's
// a headline message. // a headline message.
( $message.attr('type') !== 'error' && ( $message.attr('type') !== 'error' &&
typeof from_jid !== 'undefined' && !_.isUndefined(from_jid) &&
from_jid.indexOf('@') === -1 !_.includes(from_jid, '@')
)) { )) {
return true; return true;
} }
@ -326,11 +326,11 @@
if (typeof attr === 'object') { if (typeof attr === 'object') {
var value = false; var value = false;
_.forEach(attr, function (a) { _.forEach(attr, function (a) {
value = value || item.get(a).toLowerCase().indexOf(query.toLowerCase()) !== -1; value = value || _.includes(item.get(a).toLowerCase(), query.toLowerCase());
}); });
return value; return value;
} else if (typeof attr === 'string') { } else if (typeof attr === 'string') {
return item.get(attr).toLowerCase().indexOf(query.toLowerCase()) !== -1; return _.includes(item.get(attr).toLowerCase(), query.toLowerCase());
} else { } else {
throw new TypeError('contains: wrong attribute type. Must be string or array.'); throw new TypeError('contains: wrong attribute type. Must be string or array.');
} }
@ -360,7 +360,7 @@
options.push(tpl_select_option({ options.push(tpl_select_option({
value: value, value: value,
label: $($options[j]).attr('label'), label: $($options[j]).attr('label'),
selected: (values.indexOf(value) >= 0), selected: _.startsWith(values, value),
required: $field.find('required').length required: $field.find('required').length
})); }));
} }