ISSUE: Kendo tooltip with custom angularjs directive and kendoConfirm - angularjs-directive

My current situation:
kendo tooltip works fine alone.
my new custom angularjs directive with kendoConfirm works fine alone.
but once i try to use them both together on an element, then only the kendo tooltip stops working.
<button type="button" title="Disable Item" k-confirm-disable k-confirm-disable-title="'Confirm Disable'" k-confirm-disable-msg="'Are you sure you want to disable this item?'" ng-click="disable(dataItem.id)" class="btn btn-danger" kendo-tooltip k-content="'Disable Item'" k-options="kendoTooltipOptions">
$scope.kendoTooltipOptions = {
showAfter: 600, //time for tooltip appear
position : 'top',
width : 100
}
kendo tooltip only works when I remove the custom angular directive from the element.
function kConfirmDisable($compile){
return {
restrict: 'A',
scope: {
kConfirmDisableTitle: '#',
kConfirmDisableMsg: '#'
},
link: function(scope, element, attrs){
var clickHandlers = $._data(element[0]).events.click;
clickHandlers.reverse(); //reverse the click event handlers list
var onClick = function(evt) {
evt.preventDefault();
evt.stopImmediatePropagation();
if(!scope.kConfirmDisableTitle) {
scope.kConfirmDisableTitle = "Confirm";
}
if(!scope.kConfirmDisableMsg) {
scope.kConfirmDisableMsg = "Are you sure?";
}
angular.element("<div></div>").kendoConfirm({
title: scope.kConfirmDisableTitle.replace(/['"]+/g, ''),
content: scope.kConfirmDisableMsg.replace(/['"]+/g, ''),
buttonLayout: "normal",
visible: false,
actions: [
{
text: "No",
Primary: false,
action: function(){
evt.preventDefault();
evt.stopImmediatePropagation();
}
},
{
text: "Yes",
Primary: true,
action: function(){
element.unbind(this);
setTimeout(function() {
element.unbind("click", onClick);
element.click();
evt.preventDefault();
evt.stopImmediatePropagation();
element.on("click", onClick);
},0);
}
},
],
animation: {
open:{
effects: "zoom:in",
duration: 250
},
close:{
effects: "fade:out",
duration: 250
}
},
open: function(e) {
$("html, body").css("overflow", "hidden");
},
close: function() {
$("html, body").css("overflow", "visible");
}
}).data("kendoConfirm").open().result;
};
element.on("click", onClick);
clickHandlers.reverse();
}
}
}

Since Kendo AngularJs source is not available, I can only suggest couple of things:
Try to research what happens if you dont stop the propagation and not stop the default on the click in your directive.
If the scenario is that it does not work immediately on page reload and hovering on the element without using clicks- then this is not relevant.
Avoid using isolated scope in your directive and get the attributes via the $attrs link function parameter. Since you did not specify you get js error, I am assuming Kendo isn't using isolated scope, but it is still a direction to investigate.

my solution is I removed the "k-" from the "k-confirm-disable" directive and it worked.
i think its because kendo has "k-" reserved.

Related

Hide and Unhide text using popper.js

I have the following popper.js script and I want that when I click a button a text appears and when I click the button again the text disappears. The script shown only unhide the text.
var ref = $('#button-a');
var popup = $('#popup');
popup.hide();
ref.click(function(){
popup.show();
var popper = new Popper(ref,popup,{
placement: 'bottom',
onCreate: function(data){
console.log(data);
},
modifiers: {
flip: {
behavior: ['bottom']
},
offset: {
enabled: true,
offset: '0,10'
}
}
});
});
Your event handler is never calling .hide() (I assume these are the JQuery show and hide functions?). You either need to use .toggle() instead of .show() or set up a conditional that handles the case where the popup is already visible and calls .hide().

Extending sap.ui.core.Icon with hover event or mouseover

I extended sap.ui.core.Icon with hover event handling:
sap.ui.define(function () {
"use strict";
return sap.ui.core.Icon.extend("abc.reuseController.HoverIcon", {
metadata: {
events: {
"hover" : {}
}
},
// the hover event handler, it is called when the Button is hovered - no event registration required
onmouseover : function(evt) {
this.fireHover();
},
// add nothing, just inherit the ButtonRenderer as is
renderer: {}
});
});
The event onmouseover is never fired. I also used this extension for sap.m.Button and it works. But I need this for sap.ui.core.Icon.
I also tried this jquery example but it did not work at all.
$("testIcon").hover(function(oEvent){alert("Button" + oEvent.getSource().getId());});
Please, do you have any idea why event handler onmouseover is not called for sap.ui.core.Icon? Or can you propose some other solution?
Bellow is how I added icon to my sap.suite.ui.commons.ChartContainer:
var oFilterIcon = new HoverIcon({
tooltip : "{i18n>filter}",
src : "sap-icon://filter",
hover : function(oEvent){alert("Button" + oEvent.getSource().getId());},
});
this.byId("idChartContainer").addCustomIcon(oFilterIcon);
This is my analysis:
Your new custom Control Icon for hover is correct. If you will use it independently it will work correctly .
However, your custom control will not work as your icons are converted to sap.m.OverflowToolbarButton when you use ChartContainer.
I looked into the source code of Chart Container and below is the code:
sap.suite.ui.commons.ChartContainer.prototype._addButtonToCustomIcons = function(i) {
var I = i;
var s = I.getTooltip();
var b = new sap.m.OverflowToolbarButton({
icon: I.getSrc(),
text: s,
tooltip: s,
type: sap.m.ButtonType.Transparent,
width: "3rem",
press: [{
icon: I
}, this._onOverflowToolbarButtonPress.bind(this)]
});
this._aCustomIcons.push(b);
}
So, you Icon is not used but its properties are used. As this is standard code, your hover code of Custom icon is not passed along.
One solution will be to add the onmouseover to sap.m.OverflowToolbarButton :
sap.m.OverflowToolbarButton.prototype.onmouseover=function() {
alert('hey')
};
However, this is dangerous as all OverflowToolbarButton button start using this code and I will not recommend it.
Next solution would be to overwrite the private method:_addButtonToCustomIcons ( again not recommendred :( )
sap.suite.ui.commons.ChartContainer.prototype._addButtonToCustomIcons = function(icon) {
var oIcon = icon;
var sIconTooltip = oIcon.getTooltip();
var oButton = new sap.m.OverflowToolbarButton({
icon : oIcon.getSrc(),
text : sIconTooltip,
tooltip : sIconTooltip,
type : sap.m.ButtonType.Transparent,
width : "3rem",
press: [{icon: oIcon}, this._onOverflowToolbarButtonPress.bind(this)]
});
this._aCustomIcons.push(oButton);
//oButton.onmouseover.
oButton.onmouseover = function() {
this.fireHover();
}.bind(oIcon);
};
Let me know if this helps u. :)

draggable rows in a p:dataTable by handle

I have a DataTable in which I added drag and drop support for the rows (draggableRows="true"). The problem is that wherever I click inside a row, I can drag it.
What I want is the possibility to drag the row only by a handle, the handle could be a column field with an icon at the left of the row for example (have a look at the screenshot), so if the user clicks on a row outside of the handle, there's no drag support; but if he clicks on the handle, he'll have the possibility to drag the entire row.
How could I implement this?
The source is always with you. In there you can see the makeRowsDraggable function on line 2727 in datatable.js
makeRowsDraggable: function() {
var $this = this;
this.tbody.sortable({
placeholder: 'ui-datatable-rowordering ui-state-active',
cursor: 'move',
handle: 'td,span:not(.ui-c)',
appendTo: document.body,
start: function(event, ui) {
ui.helper.css('z-index', ++PrimeFaces.zindex);
},
...
}
with a reference to the handle ('td, span:not(.ui-c)').
By overriding this function and having the handle point to a selector that explicitly refers to your handle, you can 'fix' it.
You can even make this generic by not assigning an explict string to the handle, but but looking it up on e.g. a custom pass-through attribute you define on the datatable where you put the 'string' in.
Did I mention already that the source is always with you? Good thing to remember when having further questions
Since Primefaces 6.2 p:datatable has a property rowDragSelector specifically for this purpose. See the example below:
<p:dataTable value="#{myBean.entities}" id="myTablePreferredId" rowDragSelector=".draggableHandle" draggableRows="true">
<p:ajax event="rowReorder" listener="#{myBean.onRowReorder}"/>
<p:column>
<h:outputText styleClass="fa fa-arrows-v draggableHandle" />
</p:column>
...
</p:dataTable>
For more details refer to the primefaces documentation.
My solution is the same as the solution of #Kuketje.
Here is the source code (compatible with Primefaces 6.1)
if (PrimeFaces.widget.DataTable){
PrimeFaces.widget.DataTable = PrimeFaces.widget.DataTable.extend({
makeRowsDraggable: function () {
var $this = this,
draggableHandle = '.dnd-handle'; //change to what ever selector as you like
this.tbody.sortable({
placeholder: 'ui-datatable-rowordering ui-state-active',
cursor: 'move',
handle: draggableHandle,
appendTo: document.body,
start: function (event, ui) {
ui.helper.css('z-index', ++PrimeFaces.zindex);
},
helper: function (event, ui) {
var cells = ui.children(),
helper = $('<div class="ui-datatable ui-widget"><table><tbody></tbody></table></div>'),
helperRow = ui.clone(),
helperCells = helperRow.children();
for (var i = 0; i < helperCells.length; i++) {
helperCells.eq(i).width(cells.eq(i).width());
}
helperRow.appendTo(helper.find('tbody'));
return helper;
},
update: function (event, ui) {
var fromIndex = ui.item.data('ri'),
toIndex = $this.paginator ? $this.paginator.getFirst() + ui.item.index() : ui.item.index();
$this.syncRowParity();
var options = {
source: $this.id,
process: $this.id,
params: [
{name: $this.id + '_rowreorder', value: true},
{name: $this.id + '_fromIndex', value: fromIndex},
{name: $this.id + '_toIndex', value: toIndex},
{name: this.id + '_skipChildren', value: true}
]
}
if ($this.hasBehavior('rowReorder')) {
$this.cfg.behaviors['rowReorder'].call($this, options);
}
else {
PrimeFaces.ajax.Request.handle(options);
}
},
change: function (event, ui) {
if ($this.cfg.scrollable) {
PrimeFaces.scrollInView($this.scrollBody, ui.placeholder);
}
}
});
}
});
}
The solution from Vít Suchánek is not really working. It detects the drag&drop handle only when the page is ready. After the first drag&drop interaction, it is not going to work anymore.
Another possibility is to override Primefaces's setting of handler after initialization of UI sortable:
<script type="text/javascript">
$(document).ready(function() {
var sortableRows = $(".tableWithDraggableRows > tbody");
if (sortableRows) {
sortableRows.sortable("option", "handle", ".ui-icon-arrow-4");
}
});
</script>
See http://api.jqueryui.com/sortable/#option-handle

jQuery UI Delay not work

why the delay doesn't work in this code?
$(function() {
$( "#button" ).click(function() {
$("#dialog").dialog({
show: { effect: 'fade', direction: "up" },
hide: { effect: 'fade', direction: "down" },
}).delay(1000).dialog( "close" );
return false;
});
});
Thank you!
From .delay documentation:
It can be used with the standard effects queue or with a custom queue. Only
subsequent events in a queue are delayed; for example this will not
delay the no-arguments forms of .show() or .hide() which do not use
the effects queue.

how do i add in mootools an onComplete event on a morph attached to a mouseleave?

here is my code:
$('myButton').addEvents({
mouseenter: function(){
$('myImage').setStyle('display','block');
$('myImage').morph({
'duration': 500,
'transition': Fx.Transitions.Sine.in,
'opacity': 1,
'top': -205
});
},
mouseleave: function(){
$('myImage').morph({
'opacity': 0,
'top': -175,
'onComplete': hidemyImage
});
}
});
function hidemyImage() {
$('myImage').setStyle('display','none')
}
the onComplete inside the mouseleave does not work as expected... it hides the image immediately when i move away from myButton instead of hiding it after the morph has finished... i tried several solutions but none worked so far. any idea / help? thanks in advance!
you need to work with the instance and not pass on things in the morph function directly, that takes properties to morph and it probably runs your function immediately in the hope it will return a property value. you can do el.set('morph', {onComplete: hideImagefn}) before that and it will work but read on...
one way to do it is to set your morph options/instance once and work with it afterwards like so:
(function() {
var img = document.id('myImage').set('morph', {
duration: 500,
transition: Fx.Transitions.Sine.in,
link: 'cancel',
onStart: function() {
this.element.setStyle('display', 'block');
}
}), fx = img.get('morph');
// of you can just do var fx = new Fx.Morph(img, { options});
document.id('myButton').addEvents({
mouseenter: function(){
fx.start({
opacity: 1,
top: -205
});
},
mouseleave: function(){
fx.addEvent('complete', function() {
this.element.setStyle('display', 'none');
this.removeEvents('complete');
}).start({
opacity: 0,
top: -175
});
}
});
})();
the start ensures its always visible when mouseovered, the link is cancel which means it will stop execution if you mouse out too early and if you do mouseout, it will then hide the image and remove the onComplete event so that if you show it once more, it stays visible when it comes into view.
if you don't plan on being able to bring it back you can clean-up better and even use event pseudos like onComplete:once etc - though thats part of Event.Pseudos from mootools-more.
in general - .get/.set morph is your setup. el.morph() passes values to morphInstance.start()
play here: http://jsfiddle.net/dimitar/NkNHX/