How do I know which element was clicked in context menus? - javascript

We develop extensions for Chrome, Firefox and Safari. We want to add context menus to our extensions that will show when right clicking on any form element which is editable. I tried to add an editable context menu to Chrome:
chrome.contextMenus.create({
"title": "Test editable menu item",
"contexts": ["editable"],
"onclick": function(info, tab) {
console.log("item " + info.menuItemId + " was clicked");
console.log("info: " + JSON.stringify(info));
console.log("tab: " + JSON.stringify(tab));
}
});
But I need to know which element the user clicked on, and info and tab don't contain the element. How do I know which element the user clicked? I would like to have a jQuery object containing the element.
The info object contains the following attributes:
"editable": true
"menuItemId"
"pageUrl"

One of the best workarounds I know of is to follow the advice given in this thread to use content scripts to inject a listener in the target page for the 'contextmenu' event.

I know that is to late for you but I answer here for anyone else who's google it.
My solution was to create a mapping between created menu items and the business model (in this case a "data" array):
var itemsDic = {};
function onClickHandler(info) {
alert(itemsDic[info.menuItemId]);
};
for(i in data) {
var currentItem = chrome.contextMenus.create({
parentId: item,
title: data[i].ItemName,
type: data[i].ItemType,
contexts: ["editable"],
onclick : onClickHandler
});
itemsDic[currentItem] = data[i];
}

Related

Extjs 5.1 Dynamic addition of container to panel

What i am trying to do is dynamically add container to panel on click of button.
1st instance of container gets added and can be seen in the panel.items.length
2nd instance onwards the panel.items.length doesn't change. but the panel can be seen in dom and on screen.
Just wanted to know why the panel.items.length is not increasing. Is it a bug?
Fiddler link https://fiddle.sencha.com/#fiddle/p3u
Check for the line :
console.log(qitems);
below debugger; it is set to questionsblock.items.length that i am talking about.
Remove the itemId from QuestionTemplate and remove renderTo from the new instance.
Your click handler should look like this:
listeners: {
'click': function(button) {
var questionPanel = button.up('form').down('#questionsblock'),
qitems = questionPanel.items.length,
questiontemplate = Ext.create('QuestionTemplate', {
qid: qitems,
questiontype: 'text'
});
console.log(qitems);
questionPanel.add(questiontemplate);
questionPanel.doLayout();
}
}
Check this fiddle: https://fiddle.sencha.com/#fiddle/p47

Firefox Extension: Context Menu Item

I'm trying to develop a simple Firefox extension. I want the user to right click and the extension to save what element was clicked on (paragraph, image, etc.) in a variable. Then there will be a context menu item "Item A". When the user clicks on "Item A", it will call a function which will take into consideration which element the user has right clicked on.
This is the only code I have so far for the Menu Item:
var contextMenu = require("sdk/context-menu");
var menuItem = contextMenu.Item({
label: "Menu Item A",
contentScript: 'self.on("click", function () {'
+ 'Do something'
+ '});'
});
Thank you!
var contextMenu = require("sdk/context-menu");
var menuItem = contextMenu.Item({
label: "Menu Item A",
contentScript: 'self.on("click", function (node) {console.log("node is = ",node);});'
});
you were basically there, see the node argument in function, it console.logs it on click, so go to browser console and check the message there for details on what node is

Extjs 4.1.1a Check symbol of Checkbox on grid panel doesn't work

on a tab panel I create a tab for each year I have in a database (in this case the database contains at the moment only 3 years: 2012, 2013 ans 2014) and finally I set as active tab the current year (2013). In the controller I do the following:
var tp= this.getTpOverview();
this.getPlannedYearsStore().load({
callback: function(records) {
for (i=0; i< records.length; i++){
var year = records[i].data.year;
var tab = tp.add({
title: year,
year: year,
layout:'fit',
listeners: {
activate: function() {
var tbOverview = Ext.getCmp('tabOverview-'+ this.year);
if (!tbOverview) {
var gridOverview = Ext.create('WLPT.view.CPAssMonthActHours', {
id: 'tabOverview-' + this.year,
year: this.year,
xtype: 'cpassmonthacthoursview',
autoScroll: true
});
this.add(gridOverview);
} else {
selectedYear = this.year;
tbOverview.getStore().load({
params : {
wrk_year: selectedYear
}
});
}
}
}
});
if (currentYear == parseInt(records[i].data.year)) {
tab2Activate = tab;
}
}
tp.setActiveTab(tab2Activate);
}
});
When I run the application this seams to work fine.
I forgot to say that each tab contains a grid panel with a check column (Checkbox model) and for each item (row) a cell editor is setted on selected cells.
The active tab (2013) works fine. I can check the checkboxes to perfom a sum of the selected items. Indeed, the cell editor works fine.
The problem appears when I change the tab. The corresponding grid comes with the checkbox column. But on the javascript console appears the following error message:
Uncaught TypeError: Cannot call method 'setWidth' of undefined ext-all-debug.js:95689
Ext.define.onColumnResize ext-all-debug.js:95689
Ext.define.onColumnResize ext-all-debug.js:101362
Ext.util.Event.Ext.extend.fire ext-all-debug.js:8896
Ext.define.continueFireEvent ext-all-debug.js:9102
Ext.define.fireEvent ext-all-debug.js:9080
Ext.override.fireEvent ext-all-debug.js:51104
Ext.define.onHeaderResize ext-all-debug.js:97344
Ext.define.afterComponentLayout ext-all-debug.js:98063
Ext.define.notifyOwner ext-all-debug.js:28381
Ext.define.callLayout ext-all-debug.js:103511
Ext.define.flushLayouts ext-all-debug.js:103680
Ext.define.runComplete ext-all-debug.js:104194
callOverrideParent ext-all-debug.js:54
Base.implement.callParent ext-all-debug.js:3813
Ext.override.runComplete ext-all-debug.js:21234
Ext.define.run ext-all-debug.js:104175
Ext.define.statics.flushLayouts ext-all-debug.js:21238
Ext.define.statics.resumeLayouts ext-all-debug.js:21246
Ext.resumeLayouts ext-all-debug.js:23343
Ext.define.setActiveTab ext-all-debug.js:111589
Ext.define.onClick ext-all-debug.js:111357
(anonymous function)
Ext.apply.createListenerWrap.wrap
Despite that, the grid is shown correctly. But, when I select a item the javascript console shows the following error message:
Uncaught TypeError: Cannot call method 'up' of null ext-all-debug.js:99591
Ext.define.onRowFocus ext-all-debug.js:99591
Ext.util.Event.Ext.extend.fire ext-all-debug.js:8896
Ext.define.continueFireEvent ext-all-debug.js:9102
Ext.define.fireEvent ext-all-debug.js:9080
Ext.override.fireEvent ext-all-debug.js:51104
Ext.define.focusRow ext-all-debug.js:92462
Ext.define.onRowFocus ext-all-debug.js:92423
Ext.define.onLastFocusChanged ext-all-debug.js:109495
Ext.define.setLastFocused ext-all-debug.js:83855
Ext.define.doMultiSelect ext-all-debug.js:83761
Ext.define.doSelect ext-all-debug.js:83721
Ext.define.selectWithEvent ext-all-debug.js:83623
Ext.define.onRowMouseDown ext-all-debug.js:109750
Ext.util.Event.Ext.extend.fire ext-all-debug.js:8896
Ext.define.continueFireEvent ext-all-debug.js:9102
Ext.define.fireEvent ext-all-debug.js:9080
Ext.override.fireEvent ext-all-debug.js:51104
Ext.define.processUIEvent ext-all-debug.js:85315
Ext.define.handleEvent ext-all-debug.js:85227
(anonymous function)
Ext.apply.createListenerWrap.wrap
The selection on the item fires the event 'select' and 'deselect' when I click a second time. But the check symbol on the checkbox doesn't work any time.
I have thougth to put this symbol manually on the events 'select' and 'deselect' as a workaround, but I don't know how to put this style and which one is.
Do you have any ideas? Look forward for your suggestions. Thank you in advance.
Manuel
I think, the errors are not related to the code you posted. In fact, your code does not set the width, nor does it call up.
I find your code convoluted: a callback with a listener inside, that creates a view inside. And I don't understand if your code is inside a controller or another class.
Here is a problem:
var tab = tp.add({
//xtype is missing
title: year,
For debugging, I can giv you the following recommendation:
Use ext-dev.js instead of ext-all-debug.js. This will load all required classes one after the other, and the errors in the backtrace are not all inside ext-all-debug.js, but each line shows the line in the source class with all comments in it.
To get a cleaner programming style, try to follow the MVC pattern strictly:
Folder structure as recommended
Define events in the controller, like
init: function(){
this.listen({
store: {
'#plannedYearsStore': {load: this.onPlannedYearsStoreLoad}
}
})
this.control({
'tab': {activate: this.onTabActivate}
})
},
onPlannedYearsStoreLoad: function (store, records){
for (i=0; i< records.length; i++){
var year = records[i].data.year;
var tab = tp.add({
...
},
onTabActivate: function (){
var tbOverview = Ext.getCmp('tabOverview-'+ this.year);
...
},
If possible, define your tab in a view class in a separate file.
When you adhere striclty to this MVC structure, you will get a much easier maintainable code.

Google Chrome Omnibox API -- automatically select first option on enter

So I'm trying to build a simple Omnibox extension for Chrome for personal use. It works like any other Omnibox extension: you enter the extension keyword and press tab, which gives the extension control of the omnibox. Then you type in a phrase or whatnot and a list of suggestions pop up below the omnibox. Then you can use the arrow keys or mouse to select a suggestion and then the browser navigates to the page associated with that suggestion. All of that works perfectly fine.
However, what I'd like it to do is that when I press enter in without having selected a suggestion, I'd like the browser to go to the first suggestion from the suggestion list. Instead what happens right now, I get this error page:
I couldn't find any answers in the documentation on this. This is what my code looks like right now (in background.js):
chrome.omnibox.onInputChanged.addListener(
function(text, suggest)
{
text = text.replace(" ", "");
suggest([
{ content: "http://reddit.com/r/" + text, description: "reddit.com/r/" + text },
{ content: "http://imgur.com/r/" + text, description: "imgur.com/r/" + text }
]);
}
);
chrome.omnibox.onInputEntered.addListener(
function(text)
{
chrome.tabs.getSelected(null, function(tab)
{
chrome.tabs.update(tab.id, {url: text});
});
}
);
chrome.omnibox.setDefaultSuggestion({ description: "visit /r/%s" });
So is there a way of setting the default action when the enter is pressed without a suggestion being selected? Sort of like the custom search functionality works by default in the Chrome omnibox?
Within chrome.omnibox.onInputChanged.addListener(), you'll want to call chrome.omnibox.setDefaultSuggestion().
So when you type something in the Omnibox, you'll want to make the first suggestion become the default suggestion (so you don't have to press the Down Arrow), and then suggest() any remaining suggestions like normal.
Example:
chrome.omnibox.onInputChanged.addListener(
function(text, suggest)
{
text = text.replace(" ", "");
// Add suggestions to an array
var suggestions = [];
suggestions.push({ content: "http://reddit.com/r/" + text, description: "reddit.com/r/" + text });
suggestions.push({ content: "http://imgur.com/r/" + text, description: "imgur.com/r/" + text });
// Set first suggestion as the default suggestion
chrome.omnibox.setDefaultSuggestion({description:suggestions[0].description});
// Remove the first suggestion from the array since we just suggested it
suggestions.shift();
// Suggest the remaining suggestions
suggest(suggestions);
}
);
chrome.omnibox.onInputEntered.addListener(
function(text)
{
chrome.tabs.getSelected(null, function(tab)
{
var url;
if (text.substr(0, 7) == 'http://') {
url = text;
// If text does not look like a URL, user probably selected the default suggestion, eg reddit.com for your example
} else {
url = 'http://reddit.com/r/' + text;
}
chrome.tabs.update(tab.id, {url: url});
});
}
);

Sencha Touch - deselect list item?

I'm working on a Sencha Touch application, and have a list of contacts. When a list item is tapped, an ActionSheet is displayed showing some basic functions (such as call, delete and ignore). Unfortunately, when the user taps and the ActionSheet is fired, the List item remains selected underneath the overlay (see the screenshot below):
Here's the function bound to the itemTap event:
itemTap: function(list, index)
{
// Deselect the selected record:
var currentRecord = list.getStore().getAt(index);
currentRecord.forename = currentRecord.get('forename');
currentRecord.surname = currentRecord.get('surname');
currentRecord.phoneNumber = currentRecord.get('phoneNumber');
currentRecord.shortFullName = currentRecord.forename + ' ' + currentRecord.surname[0];
list.getStore().deselect(index, true);
callButton.setText('Call ' + currentRecord.shortFullName + ' (' + currentRecord.phoneNumber + ')');
unfriendButton.setText('Remove ' + currentRecord.shortFullName + ' as friend');
friendActionSheet.show();
}
Unfortunately, list.getStore().deselect(index, true) returns the following error: Object [object Object] has no method 'deselect'
Any ideas on what I could be doing wrong, or how I can achieve this?
This works for me:
listeners: {
itemtap: function(dv, ix, item, e) {
// Clear the selection soon
setTimeout(function(){dv.deselect(ix);},500);
}
}
In Sencha Touch 2, use disableSelection: true, while creating a list
Ext.define('App.view.NewsList',{
extend: 'Ext.List',
xtype: NEWS_LIST,
config: {
store: NEWS_FEED,
//deselectOnContainerClick: true,// not working in Sencha Touch 2
disableSelection: true, // since Sencha Touch 2
itemTpl: '{heading}'
}
});
If you want to clear the whole list:
var selModel = app.views.notesList.deselect(app.views.notesList.getSelectedRecords());
setTimeout is really not a good solution here. It should be like this:
listeners: {
itemtap: function(list, ix, item, e) {
// Clear the selection soon
list.deselect(list.getSelectedRecords());
}
}
I haven't tried to recreate your problem but you may want to try:
list.deselect(currentRecord, true);
After you do that you may have to call
doLayout()
or
doComponentLayout()
to refresh the view.
This drove me INSANE.
While the approved answer will work, its worth noting that you can do it with a delay(like nested list does too) like this:
var selModel = app.views.VideosList.items.items[0].getSelectionModel();
Ext.defer(selModel.deselectAll, 200, selModel);
I put that in my controller (so its called when the view changes), where app.views.VideosList is my main panel and app.views.VideosList.items.items[0] is the list in that panel.
this did it for me (sencha touch 2.3):
list = Ext.Viewport.down('nestedlist');
list.getActiveItem().deselectAll();

Categories