Is there any method in Fullcalendar v5 which rerenders event? - javascript

I have bootstrap popover initialized on events, inside popover content i have button (on click button calls function which changes the extendedProp.status of related event using event.setExtendedProp() method)
//above of my code FullCalendar has rendered and set as variable var = calendar
eventDidMount: function (info) {
$(info.el).popover({
html: true,
content: PopoverHtml(info.event),
container: 'body',
animation: true,
})
}
Since popover is initialized right after the event element has been added to the DOM i need to rerender event to change popover's content
eventChange: function (changeInfo) {
event_source = calendar.getEventSourceById(changeInfo.event.id);
event_source.refetch();
},
I also tried dynamic content setting method of bootstrap setContent()

I use popover with eventClick without problems:
function event_click(info) {
$('.popover_show').popover('dispose');
$(info.jsEvent.srcElement).popover({
container: 'body',
animation: false,
title: 'Zeitraum: '+fc_date_print(info.event.start, true)+" - "+fc_date_print(info.event.end, false)+
"<a href='#' class='float-right' onclick='form_cancel()' ><img src='/icon/x.svg' width='23' height='23' > </a>",
placement: 'bottom',
boundary: 'window',
sanitize: false,
trigger : 'manual',
popperConfig: {eventsEnabled: false },
"html": true,
content: function(){ a = get_form(info.event.extendedProps['id']); return a; }
});
$(info.jsEvent.srcElement).popover('show');
$(info.jsEvent.srcElement).addClass('popover_show');
}
I create the popover-content dynamicly in get_form() (currently in 2 way, one by javascript from extentedProbs, second I load content from popover dynamicly via ajax. This is much more efficent, than creating a popover for every event in advance.
Works fine for me.
The line
$(info.jsEvent.srcElement).popover('show');
do the magic, that you don't need a second click.
I add the class popover_show to the sourceElement, so $('.popover_show').popover('dispose');
will close all popover. (I do that before open a new popover)
But there are plenty other ways for that.

Related

Change tooltip content by Tippy js v6

I'm using clipboard js to copy-paste content and there is a tooltip attached to the button by Tippy js.
But how do I change the tooltip content and make it appear for two seconds as long as the clipboard success event is fired? I cannot think of a way to change the content because I'm not using the prop but the attribute method.
Possible related doc:
https://atomiks.github.io/tippyjs/v6/constructor/
https://atomiks.github.io/tippyjs/v6/tippy-instance/
https://atomiks.github.io/tippyjs/v6/methods/
var clipboard = new ClipboardJS('.btn');
tippy('.btn', {
placement: 'bottom',
theme: 'clean'
});
clipboard.on('success', function(e) {
//Change the tooltip content and show for two seconds
});
<button class="btn" data-clipboard-text="Testing...123" data-tippy-content="Tooltip">
Copy to clipboard
</button>
<script src="https://unpkg.com/#popperjs/core#2"></script>
<script src="https://unpkg.com/tippy.js#6"></script>
<script src="https://unpkg.com/clipboard#2/dist/clipboard.min.js"></script>
You just need to get instance of your tippy object and call some methods on it in your event listener.
var clipboard = new ClipboardJS('.btn');
const btnTippy = tippy('.btn', {
placement: 'bottom',
theme: 'clean',
})[0]; // 0-index used because tippy will return array of buttons here. You can use `querySelector` that will return only one instance if don't need array.
const copiedTippy = tippy('.btn', {
placement: 'bottom',
theme: 'clean',
trigger: '',
})[0];
copiedTippy.setContent('Just copied')
clipboard.on('success', function (e) {
copiedTippy.show()
setTimeout(copiedTippy.hide, 2000) // to hide tip after 2 seconds
});

Popover with MeteorJS

Try to use bootstrap popover with MeteorJS and have 2 troubles:
Can't assign some value that coming from collection to input value
I try to get one popover on html,body but have every popover on every template, it's normal, but I try to do only 1 popover on 1 screen
I have collection Posts with such documents Posts.insert({title:"Loli Pop"});
Meteor.publish("posts_levels", function(){
return Posts.find();
});
<template name="www">
{{#each level}}
{{> one}}
{{/each}}
</template>
Template.www.onCreated(function(){
var self = this;
self.autorun(function() {
self.subscribe('posts_levels');
});
});
<template name="one">
<div class="popover-markup">
<div class=" trigger ">
Edit
</div>
</div>
<div class="content-popover hide">
<form class="form">
<input name="title" id="post_edit_title" value="{{title}}" />
</form>
</div>
</template>
Template.one.onRendered(function(){
$('.popover-markup > .trigger').popover({
html : true,
content: function() {
return $('.content-popover').html();
},
container: 'body',
placement: 'right'
});
EDIT: 2 problem solved for 50%, I add this, and now it's hide when I open another popover, but then I must click 2x on .trigger to show new popover
$('.popover-markup > .trigger').popover({
html : true,
content: function() {
return $('.content-popover').html();
},
container: 'body',
placement: 'right'
}).on("click", function(e){
$('.trigger').not(this).popover('hide');
});
Here's an anwser for your question 1 (assign value from collection to input).
The input in the template gets the value of title. When you remove the hide class you can see the title from the collection. But a popover inserts new elements into the DOM. And those new elements are rendered by Bootstrap and not rendered by Blaze, so the input is not filled with the value of title.
What you can do is attach an event handler to the popover when it is shown. Something like this:
Template.one.onRendered(function(){
$('.popover-markup > .trigger').popover({
html: true,
content: function () {
return $('.content-popover').html();
},
container: 'body',
placement: 'auto top'
}).on('shown.bs.popover', function () {
$('.popover-content #post_edit_title').val(this.data.title);
}.bind(this));
});
As you can see the event shown.bs.popover can be used to do some initialization. In the event handler the value for the input is set.
It is important to have the jquery selector find your input in the popped form, that's why the selector starts with .popover-content. Otherwise it would set the value to the first input that was defined in the template.
Another thing to note is the use of bind(this). That attaches this and makes it usable inside the event handler so you can get the value of title.
BTW, there is also a hidden.bs.popover event when the popover is closing.

calling a template helper function from inside a template event callback

I am very new to meteor and it is possible that I am going about this entirely incorrectly.
I have a simple template that represents a menu bar. When the user clicks an Icon, the menu is supposed to appear. When they click it again, it is supposed to disappear.
Here is the markup:
<template name="menu">
<div class="menu">
<div class="toggler">
<i class="fa fa-bars fa-3x"></i>
</div>
<div class="menu-body">
<!-- ... -->
</div>
</div>
</template>
Here is the JS that I have:
Template.menu.helpers({
self: Template.instance(),
menu_body: self.find('.menu-body'),
toggler: self.find('.toggler'),
currently_open: false,
open: function() {
menu_body.style.display = 'flex';
},
close: function() {
menu_body.style.display = 'none';
},
toggle: function() {
if(currently_open) close();
else open();
}
});
Template.menu.events({
'click .toggler': function(event, template) {
console.log(template);
template.toggle();
}
});
I thought the template instance would have access to the helper functions, but according to the log statement, this is what the template instance consists of:
B…e.TemplateInstance {view: B…e.View, data: null, firstNode: div.menu, lastNode: div.menu, _allSubsReadyDep: T…r.Dependency…}
_allSubsReady: false
_allSubsReadyDep: Tracker.Dependency
_subscriptionHandles: Object
data: null
firstNode: div.menu
lastNode: div.menu
view: Blaze.View
__proto__: Blaze.TemplateInstance
Can someone point me in the right direction here. Please feel free to be scrutinous if I am going about it wrong.
Helpers are for functional calls - not event driven works.
Meteor has an events handle that you can use to track events like clicks. Also you can use your css classes to define the styles nicely without programatically overwriting them.
Template.name.events({
'click .menuToggler': function(event, template) {
event.preventDefault();
var menu = template.find('.menu-body'); //(make this in ID!)
if($(menu).hasClass('menuOpen')) {
$(menu).removeClass('menuOpen');
//menu.style.display = 'none';
} else {
$(menu).addClass('menuOpen');
//menu.style.display = 'flex'; Use css to define these on the menuOpen class
}
});
Some things to note: This event handle assumes that your menu-body class is available under the template called "name" in my example. So you will want this event handler at the most top level template you have. It also assumes.
If you want to share state between the various components of your template (helpers, event callbacks etc) it should be done by setting properties directly on the template instances.
This can be done through the onCreated() callback
As per the documentation:
Callbacks added with this method [are] called before your template's logic
is evaluated for the first time. Inside a callback, this is the new
template instance object. Properties you set on this object will be
visible from the callbacks added with onRendered and onDestroyed
methods and from event handlers.
These callbacks fire once and are the first group of callbacks to
fire. Handling the created event is a useful way to set up values on
template instance that are read from template helpers using
Template.instance().
So, to provide a more relevant and concise example than the one in my original question.
Template.menu.onCreated(function() {
this.items = [
{title: 'Home', icon: 'home'},
{title: 'Profile', icon: 'user'},
{title: 'Work', icon: 'line-chart'},
{title: 'Contact', icon: 'phone'}
];
});
Template.menu.helpers({
items: function() {
var self = Template.instance();
return self.items;
}
});
Template.menu.events({
'click .toggler': function(event, template) {
console.log(template.items); //[Object,Object,Object,Object]
//do something with items
}
});
That's actually funny but I created a mini package that helps you do just that: https://atmospherejs.com/voidale/helpers-everywhere
But in your case it's not the right way of doing it. I can you see you want to add an display either flex or none it's better add CSS element like active that hold display: flex and add active or remove it on click like this: $('').addClass('active') or $().removeClass('active')
one liner can also work here: $('.menu-body').toggleClass('active')

TinyMCE Enable button while in read only mode

I have a TinyMCE 4.x instance where the text should be in read only mode. But I still have some buttons that I want to have enabled. For example, one button could provide a character count for the part of the text I've selected.
But when I turn on read only mode for TinyMCE all buttons are disabled. Can I enable just my buttons while still retaining read only mode?
It's probably too late for you but other people may pass by here.
I came up by writing this function
function enableTinyMceEditorPlugin(editorId, pluginName, commandName) {
var htmlEditorDiv = document.getElementById(editorId).previousSibling;
var editor = tinymce.get(editorId);
var buttonDiv = htmlEditorDiv.querySelectorAll('.mce-i-' + pluginName.toLowerCase())[0].parentElement.parentElement;
buttonDiv.className = buttonDiv.className.replace(' mce-disabled', '');
buttonDiv.removeAttribute('aria-disabled');
buttonDiv.firstChild.onclick = function () {
editor.execCommand(commandName);
};
}
It does the trick in 2 steps:
make the button clickable (remove mce-disabled CSS class and remove the aria-disabled property)
assign the good command to the click event
And in my editor init event I call the function.
editor.on('init', function () {
if (readOnly) {
editor.setMode('readonly');
enableTinyMceEditorPlugin(htmlEditorId, 'preview', 'mcePreview');
enableTinyMceEditorPlugin(htmlEditorId, 'code', 'mceCodeEditor');
}
});
Current version of TinyMCE for which I wrote this code is 4.4.3. It may break in a future version, specifically about the selectors to get and modify the good HTML elements.
Command identifiers can be found at this page otherwise you can also find them under tinymce\plugins\PluginName\plugin(.min).js
Here is a simple way to enable your custom toolbar button and attach a click event handler inside a read only TinyMCE editor using JQUERY:
//Initialize read only Tinymce editor so that Lock button is also disabled
function initReadOnlyTinyMCE() {
tinymce.init({
selector: '#main'
, toolbar: 'myLockButton'
, body_class: 'main-div'
, content_css: 'stylesheets/index.css'
, readonly: true
, setup: function (readOnlyMain) {
readOnlyMain.addButton('myLockButton', { //Lock button is disabled because readonly is set to true
image: 'images/lock.png'
, tooltip: 'Lock Editor'
});
}
});
}
function displayReadOnlyTinyMCEwithLockButtonEnabled() {
var edContent = $('main').html();
$("#main").empty();
initReadOnlyTinyMCE(true);
tinyMCE.activeEditor.setContent(edContent);
//enable the lock button and attach a click event handler
$('[aria-label="Lock Editor"]').removeClass("mce-disabled");
$('[aria-label="Lock Editor"]').removeAttr("aria-disabled");
$('[aria-label="Lock Editor"]').attr("onclick", "LockEditor()");
}
function LockEditor() {
alert("Tiny mce editor is locked by the current user!!");
//Write your logic to lock the editor...
}
I couldn't find an easy way to do this. The simplest way is to remove the contenteditable attribute from the iframe body instead and substitute a read only toolbar set. It also means that people will still be able to copy content from the editor.
$("iframe").contents().find("body").removeAttr("contenteditable");
How about this :
editor.addButton('yourButton', {
title: 'One can Enable/disable TinyMCE',
text: "Disable",
onclick: function (ee) {
editor.setMode('readonly');
if($(ee.target).text() == "Disable"){
var theEle = $(ee.target).toggle();
var edit = editor;
var newBut = "<input type='button' style='opacity:1;color:white; background-color:orange;' value='Enable'/>";
$(newBut).prependTo($(theEle).closest("div")).click(function(e){
edit.setMode('design');
$(e.target).remove();
$(theEle).toggle();
});
}
}
});
You can try to run the code below:
$("#tinymce").contentEditable="false";
if you have more than one editors, you can use their id like below
$("#tinymce[data-id='idOfTheEditor']").contentEditable="false";

Add click event to the summary row of grid in extjs

Asked this question yesterday but not getting any response to posting it again in diffrent words-
I have two columns with summary row-
var cols = [
{ id: 'myCol1', header: 'Price1', dataIndex: 'PRICE1', type: 'float', width: 50, summaryType: 'sum' },
{ id: 'myCol2', header: 'Price2', dataIndex: 'PRICE2', type: 'float', width: 50, summaryType: 'sum' },
];
I want to add cellclick event to these summary row so that on click I can open a new window
If I use cellclick event of grid, it works for all cells except this summary row.
Is there any other event which I can use so that I would be able to click on it.
UPDATE:
I have used following listener which is not working for summary row
listeners: {
cellclick: function(grid, rowIndex, cellIndex) {
// do whatever
},
scope: this
}
As far as I know, there's no built-in event for summary row click. What you can do is add a listener to the cell element itself.
You can do that easily by using the delegate option of the listener. But this option is only available for DOM elements events, so we also have to use the element option to hook our event on the grid's body element (alternatively, you can use something like myGrid.getEl().on({ ... })).
Here's an example of listeners that you would add directly to your grid's config:
listeners: {
scope: this
,click: {
element: 'body'
// Would have been great to use '.x-grid-row-summary .x-grid-cell',
// but delegate only accept a *simple selector* which, seemingly,
// means just one class...
,delegate: '.x-grid-cell'
,fn: function(e, target) {
// Remove the condition if you want to catch all cells. You won't
// have all the arguments that are available in the cellclick
// event, though.
if (Ext.fly(target).up('tr').is('.x-grid-row-summary')) {
// The cellIndex is assigned by the table view when it render the
// cell element.
alert('Click on summary cell at index ' + target.cellIndex);
}
}
}
}
Unfortunately, this kind of code relies on class names and the cellIndex property that are set by Ext, and that may change in the future... Keep that in mind when you upgrade the lib!
I am not sure about the code u have used adding event for row click, but still i am adding this code to grid panel hope it helps,sry if u have tried already.. I have edited this below will do i believe..
listeners: {
cellclick: function(iView, iCellEl, iColIdx, iRecord, iRowEl, iRowIdx, iEvent) {
var fieldName = iView.getGridColumns()[iColIdx].dataIndex;
console.log(fieldName );
}
}

Categories

Resources