cannot close jquery tooltip in a google map infobox - google-maps-markers

In my application, I've a huge map on the dashboard and there I'm placing markers when ajax content is loaded. Each marker has specifically designed infobox where I've a link that has two clases:
tooltip
fancybox
On mouseover, I expect the tooltip opened and on mouseout I expect it to be closed and on click I expect three things:
the infobox to be closed
the fancybox to be opened
the tooltip to be closed
The problem is that on mouseover and mouseout, the tooltip acts as expected but when I click on the link, the infobox closes, the fancybox opens but the tooltip doesn't close and it looses the parent connection and never closes.
Here are my codes:
var infowindow_options = {
content: '...<a class="bind_tooltip">...</a>...',
disableAutoPan: false,
maxWidth: 0,
alignBottom: true,
pixelOffset: new google.maps.Size( 10, 10 ),
zIndex: null,
boxClass: 'info_window',
closeBoxMargin: '10px 10px 0 0',
closeBoxURL: 'http://www.google.com/intl/en_us/mapfiles/close.gif',
pane: 'floatPane',
enableEventPropagation: true,
infoBoxClearance: '10px',
position: mrkr.position
};
google.maps.event.addListener( mrkr, 'click', function() {
infowindow ? infowindow.close() : '';
infowindow = new InfoBox( infowindow_options );
infowindow.open( map );
return false;
} );
google.maps.event.addListener( map, 'click', function() {
if( infowindow ) {
infowindow.close();
$( '.bind_tooltip' ).tooltip( 'close' );
}
return false;
} );
$( document ).tooltip( {
items: '.bind_tooltip',
content: function() {
return $( this ).parent().find( '.tooltip' ).html();
},
position: {my: 'left top+10', at: 'center center'}
} );
Also I get this error:
Error: cannot call methods on tooltip prior to initialization; attempted to call method 'close'

Initialize the tooltip before using it anywhere else in the script. You better do it at the beginning of script.
var infowindow_options = {
content: '...<a class="bind_tooltip">...</a>...',
disableAutoPan: false,
maxWidth: 0,
alignBottom: true,
pixelOffset: new google.maps.Size( 10, 10 ),
zIndex: null,
boxClass: 'info_window',
closeBoxMargin: '10px 10px 0 0',
closeBoxURL: 'http://www.google.com/intl/en_us/mapfiles/close.gif',
pane: 'floatPane',
enableEventPropagation: true,
infoBoxClearance: '10px',
position: mrkr.position
};
google.maps.event.addListener( mrkr, 'click', function() {
infowindow ? infowindow.close() : '';
infowindow = new InfoBox( infowindow_options );
infowindow.open( map );
return false;
} );
$( document ).tooltip( {
items: '.bind_tooltip',
content: function() {
return $( this ).parent().find( '.tooltip' ).html();
},
position: {my: 'left top+10', at: 'center center'}
} );
google.maps.event.addListener( map, 'click', function() {
if( infowindow ) {
infowindow.close();
$( '.bind_tooltip' ).tooltip( 'close' );
}
return false;
} );

Initializing tooltip at the beginning didn't solve my problem. So I've solved the problem this way. I've added earlier a block of code that when click on map the infowinfow should close. That's why I was loosing my infowinfow reference. So removing the auto close solved my problem.

Related

drag and drop with auto scrolling (dom-autoscrolling)

I have a list of text elements and want to automatically scroll my list to the bottom when I'm dragging my new element.
This example below works properly once I drag-and-dropped one time an element in a list.
I believe I need to call once an observable before the drag.
I'm using dragula and dom-autoscrolling.
import {takeUntil} from "rxjs/internal/operators/takeUntil";
import * as autoScroll from 'dom-autoscroller';
const drake = this.dragulaService.find(this.dragulaBagName);
this.dragulaService.drag.pipe(
takeUntil(this.destroyed$),
).subscribe(([bag, movingEl, containerEl]) => {
autoScroll(containerEl.parentNode, {
margin: 20,
pixels: 10,
scrollWhenOutside: true,
autoScroll: function () {
return this.down && drake && drake.drake && drake.drake.dragging;
}
});
});
Apparently, this.down in callback autoScroll is set to false at the beginning... once drag-and-dropped one time, it works correctly.
Any ideas?
try use (mousedown)="initAutoScroll()"
initAutoScroll(){
const drake = this.dragulaService.find(this.dragulaBagName);
this.scroll = autoScroll(
containerEl.parentNode,
{
margin: 30,
maxSpeed: 25,
scrollWhenOutside: true,
autoScroll: function () {
return this.down && drake.drake.dragging;
}
});
}
this.dragulaService.dragend.asObservable().subscribe(value => {
if (this.scroll) {
this.scroll.destroy(); // destroy when don't use auto-scroll
}
});

Call parent window function from child window

I'm trying to call a function on the parent page from a popup window. I keep getting the error Object doesn't support property or method 'GetValueFromChild'. I believe the error is on this line in the popup window -
window.top.opener.parent.Xrm.Page.GetValueFromChild(person);. I tried using window.opener.GetValueFromChild(person); but still get the same error. Any help is much appreciated. Here's the code -
//parent
$(document).ready(function () {
// This needs to be called from Child window
function GetValueFromChild(person) {
alert(person.Id);
alert(person.Name);
alert(person.Market);
}
});
//parent - jqgrid
colModel: [
{
name: 'Person', index: 'PersonName', width: 70, editable: true, edittype: 'button',
editoptions: {
value: 'Select',
dataEvents: [{
type: 'click',
fn: function (elem) {
var left = (screen.width / 2) - (700 / 2);
var top = (screen.height / 2) - (550 / 2);
var popup = window.open("popup.htm", "popup", "resizable=1,copyhistory=0,menubar=0,width=700,height=550,left='+left+',top='+top");
popup.focus();
}
}]
}
},
//popup window. this page has another jqgrid and an OK button.
$('#btnOK').click(function() {
var person= {
Id: grid.jqGrid('getCell', grid.getGridParam('selrow'), 'Id'),
Name: grid.jqGrid('getCell', grid.getGridParam('selrow'), 'Name'),
Market: grid.jqGrid('getCell', grid.getGridParam('selrow'), 'Market')
};
window.top.opener.parent.Xrm.Page.GetValueFromChild(person); //Error is on this line.
window.close();
});
Your GetValueFromChild is scoped to your ready callback. If it doesn't need to access other scoped functions and variables then simply declare it at the top level instead. If it does need to access them, you need to create a global reference to it in your callback.
Declare at top level:
// This needs to be called from Child window
function GetValueFromChild(person) {
alert(person.Id);
alert(person.Name);
alert(person.Market);
}
Export from scope:
$(document).ready(function () {
// This needs to be called from Child window
function GetValueFromChild(person) {
alert(person.Id);
alert(person.Name);
alert(person.Market);
}
window.GetValueFromChild = GetValueFromChild;
});

CKEditor: Controlling Entermode with a toolbar button

By default, CKEditor's enter key behavior is adding a <p> tag and starting a new paragraph. But that behavior can be modified in the configuration with a .EnterMode parameter.
I'm wondering if there is a way to change Enter key behavior in the runtime, by putting a button into its tool bar, to switch between <p> and <br> (single line vs double line), just like as in Word.
Any ideas on how to do this?
Save the following to editor_dir/plugins/entermode/plugin.js:
'use strict';
(function() {
CKEDITOR.plugins.add( 'entermode', {
icons: 'entermode',
init: function( editor ) {
var enterP = new enterModeCommand( editor, CKEDITOR.ENTER_P );
var enterBR = new enterModeCommand( editor, CKEDITOR.ENTER_BR );
editor.addCommand( 'entermodep', enterP );
editor.addCommand( 'entermodebr', enterBR );
if ( editor.ui.addButton ) {
editor.ui.addButton( 'EnterP', {
label: 'Enter mode P',
command: 'entermodep',
toolbar: 'paragraph,10'
});
editor.ui.addButton( 'EnterBR', {
label: 'Enter mode BR',
command: 'entermodebr',
toolbar: 'paragraph,20'
});
}
editor.on( 'dataReady', function() {
refreshButtons( editor );
});
}
});
function refreshButtons( editor ) {
editor.getCommand( 'entermodep' ).setState(
editor.config.enterMode == CKEDITOR.ENTER_P ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF );
editor.getCommand( 'entermodebr' ).setState(
editor.config.enterMode == CKEDITOR.ENTER_BR ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF );
}
function enterModeCommand( editor, mode ) {
this.mode = mode;
}
enterModeCommand.prototype = {
exec: function( editor ) {
editor.config.enterMode = this.mode;
refreshButtons( editor );
},
refresh: function( editor, path ) {
refreshButtons( editor );
}
};
})();
Now add the following to toolbar.css in your skin file:
.cke_button__enterp_icon, .cke_button__enterbr_icon { display: none !important; }
.cke_button__enterp_label, .cke_button__enterbr_label { display: inline !important; }
...or paint some icons, if you want.
Enable the plugin when running the editor:
CKEDITOR.replace( 'id', { extraPlugins: 'entermode' } );
Now you can control config.enterMode from the toolbar.

Replace the image plugin in CKeditor

I want to override the image plugin in CKeditor. When I right click on an image I want to open my own dialog. Can anyone point me in the right direction. I've done a basic plugin which I copied from the CKeditor site - How do I swap this to replace the image editor.
CKEDITOR.plugins.add('myplugin',
{
init: function (editor) {
editor.addCommand('mydialog', new CKEDITOR.dialogCommand('mydialog'));
if (editor.contextMenu) {
editor.addMenuGroup('mygroup', 10);
editor.addMenuItem('My Dialog',
{
label: 'Open dialog',
command: 'mydialog',
group: 'mygroup'
});
editor.contextMenu.addListener(function (element) {
return { 'My Dialog': CKEDITOR.TRISTATE_OFF };
});
}
CKEDITOR.dialog.add('mydialog', function (api) {
// CKEDITOR.dialog.definition
var dialogDefinition =
{
title: 'Sample dialog',
minWidth: 390,
minHeight: 130,
contents: [
{
id: 'tab1',
label: 'Label',
title: 'Title',
expand: true,
padding: 0,
elements:
[
{
type: 'html',
html: '<p>This is some sample HTML content.</p>'
},
{
type: 'textarea',
id: 'textareaId',
rows: 4,
cols: 40
}
]
}
],
buttons: [CKEDITOR.dialog.okButton, CKEDITOR.dialog.cancelButton],
onOk: function () {
// "this" is now a CKEDITOR.dialog object.
// Accessing dialog elements:
var textareaObj = this.getContentElement('tab1', 'textareaId');
alert("You have entered: " + textareaObj.getValue());
}
};
return dialogDefinition;
});
}
});
Hi the reason I wanted to do this was that we have our image editor control which for "usability" reasons we need to carry on using. It gets used in different bits of the site and two dialogs would confuse people. In summary what I did was
Remove the image plugin CKEDITOR.config.removePlugins = 'image, forms, div,flash,iframe,table';
Add extra plugins extraPlugins: 'tinsertimage,teditimage,teditlink,tinsertlink,teditimagelink' on creating the CKEditor
In the plugin run some JS which intercept the right click on the image
CKEDITOR.plugins.add('teditimage',
{
init: function (editor) {
editor.addCommand('tEditImage',
{
exec: function (editor) {
//This opens the custom editor
ZWSInlineEditor.openImageProperties(editor, false);
}
});
if (editor.addMenuItem) {
// A group menu is required
// order, as second parameter, is not required
editor.addMenuGroup('gImage');
// Create a manu item
editor.addMenuItem('gEditImageItem', {
label: 'Edit Image Properties',
command: 'tEditImage',
group: 'gImage'
});
}
if (editor.contextMenu) {
editor.contextMenu.addListener(function (element, selection) {
// Get elements parent, strong parent first
var parents = element.getParents("img");
// Check if it's strong
if (parents[0].getName() != "img")
return null; // No item
return { gEditImageItem: CKEDITOR.TRISTATE_ON };
});
}
}
});
I don't understand what's the point in what you're doing (or please explain us). Maybe you should rather customize dialogs than do things from scratch?

Sencha Touch, dock panel inside Nested List

I have a Sencha Touch app that has a nested list.
The nestedList automatically creates its own toolBar.
I would like to dock a panel below the toolbar, but above the list-items. And I only need this on the top-level of the list. I am hoping to have it disappear after the first leaf is selected.
Does this sound like something doable? As you can see in my code, I only have the ability to dock an item panel on top of the current toolbar.
Thanks so much in advance. I really appreciate any advice you guys might have.
Al.
Below is what I have so far...
// Menu Pages
var menu = new Ext.NestedList({
fullscreen: true,
title: 'Menu',
displayField: 'text',
store: menu_store,
// ** This is the dockedItem I would like to insert between the toolbar and list-items
dockedItems: [ {
xtype : 'panel',
dock : 'top',
html : '<span>This is the logo panel</span>',
cls : 'front-logo-panel',
flex : 1
}],
// Add Panel for Leaf nodes
getDetailCard: function(item, parent) {
var itemData = item.attributes.record.data,
parentData = parent.attributes.record.data,
detailCard = new Ext.Panel({
scroll: 'vertical',
cls: 'menu-item-panel',
styleHtmlContent : true,
tpl: menuTemplate,
// add button to Leaf Node
listeners: {
activate: function() {
Ext.getCmp('itemToolbar').setTitle('New Title Bar');
}
}
});
detailCard.update(itemData);
this.backButton.setText(parentData.text);
return detailCard;
},
// add template for all nodes
getItemTextTpl: function() {
var tplConstructor =
'<tpl if="newItem">' +
'<span class="list-new-item">New Item!</span>' +
'</tpl>'+
'{text}' +
'<tpl>'+
'<div class="metadata">' +
'{description:ellipsis(40)}' +
'</div>' +
'</tpl>';
return tplConstructor;
}
});
Old question, I know, but to solve this, you can remove the toolbar from the list (without destroying it) and add it to a panel above the list. All nestedList functionality stays the same on the toolbar. Here's the solution I have:
First, I created a view that extends from NestedList and contains a toolbar:
Ext.define('MyApp.view.DynamicList', {
extend: 'Ext.dataview.NestedList',
alias: 'widget.dynamiclist',
config: {
toolbar: {
xtype: 'toolbar',
docked: 'top',
itemId: 'header-bar',
layout: {
pack: 'end',
type: 'hbox'
},
items: [
{
xtype: 'spacer'
},
{
xtype: 'button',
itemId: 'show-nav-sheet-button',
ui: 'plain',
width: 45,
iconCls: 'more'
}
]
}
}
});
Next, I created a main panel with a vbox layout that contains a child panel and this toolbar:
Ext.define('MyApp.view.MainContainer', {
extend: 'Ext.Container',
requires: [
'MyApp.view.DynamicList'
],
config: {
id: 'main-container',
layout: {
type: 'vbox'
},
items: [
{
xtype: 'panel',
flex: 1,
itemId: 'info-container'
},
{
xtype: 'dynamiclist',
flex: 1
}
]
}
});
Then, in a controller, I listen for the initialize event of the nested list. When it's fired, I remove the toolbar from the nested list and add it to the panel.
onNestedListInitialize: function() {
// need to wait until everythin is initialized;
var me = this;
var renderFn = function renderPanels() {
var main = me.getMainContainer();
// wait until main is intialized;
if(!main) {
Ext.defer(renderFn, 50, this);
return;
}
var list = main.down('#my-list');
var infocont = main.down('#info-container');
// wait until the container's components are initialized
if(!list || !infocont) {
Ext.defer(renderFn, 50, this);
return;
}
// remove the toolbar from the list, and add it to the container.
var toolbar = list.down('#header-bar');
list.remove(toolbar, false);
infocont.add(toolbar);
}
// call the function for the first time.
renderFn();
}
Note, I had to add a few checks to make sure the components were correctly initialized before using them, but the heart of it comes to the list.remove(toolbar, false) followed by the infocont.add(toolbar) commands. The false flag in the .remove() method means that the item won't be destroyed, so it's available to be re-added to the panel.

Resources