Notification Group Room message didn't show unread messages, only displays the browser notification - converse.js

How can I display unread messages like private chats..
Any new message to group room... didn't show the unread messages like private messages

This problem is marked as a bug in the issue tracker, so perhaps it will be fixed. Below is a workaround I've used using a plugin. What this does is it checks for a group message, and when received, adds a class to the minimized chat box. I added some example css with a style to blink the text in the box.
converse.plugins.add('myplugin', {
initialize: function () {
var c = this._converse;
c.on('message', function (m) {
if (m.stanza.textContent!='' && m.attrs.type == 'groupchat') {
$('.chat-head-chatroom').addClass('alert-room');
}
});
}
});
converse.initialize({
...
whitelisted_plugins: ['myplugin'],
...
CSS Code:
.alert-room {
font-weight: bold !important;
}
.alert-room .restore-chat {
animation: blinker 1s linear infinite;
}
#keyframes blinker {
50% {
opacity: 0.5;
}
}

Related

Position the dialog at the center of the screen in Fiori

I have a SAPUI5 Fiori application.
I use theme sap_fiori_3 as the base theme.
I customized this theme and only attached a background image to the theme.
The interesting part is when I activate this customized theme (that only has an extra background image in comparison to original sap_fiori_3 theme), the dialog are not centered in my app anymore.
The dialog are made with sap.m.dialog class.
I wrote a small snippet of code to center the dialog like following:
onAfterDialogOpen: function(oEvent){
var oDialog = oEvent.getSource(),
$Dialog = oDialog.$(),
oPosition = $Dialog.position(),
iTop = oPosition.top,
iLeft = oPosition.left,
iDialogWidth = $Dialog.width(),
iDialogHeight = $Dialog.height(),
iScreenWidth = sap.ui.Device.resize.width,
iScreenHight = sap.ui.Device.resize.height,
iNewTop = Math.floor((iScreenHight-iDialogHeight)/2),
iNewLeft = Math.floor((iScreenWidth-iDialogWidth)/2);
if(Math.abs(iNewLeft-iLeft) > 10 & Math.abs(iNewTop-iTop) > 10){
$Dialog.offset({top: iNewTop, left: iNewLeft});
}
},
But it is not a good solution. Why? Because it makes a motion on my screen like following:
Now the question is, how can I center the dialog without Java Script and by settings or some other tricks that when the dialog is opened, it be already centered.
Please note that using onBeforeOpen event is not possible as I need the size and position of the dialog!
I finally found out what is the source of the problem. It seems the Theme Designer of SAP is buggy and some part of the theme code does not transfer to the exported file.
When I use the theme designer to customize the theme it not only made the mentioned error, but also some other strange behavior appear in the deployed applications in the fiori launchpad which use the customized theme. However, we don't have those errors in the development time in the WEB IDE.
Therefore as I only needed to customize the following items:
background image
logo
favicon
I tried to use the standard theme like sap_fiori_3 and work around for setting these properties.
So for the first 2 issues I used the CSS hack:
div.sapUShellFullHeight {
background-image: url(../images/myBackgroundImage.svg);
background-repeat: no-repeat;
background-size: contain;
background-position: right;
}
a#shell-header-logo > img#shell-header-icon {
content:url(../images/logo.svg);
}
And for the favicon I used the promise solution. Please notice in the fiori launchpad each time that you switch between the applications fiori will reset the favicon, so I used the JavaScript promise to set it.
// Set the favicon dynamically to get read of blinking
function waitForElementAppear(selector) {
return new Promise(function(resolve, reject) {
var element = document.querySelector(selector);
if(element) {
resolve(element);
return;
}
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
var nodes = Array.from(mutation.addedNodes);
for(var node of nodes) {
if(node.matches && node.matches(selector)) {
observer.disconnect();
resolve(node);
return;
}
};
});
});
observer.observe(document.documentElement, { childList: true, subtree: true });
});
}
//
function waitForElementRemoved(selector) {
return new Promise((resolve) => {
var element = document.querySelector(selector);
if(!element) {
resolve();
return;
}
var observer = new MutationObserver((mutations, observer) => {
for (const mutation of mutations) {
for (const removedNode of mutation.removedNodes) {
if (removedNode === element) {
observer.disconnect();
resolve();
}
}
}
});
observer.observe(element.parentElement, { childList: true });
});
}
//
function changeFavIcon(selector) {
waitForElementAppear(selector).then(function(element) {
element.setAttribute("href", "icon/favicon.ico");
waitForElementRemoved(selector).then(function() {
changeFavIcon(selector);
});
});
};
changeFavIcon("link[rel='shortcut icon']");
It recursively checks when the favicon is injected then it will set its href and as soon as it is removed, this function will observe the next injection!
As I know somebody may says why not used sapui5 its original solution for setting the favicon, like this:
jQuery.sap.setIcons({
'phone': '/images/cimt-logo.png',
'phone#2': '/images/cimt-logo.png',
'tablet': '/images/cimt-logo.png',
'tablet#2': '/images/cimt-logo.png',
'favicon': '/icon/favicon.ico',
'precomposed': true
});
I must say it was not working in my case!

Customize leaflet routing error (options)

I am using Leaflet-routing-machine,
I added the error control to my map like this :
L.Routing.errorControl(this.control).addTo(map);
for style I used this :
.leaflet-routing-error {
width: 320px;
background-color: rgb(238, 153, 164);
padding-top: 4px;
transition: all 0.2s ease;
box-sizing: border-box;
}
this is what I got :
Ididn't find a lot of explanations about. Have anyone know how to customise this more, change language, hide/show... ?
After reading this source code
you can redefine the header and the fromat message function
L.Routing.errorControl(control, {
header: 'Routing error',
formatMessage(error) {
if (error.status < 0) {
return 'Calculating the route caused an error. Technical description follows: <code><pre>' +
error.message + '</pre></code';
} else {
return 'The route could not be calculated. ' +
error.message;
}
}
}).addTo(map);
I believe that in your control you can redefine this two options
also you may be able to use the leaflet element with classes leaflet-bar leaflet-routing-error and inject more html code on it as they do to create the alert
var L = require('leaflet');
onAdd: function() {
var header,
message;
this._element = L.DomUtil.create('div', 'leaflet-bar leaflet-routing-error');
this._element.style.visibility = 'hidden';
header = L.DomUtil.create('h3', null, this._element);
message = L.DomUtil.create('span', null, this._element);
header.innerHTML = this.options.header;
return this._element;
}
so retrieving the div of class or id leaflet-routing-error and injecting on it your desired html component template should be fine

Want counter to start counting only when in viewport

I have a counter that is working perfectly fine, but it starts counting when the page is loaded - meaning that often when the user scrolls down, the counter has already stoped and therefore the effect is lost.
I've tried multiple suggestions found here on Stack Overflow, but none worked for my specific case.
Here's my code:
$('.counter').each(function() {
var $this = $(this),
countTo = $this.attr('data-count');
$({ countNum: $this.text()}).animate({
countNum: countTo
},
{
duration: 9000,
easing:'linear',
step: function() {
$this.text(Math.floor(this.countNum));
},
complete: function() {
$this.text(this.countNum);
//alert('finished');
}
});
});
Any tips I could incorporate into my code to ensure the counter starts counting only in viewport?
Many thanks in advance!
A good way to achive is using IntersectionObserver https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API to active your countdown when in viewport.
First, create an observer that will trigger when in view, and then start countdown.
const options = {
root: null,
rootMargin: '0px', //this determines when observer will trigger
threshold: 0
}
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
if(entry.isIntersecting) {
observer.unobserve(entry.target)
activateCountdown(entry.target) //call you function that will activate the counter
}
})
}, options);
Now, apply this observer to all counter that exists
$('.counter').each((index, element) => {
observer.observe(element)
})
function activateCountdown(countdown) {
//here you activate your counter
}

Detect scrollHeight change with MutationObserver?

How can I detect when scrollHeight changes on a DOM element using MutationObserver? It's not an attribute and it isn't data either.
Background: I need to detect when a scrollbar appears on my content element, the overflow-y of which is set to auto. I figured that the instant the scrollbar appears the value of scrollHeight jumps from 0 to, say, 500, so the idea was to set up a MutationObserver to detect a change in this property.
What I've got so far:
HTML
<div class="body" #body>
CSS
.body {
overflow-y: auto;
}
TypeScript
export class MyWatchedContent implements AfterViewInit, OnDestroy {
#ViewChild('body', { read: ElementRef })
private body: ElementRef;
private observer: MutationObserver;
public ngAfterViewInit() {
this.observer = new MutationObserver(this.observerChanges);
this.observer.observe(this.body.nativeElement, {
attributes: true,
});
}
public ngOnDestroy() {
this.observer.disconnect();
}
private observerChanges(records: MutationRecord[], observer: MutationObserver) {
console.log('##### MUTATION');
records.forEach((_record) => {
console.log(_record);
});
}
}
If I, for example, change the background color in the developer window I can see the observer firing
MUTATION
my-content-watcher.component.ts?d0f4:233 MutationRecord {type: "attributes", target: div.body, addedNodes: NodeList(0), removedNodes: NodeList(0), previousSibling: null…}
If, however, I change the window size to make the scrollbar appear there's no mutation detected. Is this doable with MutationObserver at all and if so, how?
Here's the answer, for anyone still looking for the solution:
As of today, it's not possible to directly monitor scrollHeight changes of an element.
The MutationObserver detects changes in the DOM tree, which could indicate a scrollHeight change, but that's a wild guess.
The ResizeObserver detects changes in the outer height of an element, but not the scrollHeight (i.e. "inner" height).
There is no ScrollHeight-Observer (yet).
BUT the solution is very close:
The Solution
The ResizeObserver detects changes in the outer height of an element...
There's no point in observing the scroll-container because its outer height does not change. The element that changes their out height is any CHILD node of the container!
Once the height of a child node changes, it means, that the scrollHeight of the parent container changed.
Vanilla JS version
const container = document.querySelector('.scrollable-container');
const observer = new ResizeObserver(function() {
console.log('New scrollHeight', container.scrollHeight);
});
// This is the critical part: We observe the size of all children!
for (var i = 0; i < container.children.length; i++) {
observer.observe(container.children[i]);
})
jQuery version
const container = $('.scrollable-container');
const observer = new ResizeObserver(function() {
console.log('New scrollHeight', container[0].scrollHeight);
});
container.children().each(function(index, child) {
observer.observe(child);
});
Further steps
When children are added dynamically, you could add a MutationObserver to add new children to the ResizeObserver once they were added.
You can emulate this behavior by adding an internal wrapping element on the contenteditable element (eg a span) and then add the ResizeObserver listener on the internal element. The internal span has to be display:block otherwise it wont trigger the ResizeObserver.
HTML
<div contenteditable id="input"><span id="content">Some content</span></div>
CSS
#input {
max-height: 100px;
overflow: scroll;
white-space: pre-wrap;
}
#content {
display: block;
white-space: pre-wrap;
}
JS
const content = document.getElementById("content");
const observer = new ResizeObserver((entries) => {
for (const entry of entries) {
console.warn(entry);
}
});
observer.observe(content);

How do you animate the opening and closing of accordion sections in Zurb Foundation 4?

How do you animate the opening and closing of accordion sections in Zurb Foundation 4?
I've done extensive searching on Zurb Foundation's Google group and couldn't find any answers there either.
I wrote a fairly simple jQuery plugin to get this working. The plugin has default options, while also allowing overrides via the data-options attribute.
Tested on Foundation 5.
Here's the plugin:
(function($) {
$.fn.accordionAnimated = function() {
var
$accordion = this,
$items = $accordion.find('> dd'),
$targets = $items.find('.content'),
options = {
active_class : 'active', // class for items when active
multi_expand: false, // whether mutliple items can expand
speed : 500, // speed of animation
toggleable: true // setting to false only closes accordion panels when another is opened
}
;
$.extend(options, Foundation.utils.data_options($accordion));
$items.each(function(i) {
$(this).find('a:eq(0)').on('click.accordion', function() {
if(!options.toggleable && $items.eq(0).hasClass(options.active_class)) {
return;
}
$targets.eq(i)
.stop(true, true)
.slideToggle(options.speed);
if(!options.multi_expand) {
$targets.not(':eq('+i+')')
.stop(true, true)
.slideUp(options.speed);
}
});
});
};
}(jQuery));
and the plugin is simply invoked via
$('.accordion').accordionAnimated();
Hope this helps someone.
Assuming you're using Foundation's HTML classes:
.top-bar-section {
-webkit-transition: 0.2s all ease-in;
-moz-transition: 0.2s all ease-in;
-o-transition: 0.2s all ease-in;
transition: 0.2s all ease-in;
}