Преглед изворни кода

utils now no longer depends on jquery.

JC Brand пре 8 година
родитељ
комит
add3b8efb3
6 измењених фајлова са 221 додато и 177 уклоњено
  1. 11 0
      spec/controlbox.js
  2. 7 6
      src/converse-muc.js
  3. 1 1
      src/converse-register.js
  4. 2 1
      src/templates/field.html
  5. 193 162
      src/utils.js
  6. 7 7
      tests/mock.js

+ 11 - 0
spec/controlbox.js

@@ -137,6 +137,17 @@
                         });
                         });
                         _converse.rosterview.update(); // XXX: Will normally called as event handler
                         _converse.rosterview.update(); // XXX: Will normally called as event handler
                     }
                     }
+
+                    $.fn.hasScrollBar = function() {
+                        if (!$.contains(document, this.get(0))) {
+                            return false;
+                        }
+                        if(this.parent().height() < this.get(0).scrollHeight) {
+                            return true;
+                        }
+                        return false;
+                    };
+
                     return test_utils.waitUntil(function () {
                     return test_utils.waitUntil(function () {
                         if (_converse.rosterview.$roster.hasScrollBar()) {
                         if (_converse.rosterview.$roster.hasScrollBar()) {
                             return $filter.is(':visible');
                             return $filter.is(':visible');

+ 7 - 6
src/converse-muc.js

@@ -191,11 +191,12 @@
                         _converse.api.listen.on('serviceDiscovered', this.featureAdded, this);
                         _converse.api.listen.on('serviceDiscovered', this.featureAdded, this);
                         // Features could have been added before the controlbox was
                         // Features could have been added before the controlbox was
                         // initialized. We're only interested in MUC
                         // initialized. We're only interested in MUC
-                        const feature = _converse.disco_entities[_converse.domain].features.findWhere({
-                            'var': Strophe.NS.MUC
-                        });
-                        if (feature) {
-                            this.featureAdded(feature);
+                        const entity = _converse.disco_entities[_converse.domain];
+                        if (!_.isUndefined(entity)) {
+                            const feature = entity.features.findWhere({'var': Strophe.NS.MUC });
+                            if (feature) {
+                                this.featureAdded(feature);
+                            }
                         }
                         }
                     });
                     });
                 },
                 },
@@ -1283,7 +1284,7 @@
                         $fieldset.append($('<p class="instructions">').text(instructions));
                         $fieldset.append($('<p class="instructions">').text(instructions));
                     }
                     }
                     _.each($fields, function (field) {
                     _.each($fields, function (field) {
-                        $fieldset.append(utils.xForm2webForm($(field), $stanza));
+                        $fieldset.append(utils.xForm2webForm(field, stanza));
                     });
                     });
                     $form.append('<fieldset></fieldset>');
                     $form.append('<fieldset></fieldset>');
                     $fieldset = $form.children('fieldset:last');
                     $fieldset = $form.children('fieldset:last');

+ 1 - 1
src/converse-register.js

@@ -356,7 +356,7 @@
                     if (this.form_type === 'xform') {
                     if (this.form_type === 'xform') {
                         $fields = $stanza.find('field');
                         $fields = $stanza.find('field');
                         _.each($fields, (field) => {
                         _.each($fields, (field) => {
-                            $form.append(utils.xForm2webForm.bind(this, $(field), $stanza));
+                            $form.append(utils.xForm2webForm.bind(this, field, stanza));
                         });
                         });
                     } else {
                     } else {
                         // Show fields
                         // Show fields

+ 2 - 1
src/templates/field.html

@@ -1,4 +1,5 @@
-<field var="{{{name}}}">{[ if (_.isArray(value)) { ]}
+<field var="{{{name}}}">
+{[ if (_.isArray(value)) { ]}
     {[ _.each(value,function(arrayValue) { ]}<value>{{{arrayValue}}}</value>{[ }); ]}
     {[ _.each(value,function(arrayValue) { ]}<value>{{{arrayValue}}}</value>{[ }); ]}
 {[ } else { ]}
 {[ } else { ]}
     <value>{{{value}}}</value>
     <value>{{{value}}}</value>

+ 193 - 162
src/utils.js

@@ -1,7 +1,14 @@
+// Converse.js (A browser based XMPP chat client)
+// http://conversejs.org
+//
+// This is the utilities module.
+//
+// Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
+// Licensed under the Mozilla Public License (MPLv2)
+//
 /*global define, escape, locales, Jed */
 /*global define, escape, locales, Jed */
 (function (root, factory) {
 (function (root, factory) {
     define([
     define([
-        "jquery.noconflict",
         "sizzle",
         "sizzle",
         "es6-promise",
         "es6-promise",
         "jquery.browser",
         "jquery.browser",
@@ -19,7 +26,6 @@
         "tpl!form_captcha"
         "tpl!form_captcha"
     ], factory);
     ], factory);
 }(this, function (
 }(this, function (
-        $,
         sizzle,
         sizzle,
         Promise,
         Promise,
         jQBrowser,
         jQBrowser,
@@ -36,7 +42,6 @@
         tpl_form_input,
         tpl_form_input,
         tpl_form_captcha
         tpl_form_captcha
     ) {
     ) {
-
     "use strict";
     "use strict";
     locales = locales || {};
     locales = locales || {};
     const b64_sha1 = Strophe.SHA1.b64_sha1;
     const b64_sha1 = Strophe.SHA1.b64_sha1;
@@ -93,16 +98,6 @@
         });
         });
     };
     };
 
 
-    $.fn.hasScrollBar = function() {
-        if (!$.contains(document, this.get(0))) {
-            return false;
-        }
-        if(this.parent().height() < this.get(0).scrollHeight) {
-            return true;
-        }
-        return false;
-    };
-
     function calculateSlideStep (height) {
     function calculateSlideStep (height) {
         if (height > 100) {
         if (height > 100) {
             return 10;
             return 10;
@@ -113,12 +108,12 @@
         }
         }
     }
     }
 
 
-    var utils = {};
+    var u = {};
 
 
     // Translation machinery
     // Translation machinery
     // ---------------------
     // ---------------------
-    utils.__ = function (str) {
-        if (!utils.isConverseLocale(this.locale) || this.locale === 'en') {
+    u.__ = function (str) {
+        if (!u.isConverseLocale(this.locale) || this.locale === 'en') {
             return Jed.sprintf.apply(Jed, arguments);
             return Jed.sprintf.apply(Jed, arguments);
         }
         }
         if (typeof this.jed === "undefined") {
         if (typeof this.jed === "undefined") {
@@ -132,7 +127,7 @@
         }
         }
     };
     };
 
 
-    utils.___ = function (str) {
+    u.___ = function (str) {
         /* XXX: This is part of a hack to get gettext to scan strings to be
         /* XXX: This is part of a hack to get gettext to scan strings to be
          * translated. Strings we cannot send to the function above because
          * translated. Strings we cannot send to the function above because
          * they require variable interpolation and we don't yet have the
          * they require variable interpolation and we don't yet have the
@@ -143,7 +138,7 @@
         return str;
         return str;
     };
     };
 
 
-    utils.isLocaleAvailable = function (locale, available) {
+    u.isLocaleAvailable = function (locale, available) {
         /* Check whether the locale or sub locale (e.g. en-US, en) is supported.
         /* Check whether the locale or sub locale (e.g. en-US, en) is supported.
          *
          *
          * Parameters:
          * Parameters:
@@ -159,7 +154,7 @@
         }
         }
     };
     };
 
 
-    utils.addHyperlinks = function (text) {
+    u.addHyperlinks = function (text) {
         const list = text.match(URL_REGEX) || [];
         const list = text.match(URL_REGEX) || [];
         var links = [];
         var links = [];
         _.each(list, (match) => {
         _.each(list, (match) => {
@@ -179,7 +174,7 @@
         return text;
         return text;
     };
     };
 
 
-    utils.renderImageURLs = function (obj) {
+    u.renderImageURLs = function (obj) {
         const list = obj.textContent.match(URL_REGEX) || [];
         const list = obj.textContent.match(URL_REGEX) || [];
         _.forEach(list, function (url) {
         _.forEach(list, function (url) {
             isImage(url).then(function (img) {
             isImage(url).then(function (img) {
@@ -191,23 +186,23 @@
         return obj;
         return obj;
     };
     };
 
 
-    utils.slideInAllElements = function (elements) {
+    u.slideInAllElements = function (elements) {
         return Promise.all(
         return Promise.all(
             _.map(
             _.map(
                 elements,
                 elements,
-                _.partial(utils.slideIn, _, 600)
+                _.partial(u.slideIn, _, 600)
             ));
             ));
     };
     };
 
 
-    utils.slideToggleElement = function (el) {
+    u.slideToggleElement = function (el) {
         if (_.includes(el.classList, 'collapsed')) {
         if (_.includes(el.classList, 'collapsed')) {
-            return utils.slideOut(el);
+            return u.slideOut(el);
         } else {
         } else {
-            return utils.slideIn(el);
+            return u.slideIn(el);
         }
         }
     };
     };
 
 
-    utils.slideOut = function (el, duration=900) {
+    u.slideOut = function (el, duration=900) {
         /* Shows/expands an element by sliding it out of itself. */
         /* Shows/expands an element by sliding it out of itself. */
 
 
         function calculateEndHeight (el) {
         function calculateEndHeight (el) {
@@ -237,7 +232,7 @@
                 window.clearInterval(interval_marker);
                 window.clearInterval(interval_marker);
             }
             }
             const end_height = calculateEndHeight(el);
             const end_height = calculateEndHeight(el);
-            if ($.fx.off) { // Effects are disabled (for tests)
+            if (window.converse_disable_effects) { // Effects are disabled (for tests)
                 el.style.height = end_height + 'px';
                 el.style.height = end_height + 'px';
                 wrapup(el);
                 wrapup(el);
                 resolve();
                 resolve();
@@ -266,7 +261,7 @@
         });
         });
     };
     };
 
 
-    utils.slideIn = function (el, duration=600) {
+    u.slideIn = function (el, duration=600) {
         /* Hides/collapses an element by sliding it into itself. */
         /* Hides/collapses an element by sliding it into itself. */
         return new Promise((resolve, reject) => {
         return new Promise((resolve, reject) => {
             if (_.isNil(el)) {
             if (_.isNil(el)) {
@@ -275,7 +270,7 @@
                 return reject(new Error(err));
                 return reject(new Error(err));
             } else if (_.includes(el.classList, 'collapsed')) {
             } else if (_.includes(el.classList, 'collapsed')) {
                 return resolve();
                 return resolve();
-            } else if ($.fx.off) { // Effects are disabled (for tests)
+            } else if (window.converse_disable_effects) { // Effects are disabled (for tests)
                 el.classList.add('collapsed');
                 el.classList.add('collapsed');
                 el.style.height = "";
                 el.style.height = "";
                 return resolve();
                 return resolve();
@@ -307,11 +302,11 @@
         });
         });
     };
     };
 
 
-    utils.fadeIn = function (el, callback) {
+    u.fadeIn = function (el, callback) {
         if (_.isNil(el)) {
         if (_.isNil(el)) {
             console.warn("Undefined or null element passed into fadeIn");
             console.warn("Undefined or null element passed into fadeIn");
         }
         }
-        if ($.fx.off) {
+        if (window.converse_disable_effects) { // Effects are disabled (for tests)
             el.classList.remove('hidden');
             el.classList.remove('hidden');
             if (_.isFunction(callback)) {
             if (_.isFunction(callback)) {
                 callback();
                 callback();
@@ -331,12 +326,12 @@
         }
         }
     };
     };
 
 
-    utils.isSameBareJID = function (jid1, jid2) {
+    u.isSameBareJID = function (jid1, jid2) {
         return Strophe.getBareJidFromJid(jid1).toLowerCase() ===
         return Strophe.getBareJidFromJid(jid1).toLowerCase() ===
                 Strophe.getBareJidFromJid(jid2).toLowerCase();
                 Strophe.getBareJidFromJid(jid2).toLowerCase();
     };
     };
 
 
-    utils.isNewMessage = function (message) {
+    u.isNewMessage = function (message) {
         /* Given a stanza, determine whether it's a new
         /* Given a stanza, determine whether it's a new
          * message, i.e. not a MAM archived one.
          * message, i.e. not a MAM archived one.
          */
          */
@@ -347,13 +342,13 @@
         }
         }
     };
     };
 
 
-    utils.isOTRMessage = function (message) {
+    u.isOTRMessage = function (message) {
         var body = message.querySelector('body'),
         var body = message.querySelector('body'),
             text = (!_.isNull(body) ? body.textContent: undefined);
             text = (!_.isNull(body) ? body.textContent: undefined);
         return text && !!text.match(/^\?OTR/);
         return text && !!text.match(/^\?OTR/);
     };
     };
 
 
-    utils.isHeadlineMessage = function (message) {
+    u.isHeadlineMessage = function (message) {
         var from_jid = message.getAttribute('from');
         var from_jid = message.getAttribute('from');
         if (message.getAttribute('type') === 'headline') {
         if (message.getAttribute('type') === 'headline') {
             return true;
             return true;
@@ -370,7 +365,7 @@
         return false;
         return false;
     };
     };
 
 
-    utils.merge = function merge (first, second) {
+    u.merge = function merge (first, second) {
         /* Merge the second object into the first one.
         /* Merge the second object into the first one.
          */
          */
         for (var k in second) {
         for (var k in second) {
@@ -382,7 +377,7 @@
         }
         }
     };
     };
 
 
-    utils.applyUserSettings = function applyUserSettings (context, settings, user_settings) {
+    u.applyUserSettings = function applyUserSettings (context, settings, user_settings) {
         /* Configuration settings might be nested objects. We only want to
         /* Configuration settings might be nested objects. We only want to
          * add settings which are whitelisted.
          * add settings which are whitelisted.
          */
          */
@@ -398,7 +393,7 @@
         }
         }
     };
     };
 
 
-    utils.refreshWebkit = function () {
+    u.refreshWebkit = function () {
         /* This works around a webkit bug. Refreshes the browser's viewport,
         /* This works around a webkit bug. Refreshes the browser's viewport,
          * otherwise chatboxes are not moved along when one is closed.
          * otherwise chatboxes are not moved along when one is closed.
          */
          */
@@ -412,34 +407,69 @@
         }
         }
     };
     };
 
 
-    utils.webForm2xForm = function (field) {
+    u.stringToDOM = function (s) {
+        /* Converts an HTML string into a DOM element.
+         *
+         * Parameters:
+         *      (String) s - The HTML string
+         */
+        var div = document.createElement('div');
+        div.innerHTML = s;
+        return div.childNodes;
+    };
+
+    u.matchesSelector = function (el, selector) {
+        /* Checks whether the DOM element matches the given selector.
+         *
+         * Parameters:
+         *      (DOMElement) el - The DOM element
+         *      (String) selector - The selector
+         */
+        return (
+            el.matches ||
+            el.matchesSelector ||
+            el.msMatchesSelector ||
+            el.mozMatchesSelector ||
+            el.webkitMatchesSelector ||
+            el.oMatchesSelector
+        ).call(el, selector);
+    };
+
+    u.queryChildren = function (el, selector) {
+        /* Returns a list of children of the DOM element that match the
+         * selector.
+         *
+         *  Parameters:
+         *      (DOMElement) el - the DOM element
+         *      (String) selector - the selector they should be matched
+         *          against.
+         */
+        return _.filter(el.children, _.partial(u.matchesSelector, _, selector));
+    };
+
+    u.webForm2xForm = function (field) {
         /* Takes an HTML DOM and turns it into an XForm field.
         /* Takes an HTML DOM and turns it into an XForm field.
-        *
-        * Parameters:
-        *      (DOMElement) field - the field to convert
-        */
-        var $input = $(field), value;
-        if ($input.is('[type=checkbox]')) {
-            value = $input.is(':checked') && 1 || 0;
-        } else if ($input.is('textarea')) {
-            value = [];
-            var lines = $input.val().split('\n');
-            for( var vk=0; vk<lines.length; vk++) {
-                var val = $.trim(lines[vk]);
-                if (val === '')
-                    continue;
-                value.push(val);
-            }
+         *
+         * Parameters:
+         *      (DOMElement) field - the field to convert
+         */
+        let value;
+        if (field.getAttribute('type') === 'checkbox') {
+            value = field.checked && 1 || 0;
+        } else if (field.tagName == "textarea") {
+            value = _.filter(field.value.split('\n'), _.trim);
         } else {
         } else {
-            value = $input.val();
+            value = field.value;
         }
         }
-        return $(tpl_field({
-            name: $input.attr('name'),
-            value: value
-        }))[0];
+        return u.stringToDOM(
+            tpl_field({
+                name: field.getAttribute('name'),
+                value: value
+            })
+        )[0];
     };
     };
 
 
-    utils.contains = function (attr, query) {
+    u.contains = function (attr, query) {
         return function (item) {
         return function (item) {
             if (typeof attr === 'object') {
             if (typeof attr === 'object') {
                 var value = false;
                 var value = false;
@@ -455,94 +485,95 @@
         };
         };
     };
     };
 
 
-    utils.xForm2webForm = function ($field, $stanza) {
+    u.xForm2webForm = function (field, stanza) {
         /* Takes a field in XMPP XForm (XEP-004: Data Forms) format
         /* Takes a field in XMPP XForm (XEP-004: Data Forms) format
-        * and turns it into a HTML DOM field.
-        *
-        *  Parameters:
-        *      (XMLElement) field - the field to convert
-        */
-
-        // FIXME: take <required> into consideration
-        var options = [], j, $options, $values, value, values;
-
-        if ($field.attr('type') === 'list-single' || $field.attr('type') === 'list-multi') {
-            values = [];
-            $values = $field.children('value');
-            for (j=0; j<$values.length; j++) {
-                values.push($($values[j]).text());
-            }
-            $options = $field.children('option');
-            for (j=0; j<$options.length; j++) {
-                value = $($options[j]).find('value').text();
-                options.push(tpl_select_option({
-                    value: value,
-                    label: $($options[j]).attr('label'),
-                    selected: _.startsWith(values, value),
-                    required: $field.find('required').length
-                }));
-            }
+         * and turns it into an HTML field.
+         *
+         * Returns either text or a DOM element (which is not ideal, but fine
+         * for now).
+         *
+         *  Parameters:
+         *      (XMLElement) field - the field to convert
+         */
+        if (field.getAttribute('type') === 'list-single' ||
+            field.getAttribute('type') === 'list-multi') {
+
+            const values = _.map(
+                u.queryChildren(field, 'value'),
+                _.partial(_.get, _, 'textContent')
+            );
+            const options = _.map(
+                u.queryChildren(field, 'option'),
+                function (option) {
+                    const value = _.get(option.querySelector('value'), 'textContent');
+                    return tpl_select_option({
+                        'value': value,
+                        'label': option.getAttribute('label'),
+                        'selected': _.startsWith(values, value),
+                        'required': _.isNil(field.querySelector('required'))
+                    })
+                }
+            );
             return tpl_form_select({
             return tpl_form_select({
-                name: $field.attr('var'),
-                label: $field.attr('label'),
-                options: options.join(''),
-                multiple: ($field.attr('type') === 'list-multi'),
-                required: $field.find('required').length
-            });
-        } else if ($field.attr('type') === 'fixed') {
-            return $('<p class="form-help">').text($field.find('value').text());
-        } else if ($field.attr('type') === 'jid-multi') {
+                'name': field.getAttribute('var'),
+                'label': field.getAttribute('label'),
+                'options': options.join(''),
+                'multiple': (field.getAttribute('type') === 'list-multi'),
+                'required': _.isNil(field.querySelector('required'))
+            })
+        } else if (field.getAttribute('type') === 'fixed') {
+            const text = _.get(field.querySelector('value'), 'textContent');
+            const el = u.stringToDOM('<p class="form-help">');
+            el.textContent = text;
+            return el;
+        } else if (field.getAttribute('type') === 'jid-multi') {
             return tpl_form_textarea({
             return tpl_form_textarea({
-                name: $field.attr('var'),
-                label: $field.attr('label') || '',
-                value: $field.find('value').text(),
-                required: $field.find('required').length
-            });
-        } else if ($field.attr('type') === 'boolean') {
+                'name': field.getAttribute('var'),
+                'label': field.getAttribute('label') || '',
+                'value': _.get(field.querySelector('value'), 'textContent'),
+                'required': _.isNil(field.querySelector('required'))
+            })
+        } else if (field.getAttribute('type') === 'boolean') {
             return tpl_form_checkbox({
             return tpl_form_checkbox({
-                name: $field.attr('var'),
-                type: XFORM_TYPE_MAP[$field.attr('type')],
-                label: $field.attr('label') || '',
-                checked: $field.find('value').text() === "1" && 'checked="1"' || '',
-                required: $field.find('required').length
-            });
-        } else if ($field.attr('type') && $field.attr('var') === 'username') {
+                'name': field.getAttribute('var'),
+                'type': XFORM_TYPE_MAP[field.getAttribute('type')],
+                'label': field.getAttribute('label') || '',
+                'checked': _.get(field.querySelector('value'), 'textContent') === "1" && 'checked="1"' || '',
+                'required': _.isNil(field.querySelector('required'))
+            })
+        } else if (field.getAttribute('type') && field.getAttribute('var') === 'username') {
             return tpl_form_username({
             return tpl_form_username({
-                domain: ' @'+this.domain,
-                name: $field.attr('var'),
-                type: XFORM_TYPE_MAP[$field.attr('type')],
-                label: $field.attr('label') || '',
-                value: $field.find('value').text(),
-                required: $field.find('required').length
-            });
-        } else if ($field.attr('type')) {
+                'domain': ' @'+this.domain,
+                'name': field.getAttribute('var'),
+                'type': XFORM_TYPE_MAP[field.getAttribute('type')],
+                'label': field.getAttribute('label') || '',
+                'value': _.get(field.querySelector('value'), 'textContent'),
+                'required': _.isNil(field.querySelector('required'))
+            })
+        } else if (field.getAttribute('type')) {
             return tpl_form_input({
             return tpl_form_input({
-                name: $field.attr('var'),
-                type: XFORM_TYPE_MAP[$field.attr('type')],
-                label: $field.attr('label') || '',
-                value: $field.find('value').text(),
-                required: $field.find('required').length
-            });
+                'name': field.getAttribute('var'),
+                'type': XFORM_TYPE_MAP[field.getAttribute('type')],
+                'label': field.getAttribute('label') || '',
+                'value': _.get(field.querySelector('value'), 'textContent'),
+                'required': _.isNil(field.querySelector('required'))
+            })
         } else {
         } else {
-            if ($field.attr('var') === 'ocr') { // Captcha
-                return _.reduce(_.map($field.find('uri'),
-                        $.proxy(function (uri) {
-                            return tpl_form_captcha({
-                                label: this.$field.attr('label'),
-                                name: this.$field.attr('var'),
-                                data: this.$stanza.find('data[cid="'+uri.textContent.replace(/^cid:/, '')+'"]').text(),
-                                type: uri.getAttribute('type'),
-                                required: this.$field.find('required').length
-                            });
-                        }, {'$stanza': $stanza, '$field': $field})
-                    ),
-                    function (memo, num) { return memo + num; }, ''
-                );
+            if (field.getAttribute('var') === 'ocr') { // Captcha
+                const uri = field.querySelector('uri');
+                const el = sizzle('data[cid="'+uri.textContent.replace(/^cid:/, '')+'"]', stanza)[0];
+                return tpl_form_captcha({
+                    'label': field.getAttribute('label'),
+                    'name': field.getAttribute('var'),
+                    'data': _.get(el, 'textContent'),
+                    'type': uri.getAttribute('type'),
+                    'required': _.isNil(field.querySelector('required'))
+                })
             }
             }
         }
         }
     }
     }
 
 
-    utils.detectLocale = function (library_check) {
+    u.detectLocale = function (library_check) {
         /* Determine which locale is supported by the user's system as well
         /* Determine which locale is supported by the user's system as well
          * as by the relevant library (e.g. converse.js or moment.js).
          * as by the relevant library (e.g. converse.js or moment.js).
          *
          *
@@ -552,36 +583,36 @@
          */
          */
         var locale, i;
         var locale, i;
         if (window.navigator.userLanguage) {
         if (window.navigator.userLanguage) {
-            locale = utils.isLocaleAvailable(window.navigator.userLanguage, library_check);
+            locale = u.isLocaleAvailable(window.navigator.userLanguage, library_check);
         }
         }
         if (window.navigator.languages && !locale) {
         if (window.navigator.languages && !locale) {
             for (i=0; i<window.navigator.languages.length && !locale; i++) {
             for (i=0; i<window.navigator.languages.length && !locale; i++) {
-                locale = utils.isLocaleAvailable(window.navigator.languages[i], library_check);
+                locale = u.isLocaleAvailable(window.navigator.languages[i], library_check);
             }
             }
         }
         }
         if (window.navigator.browserLanguage && !locale) {
         if (window.navigator.browserLanguage && !locale) {
-            locale = utils.isLocaleAvailable(window.navigator.browserLanguage, library_check);
+            locale = u.isLocaleAvailable(window.navigator.browserLanguage, library_check);
         }
         }
         if (window.navigator.language && !locale) {
         if (window.navigator.language && !locale) {
-            locale = utils.isLocaleAvailable(window.navigator.language, library_check);
+            locale = u.isLocaleAvailable(window.navigator.language, library_check);
         }
         }
         if (window.navigator.systemLanguage && !locale) {
         if (window.navigator.systemLanguage && !locale) {
-            locale = utils.isLocaleAvailable(window.navigator.systemLanguage, library_check);
+            locale = u.isLocaleAvailable(window.navigator.systemLanguage, library_check);
         }
         }
         return locale || 'en';
         return locale || 'en';
     };
     };
 
 
-    utils.isConverseLocale = function (locale) {
+    u.isConverseLocale = function (locale) {
         if (!_.isString(locale)) { return false; }
         if (!_.isString(locale)) { return false; }
         return _.includes(_.keys(locales || {}), locale);
         return _.includes(_.keys(locales || {}), locale);
     };
     };
 
 
-    utils.isMomentLocale  = function (locale) {
+    u.isMomentLocale  = function (locale) {
         if (!_.isString(locale)) { return false; }
         if (!_.isString(locale)) { return false; }
         return moment.locale() !== moment.locale(locale);
         return moment.locale() !== moment.locale(locale);
     };
     };
 
 
-    utils.getLocale = function (preferred_locale, isSupportedByLibrary) {
+    u.getLocale = function (preferred_locale, isSupportedByLibrary) {
         if (_.isString(preferred_locale)) {
         if (_.isString(preferred_locale)) {
             if (preferred_locale === 'en' || isSupportedByLibrary(preferred_locale)) {
             if (preferred_locale === 'en' || isSupportedByLibrary(preferred_locale)) {
                 return preferred_locale;
                 return preferred_locale;
@@ -593,28 +624,28 @@
                 console.log(e);
                 console.log(e);
             }
             }
         }
         }
-        return utils.detectLocale(isSupportedByLibrary) || 'en';
+        return u.detectLocale(isSupportedByLibrary) || 'en';
     };
     };
 
 
-    utils.isOfType = function (type, item) {
+    u.isOfType = function (type, item) {
         return item.get('type') == type;
         return item.get('type') == type;
     };
     };
 
 
-    utils.isInstance = function (type, item) {
+    u.isInstance = function (type, item) {
         return item instanceof type;
         return item instanceof type;
     };
     };
 
 
-    utils.getAttribute = function (key, item) {
+    u.getAttribute = function (key, item) {
         return item.get(key);
         return item.get(key);
     };
     };
 
 
-    utils.contains.not = function (attr, query) {
+    u.contains.not = function (attr, query) {
         return function (item) {
         return function (item) {
-            return !(utils.contains(attr, query)(item));
+            return !(u.contains(attr, query)(item));
         };
         };
     };
     };
 
 
-    utils.createFragmentFromText = function (markup) {
+    u.createFragmentFromText = function (markup) {
         /* Returns a DocumentFragment containing DOM nodes based on the
         /* Returns a DocumentFragment containing DOM nodes based on the
          * passed-in markup text.
          * passed-in markup text.
          */
          */
@@ -630,7 +661,7 @@
         return frag
         return frag
     };
     };
 
 
-    utils.addEmoji = function (_converse, emojione, text) {
+    u.addEmoji = function (_converse, emojione, text) {
         if (_converse.use_emojione) {
         if (_converse.use_emojione) {
             return emojione.toImage(text);
             return emojione.toImage(text);
         } else {
         } else {
@@ -638,7 +669,7 @@
         }
         }
     }
     }
 
 
-    utils.getEmojisByCategory = function (_converse, emojione) {
+    u.getEmojisByCategory = function (_converse, emojione) {
         /* Return a dict of emojis with the categories as keys and
         /* Return a dict of emojis with the categories as keys and
          * lists of emojis in that category as values.
          * lists of emojis in that category as values.
          */
          */
@@ -684,11 +715,11 @@
         return _converse.emojis_by_category;
         return _converse.emojis_by_category;
     };
     };
 
 
-    utils.getTonedEmojis = function (_converse) {
+    u.getTonedEmojis = function (_converse) {
         _converse.toned_emojis = _.uniq(
         _converse.toned_emojis = _.uniq(
             _.map(
             _.map(
                 _.filter(
                 _.filter(
-                    utils.getEmojisByCategory(_converse).people,
+                    u.getEmojisByCategory(_converse).people,
                     (person) => _.includes(person._shortname, '_tone')
                     (person) => _.includes(person._shortname, '_tone')
                 ),
                 ),
                 (person) => person._shortname.replace(/_tone[1-5]/, '')
                 (person) => person._shortname.replace(/_tone[1-5]/, '')
@@ -696,11 +727,11 @@
         return _converse.toned_emojis;
         return _converse.toned_emojis;
     };
     };
 
 
-    utils.isPersistableModel = function (model) {
+    u.isPersistableModel = function (model) {
         return model.collection && model.collection.browserStorage;
         return model.collection && model.collection.browserStorage;
     };
     };
 
 
-    utils.getWrappedPromise = function () {
+    u.getWrappedPromise = function () {
         const wrapper = {};
         const wrapper = {};
         wrapper.promise = new Promise((resolve, reject) => {
         wrapper.promise = new Promise((resolve, reject) => {
             wrapper.resolve = resolve;
             wrapper.resolve = resolve;
@@ -709,12 +740,12 @@
         return wrapper;
         return wrapper;
     };
     };
 
 
-    utils.safeSave = function (model, attributes) {
-        if (utils.isPersistableModel(model)) {
+    u.safeSave = function (model, attributes) {
+        if (u.isPersistableModel(model)) {
             model.save(attributes);
             model.save(attributes);
         } else {
         } else {
             model.set(attributes);
             model.set(attributes);
         }
         }
     }
     }
-    return utils;
+    return u;
 }));
 }));

+ 7 - 7
tests/mock.js

@@ -1,10 +1,10 @@
 (function (root, factory) {
 (function (root, factory) {
     define("mock", ['jquery.noconflict', 'converse'], factory);
     define("mock", ['jquery.noconflict', 'converse'], factory);
-}(this, function ($, converse_api) {
-    var _ = converse_api.env._;
-    var Promise = converse_api.env.Promise;
-    var Strophe = converse_api.env.Strophe;
-    var $iq = converse_api.env.$iq;
+}(this, function ($, converse) {
+    var _ = converse.env._;
+    var Promise = converse.env.Promise;
+    var Strophe = converse.env.Strophe;
+    var $iq = converse.env.$iq;
     var mock = {};
     var mock = {};
     // Names from http://www.fakenamegenerator.com/
     // Names from http://www.fakenamegenerator.com/
     mock.req_names = [
     mock.req_names = [
@@ -99,7 +99,7 @@
             });
             });
         }
         }
 
 
-        var _converse = converse_api.initialize(_.extend({
+        var _converse = converse.initialize(_.extend({
             'i18n': 'en',
             'i18n': 'en',
             'auto_subscribe': false,
             'auto_subscribe': false,
             'play_sounds': false,
             'play_sounds': false,
@@ -113,7 +113,7 @@
             'debug': false
             'debug': false
         }, settings || {}));
         }, settings || {}));
         _converse.ChatBoxViews.prototype.trimChat = function () {};
         _converse.ChatBoxViews.prototype.trimChat = function () {};
-        _converse.disable_effects = true;
+        window.converse_disable_effects = true;
         $.fx.off = true;
         $.fx.off = true;
         return _converse;
         return _converse;
     }
     }