Commit b2a118ca authored by JC Brand's avatar JC Brand

Refactor slide methods in utils and use them for toolbar menus

parent ce2548c8
...@@ -148,7 +148,7 @@ css/mobile.min.css:: stamp-npm sass/* ...@@ -148,7 +148,7 @@ css/mobile.min.css:: stamp-npm sass/*
.PHONY: watch .PHONY: watch
watch: stamp-bundler watch: stamp-bundler
$(SASS) --watch -I ./node_modules/bourbon/app/assets/stylesheets/ sass/converse/converse.scss:css/converse.css sass/_muc_embedded.scss:css/converse-muc-embedded.css $(SASS) --watch -I ./node_modules/bourbon/app/assets/stylesheets/ sass/converse/converse.scss:css/converse.css sass/_muc_embedded.scss:css/converse-muc-embedded.css sass/inverse/inverse.scss:css/inverse.css
.PHONY: watchjs .PHONY: watchjs
watchjs: stamp-npm watchjs: stamp-npm
......
This diff is collapsed.
This diff is collapsed.
...@@ -272,14 +272,6 @@ ...@@ -272,14 +272,6 @@
text-decoration: none; text-decoration: none;
text-shadow: none; text-shadow: none;
} }
.emoji-picker {
margin-bottom: $toolbar-height + 5px;
}
.toolbar-picker-panel {
a {
color: $link-color;
}
}
.chat-toolbar-text { .chat-toolbar-text {
font-size: 12px; font-size: 12px;
padding-right: 3px; padding-right: 3px;
...@@ -287,7 +279,7 @@ ...@@ -287,7 +279,7 @@
.unencrypted a, .unencrypted a,
.unencrypted { .unencrypted {
color: $text-color; color: $text-color;
.toolbar-picker-panel { .toolbar-menu {
a { a {
color: $link-color; color: $link-color;
} }
...@@ -307,24 +299,39 @@ ...@@ -307,24 +299,39 @@
float: right; float: right;
} }
li { li {
cursor: pointer;
display: inline-block; display: inline-block;
list-style: none; list-style: none;
padding: 0 3px 0 3px;
cursor: pointer;
margin-top: 1px; margin-top: 1px;
} padding: 0 3px 0 3px;
li:hover { &:hover {
cursor: pointer; cursor: pointer;
} }
ul { .toolbar-menu {
background: #fff; background-color: #fff;
bottom: 100%; bottom: 100%;
box-shadow: -1px -1px 2px 0 rgba(0, 0, 0, 0.4); box-shadow: -1px -1px 2px 0 rgba(0, 0, 0, 0.4);
font-size: 12px; font-size: 12px;
margin: 0; margin: 0;
position: absolute; position: absolute;
right: 0; right: 0;
a {
color: $link-color;
}
ul {
&.emoji-category-picker {
box-shadow: -1px -1px 2px 0 rgba(0, 0, 0, 0.4);
z-index: 100;
.picked {
background-color: $highlight-color;
}
}
&.emoji-picker {
height: 250px;
overflow: scroll;
}
li { li {
margin-left: 0;
cursor: pointer; cursor: pointer;
list-style: none; list-style: none;
position: relative; position: relative;
...@@ -333,26 +340,22 @@ ...@@ -333,26 +340,22 @@
} }
} }
} }
li {
margin-left: 0;
} }
.toggle-smiley { &.toggle-toolbar-menu {
color: $text-color; color: $text-color;
padding-left: 5px;
ul { ul {
&.emoji-category-picker { li {
z-index: 100; &:hover {
.picked {
background-color: $highlight-color; background-color: $highlight-color;
} }
} }
&.emoji-picker {
height: 250px;
overflow: scroll;
} }
}
&.toggle-smiley {
padding-left: 5px;
ul {
left: 0; left: 0;
li { li {
font-size: $font-size;
padding: 5px; padding: 5px;
z-index: 98; z-index: 98;
&.emoji { &.emoji {
...@@ -361,29 +364,18 @@ ...@@ -361,29 +364,18 @@
} }
} }
} }
li:hover {
background-color: $highlight-color;
}
} }
} }
.toggle-otr { &.toggle-otr {
ul { ul {
z-index: 99;
li { li {
padding: 7px;
background-color: white;
display: block; display: block;
z-index: 99; padding: 7px;
a { a {
-moz-transition: background-color 0.2s ease-in-out;
-webkit-transition: background-color 0.2s ease-in-out;
transition: background-color 0.2s ease-in-out;
display: block; display: block;
padding: 1px;
text-decoration: none;
} }
} }
li:hover {
background-color: $highlight-color;
} }
} }
} }
......
...@@ -74,6 +74,10 @@ ...@@ -74,6 +74,10 @@
opacity: 0; opacity: 0;
display: none; display: none;
} }
.collapsed {
height: 0;
overflow: hidden;
}
.locked { .locked {
padding-right: 22px; padding-right: 22px;
......
...@@ -54,14 +54,13 @@ ...@@ -54,14 +54,13 @@
// //
registerGlobalEventHandlers: function () { registerGlobalEventHandlers: function () {
this.__super__.registerGlobalEventHandlers(); this.__super__.registerGlobalEventHandlers();
document.addEventListener('click', function () { document.addEventListener(
if ($('.toggle-smiley ul').is(':visible')) { 'click', function () {
_.each( utils.slideInAllElements(
document.querySelectorAll('.toggle-smiley .emoji-picker-container'), document.querySelectorAll('.toolbar-menu')
utils.hideElement )
);
} }
}); );
}, },
ChatBoxViews: { ChatBoxViews: {
...@@ -114,7 +113,7 @@ ...@@ -114,7 +113,7 @@
}); });
_converse.EmojiPickerView = Backbone.View.extend({ _converse.EmojiPickerView = Backbone.View.extend({
className: 'emoji-picker-container hidden', className: 'emoji-picker-container toolbar-menu collapsed',
events: { events: {
'click .emoji-category-picker li a': 'chooseCategory', 'click .emoji-category-picker li a': 'chooseCategory',
}, },
...@@ -710,7 +709,16 @@ ...@@ -710,7 +709,16 @@
return; return;
} }
} }
utils.toggleElement(this.emoji_picker_view.el); const elements = _.difference(
document.querySelectorAll('.toolbar-menu'),
[this.emoji_picker_view.el]
);
utils.slideInAllElements(elements).then(
_.partial(
utils.slideToggleElement,
this.emoji_picker_view.el
)
);
}, },
toggleCall (ev) { toggleCall (ev) {
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
OTR_CLASS_MAPPING[VERIFIED] = 'verified'; OTR_CLASS_MAPPING[VERIFIED] = 'verified';
OTR_CLASS_MAPPING[FINISHED] = 'finished'; OTR_CLASS_MAPPING[FINISHED] = 'finished';
converse.plugins.add('converse-otr', { converse.plugins.add('converse-otr', {
overrides: { overrides: {
...@@ -51,15 +52,6 @@ ...@@ -51,15 +52,6 @@
// //
// New functions which don't exist yet can also be added. // New functions which don't exist yet can also be added.
registerGlobalEventHandlers () {
this.__super__.registerGlobalEventHandlers();
document.addEventListener('click', function () {
if ($('.toggle-otr ul').is(':visible')) {
_.each($('.toggle-otr ul', this), utils.hideElement);
}
});
},
ChatBox: { ChatBox: {
initialize () { initialize () {
this.__super__.initialize.apply(this, arguments); this.__super__.initialize.apply(this, arguments);
...@@ -347,7 +339,6 @@ ...@@ -347,7 +339,6 @@
}, },
startOTRFromToolbar (ev) { startOTRFromToolbar (ev) {
$(ev.target).parent().parent().slideUp();
ev.stopPropagation(); ev.stopPropagation();
this.model.initiateOTR(); this.model.initiateOTR();
}, },
...@@ -392,7 +383,17 @@ ...@@ -392,7 +383,17 @@
toggleOTRMenu (ev) { toggleOTRMenu (ev) {
ev.stopPropagation(); ev.stopPropagation();
utils.toggleElement(this.el.querySelector('.toggle-otr ul')); const menu = this.el.querySelector('.toggle-otr ul');
const elements = _.difference(
document.querySelectorAll('.toolbar-menu'),
[menu]
);
utils.slideInAllElements(elements).then(
_.partial(
utils.slideToggleElement,
menu
)
);
}, },
getOTRTooltip () { getOTRTooltip () {
......
...@@ -70,7 +70,7 @@ ...@@ -70,7 +70,7 @@
}); });
this.hide(); this.hide();
if (this.list_model.get('toggle-state') !== _converse.OPENED) { if (this.list_model.get('toggle-state') !== _converse.OPENED) {
this.el.querySelector('.open-rooms-list').classList.add('hidden'); this.el.querySelector('.open-rooms-list').classList.add('collapsed');
} }
this.model.each(this.renderRoomsListElement.bind(this)); this.model.each(this.renderRoomsListElement.bind(this));
const controlboxview = _converse.chatboxviews.get('controlbox'); const controlboxview = _converse.chatboxviews.get('controlbox');
...@@ -142,13 +142,13 @@ ...@@ -142,13 +142,13 @@
if (ev && ev.preventDefault) { ev.preventDefault(); } if (ev && ev.preventDefault) { ev.preventDefault(); }
const el = ev.target; const el = ev.target;
if (el.classList.contains("icon-opened")) { if (el.classList.contains("icon-opened")) {
utils.slideUp(this.el.querySelector('.open-rooms-list')).then(() => { utils.slideIn(this.el.querySelector('.open-rooms-list')).then(() => {
this.list_model.save({'toggle-state': _converse.CLOSED}); this.list_model.save({'toggle-state': _converse.CLOSED});
el.classList.remove("icon-opened"); el.classList.remove("icon-opened");
el.classList.add("icon-closed"); el.classList.add("icon-closed");
}); });
} else { } else {
utils.slideDown(this.el.querySelector('.open-rooms-list')).then(() => { utils.slideOut(this.el.querySelector('.open-rooms-list')).then(() => {
this.list_model.save({'toggle-state': _converse.OPENED}); this.list_model.save({'toggle-state': _converse.OPENED});
el.classList.remove("icon-closed"); el.classList.remove("icon-closed");
el.classList.add("icon-opened"); el.classList.add("icon-opened");
......
<ul class="emoji-category-picker">
{[ _.forEach(emojis_by_category, function (obj, category) { ]}
<li data-category="{{{category}}}" class="emoji-category {[ if (current_category === category) { ]} picked {[ } ]}">
<a href="#" data-category="{{{category}}}"> {{ emojione.shortnameToUnicode(emojis_by_category[category][0]._shortname) }} </a>
</li>
{[ }); ]}
</ul>
{[ _.forEach(emojis_by_category, function (obj, category) { ]} {[ _.forEach(emojis_by_category, function (obj, category) { ]}
<ul class="emoji-picker emoji-picker-{{{category}}} {[ if (current_category !== category) { ]} hidden {[ } ]}"> <ul class="emoji-picker emoji-picker-{{{category}}} {[ if (current_category !== category) { ]} hidden {[ } ]}">
{[ _.forEach(emojis_by_category[category], function (emoji) { ]} {[ _.forEach(emojis_by_category[category], function (emoji) { ]}
...@@ -14,3 +7,10 @@ ...@@ -14,3 +7,10 @@
{[ }); ]} {[ }); ]}
</ul> </ul>
{[ }); ]} {[ }); ]}
<ul class="emoji-category-picker">
{[ _.forEach(emojis_by_category, function (obj, category) { ]}
<li data-category="{{{category}}}" class="emoji-category {[ if (current_category === category) { ]} picked {[ } ]}">
<a href="#" data-category="{{{category}}}"> {{ emojione.shortnameToUnicode(emojis_by_category[category][0]._shortname) }} </a>
</li>
{[ }); ]}
</ul>
{[ if (use_emoji) { ]} {[ if (use_emoji) { ]}
<li class="toggle-smiley icon-happy" title="{{{label_insert_smiley}}}"> <li class="toggle-toolbar-menu toggle-smiley icon-happy" title="{{{label_insert_smiley}}}">
<ul class="emoji-picker"></ul> <ul class="emoji-picker"></ul>
</li> </li>
{[ } ]} {[ } ]}
......
{[ if (allow_otr) { ]} {[ if (allow_otr) { ]}
<li class="toggle-otr {{{otr_status_class}}}" title="{{{otr_tooltip}}}"> <li class="toggle-toolbar-menu toggle-otr {{{otr_status_class}}}" title="{{{otr_tooltip}}}">
<span class="chat-toolbar-text">{{{otr_translated_status}}}</span> <span class="chat-toolbar-text">{{{otr_translated_status}}}</span>
{[ if (otr_status == UNENCRYPTED) { ]} {[ if (otr_status == UNENCRYPTED) { ]}
<span class="icon-unlocked"></span> <span class="icon-unlocked"></span>
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
{[ if (otr_status == FINISHED) { ]} {[ if (otr_status == FINISHED) { ]}
<span class="icon-unlocked"></span> <span class="icon-unlocked"></span>
{[ } ]} {[ } ]}
<ul class="toolbar-picker-panel"> <ul class="toolbar-menu collapsed">
{[ if (otr_status == UNENCRYPTED) { ]} {[ if (otr_status == UNENCRYPTED) { ]}
<li><a class="start-otr" href="#">{{{label_start_encrypted_conversation}}}</a></li> <li><a class="start-otr" href="#">{{{label_start_encrypted_conversation}}}</a></li>
{[ } ]} {[ } ]}
......
...@@ -129,10 +129,21 @@ ...@@ -129,10 +129,21 @@
return this; return this;
}; };
var utils = { function calculateSlideStep (height) {
if (height > 100) {
return 10;
} else if (height > 50) {
return 5;
} else {
return 1;
}
}
var utils = {};
// Translation machinery // Translation machinery
// --------------------- // ---------------------
__: function (str) { utils.__ = function (str) {
if (!utils.isConverseLocale(this.locale) || this.locale === 'en') { if (!utils.isConverseLocale(this.locale) || this.locale === 'en') {
return Jed.sprintf.apply(Jed, arguments); return Jed.sprintf.apply(Jed, arguments);
} }
...@@ -145,9 +156,9 @@ ...@@ -145,9 +156,9 @@
} else { } else {
return t.fetch(); return t.fetch();
} }
}, };
___: function (str) { utils.___ = 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
...@@ -156,9 +167,9 @@ ...@@ -156,9 +167,9 @@
* See actionInfoMessages in src/converse-muc.js * See actionInfoMessages in src/converse-muc.js
*/ */
return str; return str;
}, };
isLocaleAvailable: function (locale, available) { utils.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:
...@@ -172,78 +183,97 @@ ...@@ -172,78 +183,97 @@
return sublocale; return sublocale;
} }
} }
}, };
hideElement: function (el) { utils.slideInAllElements = function (elements) {
el.classList.add('hidden'); return Promise.all(
}, _.map(
elements,
_.partial(utils.slideIn, _, 600)
));
};
toggleElement: function (el) { utils.slideToggleElement = function (el) {
if (_.includes(el.classList, 'hidden')) { if (!el.offsetHeight) {
// XXX: use fadeIn? return utils.slideOut(el);
el.classList.remove('hidden');
} else { } else {
this.hideElement (el); return utils.slideIn(el);
} }
}, };
slideDown: function (el, interval=0.6) { utils.slideOut = function (el, duration=600) {
/* Shows/expands an element by sliding it out of itself. */
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (_.isNil(el)) { if (_.isNil(el)) {
const err = "Undefined or null element passed into slideDown" const err = "Undefined or null element passed into slideOut"
console.warn(err); console.warn(err);
reject(new Error(err)); reject(new Error(err));
} }
let intval = el.getAttribute('data-slider-intval'); let interval_marker = el.getAttribute('data-slider-marker');
if (intval) { if (interval_marker) {
window.clearInterval(intval); window.clearInterval(interval_marker);
} }
const end_height = _.reduce(el.children, function (result, child) {
return result + child.offsetHeight;
}, 0);
const step = calculateSlideStep(end_height),
interval = end_height/duration*step;
let h = 0; let h = 0;
const end_height = el.getAttribute('data-slider-height'); interval_marker = window.setInterval(function () {
intval = window.setInterval(function () { h += step;
h++; if (h < end_height) {
el.style.height = h + 'px'; el.style.height = h + 'px';
if (h >= end_height) { } else {
window.clearInterval(intval); el.style.height = end_height + 'px';
el.style.height = ''; window.clearInterval(interval_marker);
el.style.overflow = ''; el.style.overflow = '';
el.removeAttribute('data-slider-intval'); el.removeAttribute('data-slider-marker');
el.removeAttribute('data-slider-height');
resolve(); resolve();
} }
}, interval); }, interval);
el.setAttribute('data-slider-intval', intval); el.setAttribute('data-slider-marker', interval_marker);
}); });
}, };
slideUp: function (el, interval=0.6) { utils.slideIn = function (el, duration=600) {
/* 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)) {
const err = "Undefined or null element passed into slideUp"; const err = "Undefined or null element passed into slideIn";
console.warn(err); console.warn(err);
reject(new Error(err)); reject(new Error(err));
} }
let intval = el.getAttribute('data-slider-intval'); if (!el.offsetHeight) {
if (intval) { resolve();
window.clearInterval(intval); return;
}
let interval_marker = el.getAttribute('data-slider-marker');
if (interval_marker) {
window.clearInterval(interval_marker);
} }
let h = el.offsetHeight; let h = el.offsetHeight;
el.setAttribute('data-slider-height', h); const step = calculateSlideStep(h),
interval = h/duration*step;
el.style.overflow = 'hidden'; el.style.overflow = 'hidden';
intval = window.setInterval(function () {
interval_marker = window.setInterval(function () {
h -= step;
if (h > 0) {
el.style.height = h + 'px'; el.style.height = h + 'px';
h--; } else {
if (h < 0) { el.style.height = 0 + 'px';
window.clearInterval(intval); window.clearInterval(interval_marker);
el.removeAttribute('data-slider-intval'); el.removeAttribute('data-slider-marker');
resolve(); resolve();
} }
}, interval); }, interval);
el.setAttribute('data-slider-intval', intval); el.setAttribute('data-slider-marker', interval_marker);
}); });
}, };
fadeIn: function (el, callback) { utils.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");
} }
...@@ -265,14 +295,14 @@ ...@@ -265,14 +295,14 @@
} else { } else {
afterAnimationEnd(el, callback); afterAnimationEnd(el, callback);
} }
}, };
isSameBareJID: function (jid1, jid2) { utils.isSameBareJID = function (jid1, jid2) {
return Strophe.getBareJidFromJid(jid1).toLowerCase() === return Strophe.getBareJidFromJid(jid1).toLowerCase() ===
Strophe.getBareJidFromJid(jid2).toLowerCase(); Strophe.getBareJidFromJid(jid2).toLowerCase();
}, };
isNewMessage: function (message) { utils.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.
*/ */
...@@ -281,15 +311,15 @@ ...@@ -281,15 +311,15 @@
} else { } else {
return !message.get('archive_id'); return !message.get('archive_id');
} }
}, };
isOTRMessage: function (message) { utils.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/);
}, };
isHeadlineMessage: function (message) { utils.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;
...@@ -304,9 +334,9 @@ ...@@ -304,9 +334,9 @@
return true; return true;
} }
return false; return false;
}, };
merge: function merge (first, second) { utils.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) {
...@@ -316,9 +346,9 @@ ...@@ -316,9 +346,9 @@
first[k] = second[k]; first[k] = second[k];
} }
} }
}, };
applyUserSettings: function applyUserSettings (context, settings, user_settings) { utils.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.
*/ */
...@@ -332,9 +362,9 @@ ...@@ -332,9 +362,9 @@
context[k] = user_settings[k]; context[k] = user_settings[k];
} }
} }
}, };
refreshWebkit: function () { utils.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.
*/ */
...@@ -346,9 +376,9 @@ ...@@ -346,9 +376,9 @@
conversejs.style.display = 'block'; conversejs.style.display = 'block';
}); });
} }
}, };
webForm2xForm: function (field) { utils.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: * Parameters:
...@@ -373,9 +403,9 @@ ...@@ -373,9 +403,9 @@
name: $input.attr('name'), name: $input.attr('name'),
value: value value: value
}))[0]; }))[0];
}, };
contains: function (attr, query) { utils.contains = function (attr, query) {
return function (item) { return function (item) {
if (typeof attr === 'object') { if (typeof attr === 'object') {
var value = false; var value = false;
...@@ -389,9 +419,9 @@ ...@@ -389,9 +419,9 @@
throw new TypeError('contains: wrong attribute type. Must be string or array.'); throw new TypeError('contains: wrong attribute type. Must be string or array.');
} }
}; };
}, };
xForm2webForm: function ($field, $stanza) { utils.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. * and turns it into a HTML DOM field.
* *
...@@ -477,7 +507,6 @@ ...@@ -477,7 +507,6 @@
} }
} }
} }
};
utils.detectLocale = function (library_check) { utils.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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment