Locker Service and Tooltip on FullCalendar V4 - salesforce

Has anyone had any joy in adding tooltips to the full calendar V4 when locker service is enabled on Salesforce?
You cannot use a 3rd party library as a proxy is returned instead of the element, so the eventRender documented method will not work.
eventRender: function(info) {
var tooltip = new Tooltip(info.el, {
title: info.event.extendedProps.description,
placement: 'top',
trigger: 'hover',
container: 'body'
});
}
I have tried using the standard Salesforce helptext classes, but still with no joy.
I've tried setting the popover classes on the eventMouseEnter and eventRender but I constantly encounter the same message 'Cannot read property 'getElement' of undefined'
eventMouseEnter: function(info){
var tooltip = '<div aura:id="eleID" id="eventTooltip" class="slds-popover slds-popover_tooltip slds-nubbin_bottom-left" role="tooltip" style="position:absolute;top:-4px;left:35px">' +
'<div class="slds-popover__body">' + info.event.title + '</div>' +
'</div>';
console.log('Mouse entered = ' + info.event.title);
**//Failing on the below line, with 'Cannot read property 'getElement' of
undefined**
var myElement = component.find('eleID').getElement();
console.log('My Element', myElement);
info.el.setAttribute("aria-describedby","eventTooltip");
info.el.parentNode.innerHTML += tooltipHtml;
}
Does anyone have any suggestions?
Many thanks

I was able to add tooltip using the following in LWC:
eventMouseEnter: function(info){
var tooltipContainer=document.createElement("div");
tooltipContainer.setAttribute("id", "eventTooltip");
tooltipContainer.setAttribute("role", "tooltip");
tooltipContainer.setAttribute("class", "slds-popover slds-popover_tooltip slds-nubbin_left");
tooltipContainer.setAttribute("style", "position:absolute;top:0;width:320px;left:120px;");
var tooltipBody=document.createElement("div");
tooltipBody.innerHTML=info.event.extendedProps.tooltip;
tooltipBody.setAttribute("class", "slds-popover__body");
tooltipContainer.appendChild(tooltipBody);
info.el.setAttribute("aria-describedby","eventTooltip");
info.el.parentNode.appendChild(tooltipContainer);
//defaulting the tooltip to be visible for 5 seconds at maximum
setTimeout(function() {
let tooltip=document.getElementById("eventTooltip");
info.el.parentNode.removeChild(tooltip);
}, 5000);
}
},
eventMouseLeave: function(info){
var tooltip=document.getElementById("eventTooltip");
info.el.parentNode.removeChild(tooltip);
},

Related

ExtJS: reload tab data on tab change

I'm creating a MVC application and I ran into some problems. I've got a treestore as menu and a tabpanel with some items. When I click a specific menu item, let's call it mymenuitem1 or mymenuitem2, a new instance of mymenuitem class is created, but always a different set of data is loaded into this instance. The problem is, that after I click mymenuitem1 the data is loaded for corporation1, when I click mymenuitem2 the data is loaded for corporation2, but when I try just to change to mymenuitem1 from mymenuitem2, there still is data for corporation2
My mymenuitem class definition:
Ext.define('Fleximanager.view.pages.corpmain', {
extend: 'Ext.panel.Panel',
xtype: 'corpmaintab',
closable: true,
layout: 'vbox',
initComponent: function() {
this.items = [{
xtype: 'dataview',
flex: 5,
store: Ext.getStore('corpmain').load({
params:{
hostname: sessionStorage.hostname,
auth: sessionStorage.authSessionId,
corp: sessionStorage.activeCorp
}
}),
itemTpl: new Ext.XTemplate(
'<tpl for="(branches)">',
'<table id="tfhover" id="home_table" class="tftable" style="margin-bottom: 10px;">',
'<caption class="x-panel-header-default">{branch_name}</caption>',
'<tr><td colspan="2">Expenses:<br>{strediskonakladyCelk}</td><td colspan="2">Profit:<br>{strediskoziskCelk}({strediskomarzaCelk})</td><td colspan="2">Revenues:<br>{strediskoprijmyCelk}</td></tr>',
'<tr><td colspan="2">Not paid expenses:<br>{strediskoneuhrPrijCelk}</td><td colspan="2">VAT: <br>{streddphCelk}</td><td colspan="2">Not paid revenues:<br>{strediskoneuhrVydCelk}</td></tr>',
'</table>',
'</tpl>'
)
}],
this.renderTo = Ext.getBody();
this.callParent();
}
});
And how do I select and add tabs from menu:
setMenuItem: function(record){
var dbName = record.get('dbName');
var classname, controller;
if(record.isLeaf()){
classname = 'Fleximanager.view.pages.' + Ext.String.createVarName(dbName);
controller = this.getController(Ext.String.createVarName(dbName));
} else {
classname = 'Fleximanager.view.pages.corpmain';
controller = this.getController('corpmain');
}
var tabPanel = Ext.getCmp('flexitabs');
var tabId = record.parentNode.get('text') + '/' + dbName + 'tab'
var tabIndex = tabPanel.items.findIndex('id', tabId)
if(tabIndex != -1){
tabPanel.setActiveTab(tabIndex);
} else {
if(record.isLeaf() && record.parentNode.get('text') != 'Root'){
sessionStorage.activeCorp = record.parentNode.get('dbName')
tabPanel.add(Ext.create(classname, {
title: record.parentNode.get('text') + ' - ' + record.get('text'),
id: tabId,
rootId: record.parentNode.get('dbName'),
className: classname
}));
} else {
sessionStorage.activeCorp = record.get('dbName')
tabPanel.add(Ext.create(classname, {
title: record.get('text'),
id: tabId,
rootId: record.get('dbName'),
className: classname
}));
}
tabPanel.setActiveTab(tabId);
}
}
Could anyone please help me?
Any answer appreciated.
You are creating for each tab new instance of Fleximanager.view.pages.corpmain. But all tabs using the same instance of store (store with id corpmain) which is loading data when the tab instance is creating. So when you click on mymenuitem1, first tab is created and store is loaded with corporation1 data. When you click on mymenuitem2, second tab is created and store is loaded with corporation2 data. But when you click back on mymenuitem1, you find existing tab, but store is still loaded with corporation2 data.
So if you want to use only one instance of store, you need to reload it with proper data also when you are switching back to already existing tab.
Another possibility is to create new instance of store for each tab.

Sencha Ext Js - Add a span/div to form field template then dynamically change contents for a text counter

I am new to Ext Js so forgive me if my terminology for certain things is not correct. What I need is text counter. Here is what I have so far...
http://jsfiddle.net/gfrobenius/WxNDf/1/
What I need to do is make this code reusable so that all textareas get this feature but I still have the ability to change the normal settings like label, name, id, maxLength, etc... Does this mean turning it into a class, plugIn, component (sorry still trying to learn terminology)? Can my afterLabelTextTpl be done simpler? I've seen examples like:
var tpl = new Ext.Template('Name: {name}, Age: {age}');
tpl.apply({name: 'John', age: 25});
in the documentation but am not sure how to incorporate it into my code. Also in my three functions for updating the text count you can see I have the line for getting the component hard-coded to 'gtext' and the line for getting the 'countDownSpan' hard-coded as well. How do I go about making them just know the parent item?
You can make your own component and extend from a textarea. Also you're doing 3 times the same thing in your callback function. And the id of your textarea should be unique.
Here's an example of your component:
Ext.define('MyApp.ux.form.field.TextArea', {
alias: 'widget.textareacounter',
extend: 'Ext.form.field.TextArea',
labelAlign: 'top',
enableKeyEvents: true,
enforceMaxLength: false,
maxLength: 1000,
constructor: function(config) {
var me = this;
Ext.apply(me, config);
me.afterLabelTextTpl = ['<span style="margin-left:5px;">(' + me.maxLength + ' char. left)</span>'];
me.callParent()
},
initComponent: function () {
var me = this;
me.on({
keydown: me.calculateCharsLeft,
keyup: me.calculateCharsLeft,
afterrender: me.calculateCharsLeft,
scope: me
});
me.callParent();
},
calculateCharsLeft: function (textfield, e) {
var me = this;
var span = Ext.dom.Query.select('span', me.getEl().dom)[0];
var remaining = me.maxLength - me.getValue().length;
span.innerHTML = '(' + remaining + ' char. left)';
}
});
And a working fiddle: http://jsfiddle.net/johanhaest/cpLvK/2/

Dynamically add/remove regions to a layout

Is it possible to dynamically add and remove regions to a layout with Marionette? My app needs to be able to push and pop regions from a layout. This is similar to how GitHub pushes and pops views when you drill down in the source code of a project. They have the slide over animation when presenting the next view and then it slides back when you're backing out. The idea is that I need to keep the previous views around. Another analogy would be how UINavigationControllers work on iOS.
Or maybe I should just define a custom layout that is able to handle adding and removing regions on the fly?
I ended up implementing a container view to fit my needs. It cleans up event refs like you'd expect in Marionette.
https://github.com/ayoung/backbone-vs-marionette/blob/marionette/public/js/views/mainContainer.js
I'm not sure but you may be getting confused with the existence of some html and the displaying of that html?
I mean you can make a CompositeView of Items and only show one of the items at a time. Then use jQuery animate or another animation library to move through the CompositeView's Items.
Yes it is possible. Here is the code I use.
The layout:
var Layout = Marionette.LayoutView.extend({
initialize: function(options) {
options = _.extend({ regionTag: 'div' }, options);
this.mergeOptions(options, ['regionTag', 'regionName']);
},
template: false,
regions: {},
append: function(view) {
var viewClass = 'dynamic-layout-' + this.regionName,
viewCount = $('.' + viewClass).length + 1,
viewId = this.regionName + '-view-' + viewCount,
$el = $('<' + this.regionTag + '/>', {
id: viewId,
class: viewClass
});
this.$el.append($el);
var region = Marionette.Region.extend({
el: '#' + viewId
});
this.regionManager.addRegion(viewId, region);
this.regionManager.get(viewId).show(view);
},
appendEmpty: function(id, className, tag) {
tag = tag || 'div';
var data = { id: id, className: className, tag: tag };
var $el = Marionette.Renderer.render('#append-layout-template', data);
this.$el.append($el);
var region = Marionette.Region.extend({
el: '#' + id
});
this.regionManager.addRegion(id, region);
},
customRemove: function(regionId) {
this.regionManager.removeRegion(regionId);
}
});
A helpful template:
<script type="text/template" id="append-layout-template">
<<%= tag %> id='<%= id %>' class='<%= className %>'></<%= tag %>>
</script>
The controller:
var view = new SomeView();
// the region name will be a part of a unique id
var layout = new Layout({ regionName: 'myRegion' });
// add a dynamic region to the layout and a view to that region
layout.append(view);
// same as above (you have to name the id and class yourself)
var regionId = 'myRegionId';
layout.appendEmpty(regionId, 'someClassName', 'span');
layout.getRegion(regionId).show(view);
// remove a region
layout.customRemove(regionId);

extjs 3 - add progressbar and image in property grid

Is it possible to implement progressbar in property grid in extjs 3? How do I add an image in property grid?
I have a value in percentage and I want to represent that in progressbar (its uneditable).
Thanks a lot for help.
You could try something like this:
//==== Progress bar 1 ====
var pbar1 = new Ext.ProgressBar({
id:'pbar1',
width:300
});
var grid = new Ext.grid.PropertyGrid({
title: 'Properties Grid',
autoHeight: true,
width: 300,
renderTo: 'grid-ct',
bbar: pbar1, //You can set the progress bar as the property girds bottom toolbar.
customRenderers: {
Available: function(v){
return '<img src="path to image" />';
}
}, //This would render the image into the Available property.
source: {
"(name)": "My Object",
"Created": new Date(Date.parse('10/15/2006')),
"Available": false,
"Version": .01,
"Description": "A test object"
}
});
When using customRenderers to render the image
The name of the renderer type should correspond with the name of the property that it will render For more see the API.
This is the first thing I though about. But it's still not so user friendly as it's render progressbars after grid is rendered.
This is custom renderer for your progress column:
renderer: function( value, metaData, record, rowIndex, colIndex, store ) {
var id = Ext.id();
(function(){
var progress = new Ext.ProgressBar({
renderTo: id,
value: progress_value
});
}).defer(25);
return '<div id="'+ id + '"></div>';
}
It renders <div id="generated-id"/> and then renders generated progressbar into this div.
It would be better to use some kind of closure to create progressbar only once and to return it's html via custom renderer as in the example above, but unfortunately I don't know yet how to do it in Ext.js 3. As for Ext.js 4 you can see this thread at sencha forum

How to change loadingText on a Panel with Sencha Touch?

I'm using setLoading(true) on a Panel, but cant find a way to change the "Loading..." text below the spinner.
I need at least to translate it to Norwegian.
app.views.ForfallDetaljerView = Ext.extend(Ext.Panel,{
id: 'forfalldetaljer',
scroll: 'vertical',
dockedItems: [ new app.views.BackToolbar({
title: 'Detaljer',
buttonHandler: function(){
Ext.dispatch({
controller: app.controllers.forfallDetaljer,
action: 'back',
});
// Clear view
app.views.forfallDetaljer.update('');
}
})],
});
app.myview = new ForfallDetaljerView();
app.myview.setLoading(true);
Anyone got any idea?
app.myview = new ForfallDetaljerView();
var mask = new Ext.LoadMask(app.myview.el, {msg: "<text here>"});
mask.show();
You can then do a mask.hide() when you want to remove it.
You could also do something like:
var l = app.myview.setLoading(true);
l.el.down('div.x-loading-msg').setHTML("<text here>");
So hopefully these two options point you in the right direction.
There's another way to show the loading message:
var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
myMask.show();
Both Panel.setLoading(true) and Ext.LoadMask(...) return a LoadMask object. So it should work similarly.
http://dev.sencha.com/deploy/touch/docs/?class=Ext.LoadMask

Resources