I want to add a context menu on right click for various elements on my geojson layer (I'm doing a road map so on a right click on the road at any part I want to show the context menu).
I've managed to get the left click working fine by using the onEachFeature and doing the following
function onEachFeature(feature, layer) {
layer.on({
click: showAssetInfo,
contextmenu: contextreg
});
}
function showAssetInfo(e) {
AssetMouseClick(e.target.feature.properties.objectid, e.latlng);
}
For the context menu I have followed the example here . The context menu library is found here
I have the following that gets called on the document ready (jquery)
$.contextMenu({
selector: 'path.leaflet-clickable',
zIndex: 99999,
callback: function (key, options) {
var m = "clicked: " + key;
window.console && console.log(m) || alert(m);
},
items: {
"edit": { name: "Edit", icon: "edit" },
"cut": { name: "Cut", icon: "cut" },
"copy": { name: "Copy", icon: "copy" },
"paste": { name: "Paste", icon: "paste" },
"delete": { name: "Delete", icon: "delete" },
"sep1": "---------",
"quit": { name: "Quit", icon: "quit" }
}
});
I've tested it and the selector does return the GeoJson features, also if it attach the same menu to something else it works correctly.
Is there something I am missing here?
Also is there a good way to pass in the objectid to the menu when it starts up so I can use it when calling the different options of the menu
EDIT:
I have created this fiddle to demonstrate http://jsfiddle.net/Q3L4c/22/
There is a good leaflet plugin for context menu that was created in Aug 2013:
Leaflet.contextmenu
This context menu library has great documentation including step-by-step instructions for implementation in GeoJSON layers.
In the following code snippet, notice how we can easily pass through the full feature and layer objects to the function that is called when the edit menu item is selected. In this example the layer group is a GeoJSON layer group, the GeoJSON properties can be accessed via feature.properties
NOTE: In this solution content menu item definitions are generated during the onEachFeature processing, not dynamically when the context menu is invoked, just something to be aware of if your were planning on dynamic menu item generation which might be dependent on variables that could change at run time, you need to evaluate the visibility or enabled option for each item as a static value when you create the menu item.
function onEachFeature(feature, layer) {
layer.bindContextMenu({
contextmenu: true,
contextmenuInheritItems: false,
contextmenuItems: [
{ text: 'edit', icon: 'edit', callback: function () { editFeature(feature, layer); } },
{ text: 'cut', icon: cut', callback: function () { console.log('cut'); } },
{ text: 'copy', icon: 'copy', callback: function () { console.log('copy'); } },
{ text: 'paste', icon: 'paste', callback: function () { console.log('paste'); } },
{ text: 'delete', icon: 'delete', callback: function () { console.log('delete'); } },
{ separator: true },
{ text: 'quit', icon: 'quit', callback: function () { console.log('quit'); } },
]
});
layer.on({
click: showAssetInfo
});
}
/**
* Edit a feature on the map
* #param {GeoJSON} feature GeoJSON feature, access metadata through feature.properties
* #param {any} layer Leaflet layer represents this feature on the map (the shape)
*/
function editFeature(feature, layer) {
console.log(JSON.stringify(feature.properties));
}
function showAssetInfo(e) {
AssetMouseClick(e.target.feature.properties.objectid, e.latlng);
}
Related
I have a listener for 'select-current-project' in my Main process. It works fine when triggered from the renderer process, but how can I emit the same event from the Menu?
Menu is created in default createWindow()
var menu = Menu.buildFromTemplate([
{
label: 'Menu',
submenu: [
{
label:'Open',
click() {
// neither of these works
// app.emit('select-current-project')
// ipcRenderer.send('select-current-project')
},
accelerator: 'CmdOrCtrl+O'
},
{
label:'Exit',
click() {
app.quit()
}
},
]
}
])
My event handler
ipcMain.on('select-current-project', async (event, arg) => {
// code
})
I'm not sure I understand the issue you are describing – but here is what I do:
The function showProjectPicker exists in main.js and is called by a menu action as shown below. If I want to call it from the renderer process I send a message over IPC.
{
label: 'File',
submenu: [
{ label: 'Open Project...', click: () => { showProjectPicker(); }, accelerator: 'CmdOrCtrl+o' }
]
}
I am new to the Tabulator plug-in and I am attempting to copy data from one table to another using the Tabulator copyToClipboard method but with no success.
In my application I have created eleven <div> elements (one for the [Crew Leader] and one each for up to ten [Crew Members]) to serve as containers for the Tabulator tables to be instantiated. I am hoping to copy data from the [Crew Leader] table and paste it into each of the affected [Crew Member] tables thus mitigating data re-entry. This sequence of copy/paste events is triggered by the click event bound to a <button> in the header of the [Crew Leader] table. The following function is called by the <button> click event:
function CloneTable() {
// Verify the [Crew Leader] Tabulator table is present....
var tableLeader = Tabulator.prototype.findTable("#CrewLeaderTable");
if (tableLeader.length > 0) {
alert("The Tabulator table #CrewLeaderTable was found.\ntable.length = " + tableLeader.length);
tableLeader.copyToClipboard("all");
alert("The table contents were copied to the clipboard.");
}
else {
alert("The Tabulator table #CrewLeaderTable was not found.");
}
}
The first alert message verifies that the #CrewLeaderTable object has been found as anticipated. However, the second alert verification is never received thus indicating failure of the Tabulator copyToClipboard method.
I have read through as much of the relevant Tabulator documentation as I can find and I am hoping I have simply overlooked something in my setup.
The following is a copy of my Tabulator constructor:
var table = new Tabulator(divid, {
height: "100%",
layout: "fitDataFill",
movableRows: true, //enable user movable rows
tabEndNewRow: true, //create empty new row on tab
rowContextMenu: myActionContextMenu,
keybindings: {
"navUp": true, //enable navUp keybinding using the "up arrow" key
"navDown": true, //enable navDown keybinding using the "down arrow" key
},
columns: [
{ title: "Phase Code", field: "phaseCode", width: 144, editor: "select", editorParams: { values: function (cell) { return window.laborPhaseCodes; } } },
{ title: "Date Worked", field: "dateComp", hozAlign: "center", sorter: "date", editor: dateEditor },
{ title: "Start Time", field: "timeStart", hozAlign: "center", sorter: "time", editor: timeEditor },
{ title: "Finish Time", field: "timeFinish", hozAlign: "center", sorter: "time", editor: timeEditor },
{ title: "Memo", field: "memo", width: 144, hozAlign: "left", editor: "input" },
{ title: "<button type='button' id='btnClone' class='btn btn-success btn-sm py-0' style='font-size:10px;'>Clone</button>", headerSort: false, headerClick: tabCloneTable }
],
cellEdited: function (cell) {
}
});
I have spent a couple of days trying to figure out the best way to "clone" the data from one table into another. The Tabulator documentation is fairly comprehensive but I fear I have overlooked something. Any assistance is greatly appreciated.
It looks like copyToClipboard doesn't return the data, it is maintained internally and not accessible. But, with what you are doing set/getData works fine.
Here is an example, https://jsfiddle.net/nrayburn/19sjg74k/7/.
Basically, what you want to do is call getData on the parent table and setData on the child table.
const crewLeaderTable = Tabulator.prototype.findTable('#CrewLeaderTable')[0];
const crewMemberTable = Tabulator.prototype.findTable('#CrewMember1Table')[0];
const crewLeaderData = crewLeaderTable.getData();
// You could also use replaceData or addData, depending on the requirements
crewMemberTable.setData(crewLeaderData);
I am a 100% newb to Sencha and am trying to take a stab at re-factoring my company's mobile app.
Here is my app.js:
Ext.application({
name: 'RecruitTalkTouch',
views: ['Login'],
launch: function () {
Ext.Viewport.add([
{ xtype: 'loginview' }
]);
}
});
Login.js View:
Ext.define('RecruitTalkTouch.view.Login', {
extend: 'Ext.Container',
alias: "widget.loginview",
xtype: 'loginForm',
id: 'loginForm',
requires: ['Ext.form.FieldSet', 'Ext.form.Password', 'Ext.Label', 'Ext.Button' ],
config: {
title: 'Login',
items: [
{
xtype: 'label',
html: 'Login failed. Please enter the correct credentials.',
itemId: 'signInFailedLabel',
hidden: true,
hideAnimation: 'fadeOut',
showAnimation: 'fadeIn',
style: 'color:#990000;margin:5px 0px;'
},
{
xtype: 'fieldset',
title: 'Login Example',
items: [
{
xtype: 'textfield',
placeHolder: 'Email',
itemId: 'userNameTextField',
name: 'userNameTextField',
required: true
},
{
xtype: 'passwordfield',
placeHolder: 'Password',
itemId: 'passwordTextField',
name: 'passwordTextField',
required: true
}
]
},
{
xtype: 'button',
itemId: 'logInButton',
ui: 'action',
padding: '10px',
text: 'Log In'
}
]
}
});
Login.js Controller:
Ext.define('RecruitTalkTouch.controller.Login', {
extend: 'Ext.app.Controller',
config: {
refs: {
loginForm: 'loginForm'
},
control: {
'#logInButton': {
tap: 'onSignInCommand'
}
}
},
onSignInCommand: function(){
console.log("HELLO WORLD");
}
});
When I click the submit button, nothing happens. How can I hook up my submit button to listen for events (click, tap, etc) along with submitting the information to a backend API?
In app.js file of your application, add:
controllers: [
'Login'
]
in your application class. And for submitting information, call a Ajax request like this:
Ext.Ajax.request({
url: // api url..,
method: 'POST',
params: {
username: // get user name from form and put here,
password: // get password and ...
},
success: function(response) {
do something...
},
failure: function(err) {do ..}
});
from inside onSignInCommand() function.
You must activate your controller by adding it to the controllers option of your application class.
Then, to submit your data to the backend, you've got several options. You can use a form panel instead of your raw container, and use its submit method. Alternatively, you can use the Ext.Ajax singleton. In this case, you'll have to build the payload yourself. Finally, you can create a model with a configured proxy, and use its save method. This last way is probably the best for long term maintainability... Even if in the case of a simple login form, that may be a little bit overkill.
Can u please refer this sample app to create login form. Its very simple app please go through it.
http://miamicoder.com/2012/adding-a-login-screen-to-a-sencha-touch-application/
MY sencha touch application is working fine in all browsers, however when I save the url to the iPad home screen. It will not load and only shows a blank screen. I get no JS errors and nothing comes through the log when debugging. Heres a sample of the app:
script type="text/javascript">
var rootPanel;
if (navigator.userAgent.match(/iPad/i)) {
viewport = document.querySelector("meta[name=viewport]");
viewport.setAttribute('content', 'width=980');
}
Ext.application({
launch: function () {
var contactForm = Ext.create('Ext.form.FormPanel', {
standardSubmit: true,
fullscreen: true,
items: [{
xtype: 'titlebar',
title: 'My App',
docked: 'top'
}, {
xtype: 'fieldset',
items: [{
xtype: 'textfield',
name: 'LoginName',
label: 'Login Name:'
}, {
xtype: 'passwordfield',
name: 'Password',
label: 'Password:'
},
{
xtype: 'hiddenfield',
name: 'ReturnUrl',
value: '/returnUser.html'
}] // items
}, {
xtype: 'toolbar',
layout: {
pack: 'center'
}, // layout
ui: 'plain',
items: [{
xtype: 'button',
text: 'Reset',
ui: 'decline',
handler: function (btn, evt) {
Ext.Msg.confirm('', 'Are you sure you want to reset this form?', function (btn) {
if (btn === 'yes') {
contactForm.setValues({
LoginName: '',
Password: ''
}); // contactForm()
} // switch
}); // confirm()
}
}, {
xtype: 'button',
text: 'Submit',
ui: 'confirm',
handler: function (btn, evt) {
var values = contactForm.getValues();
contactForm.submit({
url: 'Login',
method: 'POST',
waitTitle: 'Connecting',
waitMsg: 'Sending data...',
success: function (form, result) {
Ext.Msg.alert('Login succeeded!', result.response.reason);
},
failure: function (form, result) {
Ext.Msg.alert('Login Failed!', result.response.reason);
}
});
} // handler
}] // items (toolbar)
}] // items (formpanel)
}); // create()
} // launch
}); // application()
$(document).ready(function () {
});
I put an alert in the launch method of Ext.Application but it does not show. When I put it an alert in the document.ready function it does show. I should also note it DOES work on the ipad browser, just not when launched from the icon on the homescreen.
i faced a similar issue in android actually in my case the problem was because of Ext.Loader not enabled I see you have not included it either. Include this script before Ext.application & see if it works
Ext.Loader.setConfig({
enabled:true
});
Ext.application({...});
It appears to be the version of sencha I was using which was 2.1.0 I believe, as soon as I updated to the latest(2.1.1 Build Date 2013-02-05 12:25:50 ) I works fine.
I am implementing a project picker for a Rally custom app and would like to select a projects children automatically when the parent is selected from the picker. I was able to get the ObjectID and Name of the objects I want to select but can't seem to get them to be selected from the picker. I attempted this using the "fireEvent" method but had no success. Here's what I have so far:
var teamPick = this.down('#filterPanel').add({
xtype: 'rallymultiobjectpicker',
id: 'teams',
modelType: 'project',
fieldLabel: 'Teams',
listeners: {
select: function(field, selected) {
Ext.create('Rally.data.WsapiDataStore', {
autoLoad: true,
fetch: [ 'Name', 'ObjectID' ],
filters: [
{ property: 'Parent.ObjectID', value: selected.ObjectID }
],
model: 'Project',
listeners: {
load: function(store, data) {
Ext.Array.each(data, function(child) {
console.log(child.get('Name')); //Logs the child name
});
}
}
});
},
scope: this
}
});
Are you using 2.0p3? There was a known issue with events not being correctly fired in the MultiObjectPicker. This should be resolved in 2.0p4. I ran your code in a 2.0p4 app and it functioned as expected.
As a side note your child project query can be written like this as well:
filters: [
{ property: 'Parent', value: '/project/' + selected.ObjectID }
]
The 2.0p4 version of the component also added a new event called selectionchange which gives you an array of the currently selected values (since it is a multi select picker). There are individual select and deselect events that fire when a specific item is selected/deselected.
I was able to accomplish this without the use of the fireEvent method. Instead, I used the getValue and setValue methods and added the child projects to the state manually:
this.down('#filters').add({
xtype: 'rallymultiobjectpicker',
id: 'teams',
modelType: 'project',
listeners: {
blur: function() { this.down('#teams').collapse(); },
select: function(field, selected) {
Ext.create('Rally.data.WsapiDataStore', {
autoLoad: true,
fetch: [ 'Name', 'ObjectID' ],
filters: [
{ property: 'Parent.ObjectID', value: selected.ObjectID }
],
model: 'Project',
listeners: {
load: function(store, data) {
var selected = this.down('#teams').getValue();
Ext.Array.each(data, function(child) {
selected.push(child.data);
});
this.down('#teams').setValue(selected);
},
scope: this
}
});
}
scope: this
}
});