From add3b8efb3833e597276011a8325ff60f50aa912 Mon Sep 17 00:00:00 2001 From: JC Brand Date: Tue, 15 Aug 2017 21:23:30 +0200 Subject: [PATCH] utils now no longer depends on jquery. --- spec/controlbox.js | 11 ++ src/converse-muc.js | 13 +- src/converse-register.js | 2 +- src/templates/field.html | 3 +- src/utils.js | 359 +++++++++++++++++++++------------------ tests/mock.js | 14 +- 6 files changed, 223 insertions(+), 179 deletions(-) diff --git a/spec/controlbox.js b/spec/controlbox.js index 46aa10082..97ebb94e4 100644 --- a/spec/controlbox.js +++ b/spec/controlbox.js @@ -137,6 +137,17 @@ }); _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 () { if (_converse.rosterview.$roster.hasScrollBar()) { return $filter.is(':visible'); diff --git a/src/converse-muc.js b/src/converse-muc.js index aa3000400..89ea187fe 100755 --- a/src/converse-muc.js +++ b/src/converse-muc.js @@ -191,11 +191,12 @@ _converse.api.listen.on('serviceDiscovered', this.featureAdded, this); // Features could have been added before the controlbox was // 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($('

').text(instructions)); } _.each($fields, function (field) { - $fieldset.append(utils.xForm2webForm($(field), $stanza)); + $fieldset.append(utils.xForm2webForm(field, stanza)); }); $form.append('

'); $fieldset = $form.children('fieldset:last'); diff --git a/src/converse-register.js b/src/converse-register.js index 8e4d23535..5fb70e087 100644 --- a/src/converse-register.js +++ b/src/converse-register.js @@ -356,7 +356,7 @@ if (this.form_type === 'xform') { $fields = $stanza.find('field'); _.each($fields, (field) => { - $form.append(utils.xForm2webForm.bind(this, $(field), $stanza)); + $form.append(utils.xForm2webForm.bind(this, field, stanza)); }); } else { // Show fields diff --git a/src/templates/field.html b/src/templates/field.html index 1d501f51c..c6a679637 100644 --- a/src/templates/field.html +++ b/src/templates/field.html @@ -1,4 +1,5 @@ -{[ if (_.isArray(value)) { ]} + +{[ if (_.isArray(value)) { ]} {[ _.each(value,function(arrayValue) { ]}{{{arrayValue}}}{[ }); ]} {[ } else { ]} {{{value}}} diff --git a/src/utils.js b/src/utils.js index 61b349428..372698191 100755 --- a/src/utils.js +++ b/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 +// Licensed under the Mozilla Public License (MPLv2) +// /*global define, escape, locales, Jed */ (function (root, factory) { define([ - "jquery.noconflict", "sizzle", "es6-promise", "jquery.browser", @@ -19,7 +26,6 @@ "tpl!form_captcha" ], factory); }(this, function ( - $, sizzle, Promise, jQBrowser, @@ -36,7 +42,6 @@ tpl_form_input, tpl_form_captcha ) { - "use strict"; locales = locales || {}; 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) { if (height > 100) { return 10; @@ -113,12 +108,12 @@ } } - var utils = {}; + var u = {}; // 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); } 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 * translated. Strings we cannot send to the function above because * they require variable interpolation and we don't yet have the @@ -143,7 +138,7 @@ 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. * * Parameters: @@ -159,7 +154,7 @@ } }; - utils.addHyperlinks = function (text) { + u.addHyperlinks = function (text) { const list = text.match(URL_REGEX) || []; var links = []; _.each(list, (match) => { @@ -179,7 +174,7 @@ return text; }; - utils.renderImageURLs = function (obj) { + u.renderImageURLs = function (obj) { const list = obj.textContent.match(URL_REGEX) || []; _.forEach(list, function (url) { isImage(url).then(function (img) { @@ -191,23 +186,23 @@ return obj; }; - utils.slideInAllElements = function (elements) { + u.slideInAllElements = function (elements) { return Promise.all( _.map( elements, - _.partial(utils.slideIn, _, 600) + _.partial(u.slideIn, _, 600) )); }; - utils.slideToggleElement = function (el) { + u.slideToggleElement = function (el) { if (_.includes(el.classList, 'collapsed')) { - return utils.slideOut(el); + return u.slideOut(el); } 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. */ function calculateEndHeight (el) { @@ -237,7 +232,7 @@ window.clearInterval(interval_marker); } 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'; wrapup(el); 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. */ return new Promise((resolve, reject) => { if (_.isNil(el)) { @@ -275,7 +270,7 @@ return reject(new Error(err)); } else if (_.includes(el.classList, 'collapsed')) { 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.style.height = ""; return resolve(); @@ -307,11 +302,11 @@ }); }; - utils.fadeIn = function (el, callback) { + u.fadeIn = function (el, callback) { if (_.isNil(el)) { 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'); if (_.isFunction(callback)) { callback(); @@ -331,12 +326,12 @@ } }; - utils.isSameBareJID = function (jid1, jid2) { + u.isSameBareJID = function (jid1, jid2) { return Strophe.getBareJidFromJid(jid1).toLowerCase() === Strophe.getBareJidFromJid(jid2).toLowerCase(); }; - utils.isNewMessage = function (message) { + u.isNewMessage = function (message) { /* Given a stanza, determine whether it's a new * 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'), text = (!_.isNull(body) ? body.textContent: undefined); return text && !!text.match(/^\?OTR/); }; - utils.isHeadlineMessage = function (message) { + u.isHeadlineMessage = function (message) { var from_jid = message.getAttribute('from'); if (message.getAttribute('type') === 'headline') { return true; @@ -370,7 +365,7 @@ return false; }; - utils.merge = function merge (first, second) { + u.merge = function merge (first, second) { /* Merge the second object into the first one. */ 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 * 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, * otherwise chatboxes are not moved along when one is closed. */ @@ -412,34 +407,69 @@ } }; - utils.webForm2xForm = function (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 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 - })); - } + 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({ - 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 $('

').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('

'); + el.textContent = text; + return el; + } else if (field.getAttribute('type') === 'jid-multi') { 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({ - 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({ - 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({ - 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 { - 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 * as by the relevant library (e.g. converse.js or moment.js). * @@ -552,36 +583,36 @@ */ var locale, i; 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) { for (i=0; i _.includes(person._shortname, '_tone') ), (person) => person._shortname.replace(/_tone[1-5]/, '') @@ -696,11 +727,11 @@ return _converse.toned_emojis; }; - utils.isPersistableModel = function (model) { + u.isPersistableModel = function (model) { return model.collection && model.collection.browserStorage; }; - utils.getWrappedPromise = function () { + u.getWrappedPromise = function () { const wrapper = {}; wrapper.promise = new Promise((resolve, reject) => { wrapper.resolve = resolve; @@ -709,12 +740,12 @@ return wrapper; }; - utils.safeSave = function (model, attributes) { - if (utils.isPersistableModel(model)) { + u.safeSave = function (model, attributes) { + if (u.isPersistableModel(model)) { model.save(attributes); } else { model.set(attributes); } } - return utils; + return u; })); diff --git a/tests/mock.js b/tests/mock.js index 5d12cb51f..85280f74e 100644 --- a/tests/mock.js +++ b/tests/mock.js @@ -1,10 +1,10 @@ (function (root, 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 = {}; // Names from http://www.fakenamegenerator.com/ mock.req_names = [ @@ -99,7 +99,7 @@ }); } - var _converse = converse_api.initialize(_.extend({ + var _converse = converse.initialize(_.extend({ 'i18n': 'en', 'auto_subscribe': false, 'play_sounds': false, @@ -113,7 +113,7 @@ 'debug': false }, settings || {})); _converse.ChatBoxViews.prototype.trimChat = function () {}; - _converse.disable_effects = true; + window.converse_disable_effects = true; $.fx.off = true; return _converse; }