chrome.contextMenus.create with dynamic items - google-chrome

I want to build a chrome extension that has a menu with some items based on what you click on.
i use chrome.runtime.onConnectExternal to pass the date, everything works fine in here. but as the messaging between extension and site is done async some time the events come after the menu gets shown. and it dose not update after that.
the end result is that some times you see the menu based on the old item that was right clicked.
Is there a way to refresh the menu while open. or a way to comunicate between site and extension in a sync way?
Here is a example showing menu not updating:
const test = chrome.contextMenus.create({
'title': `menu 0`,
"contexts": ['all'],
});
let index = 0;
setInterval(() => {
chrome.contextMenus.update(test, {title: 'menu ' + index++})
}, 1000);

Related

Scroll to List Item on Unordered List after new list item is added through mutation

I have data for a list that is coming from an apollo query. The query fetches all of the data and the ul is used to display the list. Ideally, I have a button that adds a new item to the end of the list and once that button is pressed and the new item added, I want to scroll to the item on the list. My code is as follows.
const { data } = useQuery(getData);
<ul id="itemList">
{data.map(item=> <li key={item.id} id={item.id}>{item.title}</li> )
</ul>
Somewhere else on the page, I have a button you can click to use the apollo mutation hook which adds a new item to the list and refetches the getData query.
const [createListItem, { loading, error }] = useMutation(createItem);
const resp = await createListItem({variables: {details: {title: "New Item"}}, refetchQueries: [{query: getData}]
I assumed once this was done and the item is added to the list (which I can see visibly), I can use the following code below to scroll to the item on my list programitically. Id is automatically added by my DB once this item is added to the backend DB (MongoDB).
const listItem = document.getElementById(resp.data.createListItem.id);
listItem?.scrollIntoView({ behavior: "smooth" });
The listItem variable shows null. This is most likely due to the DOM not refreshing before I try to scroll to the item. If I hardcode an id that already exists (besides my newly created one), the auto scroll works.
How can I get the li document for the newly created item once added and query refetches and then scroll to it? Is there an "onchange" event or something like that I can listen for using addEventListener to search for my newly created item on the list and then scroll to it?
Thanks
I figured it out. Thanks for the componentDidUpdate suggestion. I did this using React Hooks (useEffect and useState) .
To reference my original question above, once I add the item using the mutation hook, I store the id of the newly added item in state
const [addedItem, updateAddedItem] = useState("")
So to reference code in question above.
const resp = await createListItem({variables: {details: {title: "New Item"}}, refetchQueries: [{query: getData}]
updateAddedItem(resp.data.createListItem.id)
In the component where I am rendering my list, I use the useEffect hook.
useEffect(() => {
const listItem = document.getElementById(addedItem);
listItem?.scrollIntoView({ behavior: "smooth" });
}
}
}, [data]);
This way, when the data is updated, the list item is available in the DOM to scroll to.

chrome extension refresh two tab simultaneously

I should write a chrome extension than can refresh two special tabs simultaneously when I click the extension icon. but I just find the code:
chrome.browserAction.onClicked.addListener(function(tab))
the function(tab) can not push two tabs but only one. How can I do it?
Well to refresh a tab, you only need tab id.So, you can use chrome.tabs.reload() on any number of tabs you like.
Example:
chrome.browserAction.onClicked.addListener(function(){
chrome.tabs.query({currentWindow: true},function(tabs){// This will return all tabs in current window
//If you want to reload first 2 tabs
chrome.tabs.reload(tabs[0].id);
chrome.tabs.reload(tabs[1].id);
})
})
Lets say if you want to reload current active tab and the tab left to it. Then pass active:true along with currentWindow:true to get active tab. Then use index property to reload left or right tab.
Example:
chrome.browserAction.onClicked.addListener(function(){
chrome.tabs.query({active:true,currentWindow: true},function(tabs){
var currentIndex = tabs[0].index;
var leftIndex = tabs[0].index - 1;
chrome.tabs.query({currentWindow: true},function(tabs){// This will return all tabs in current window
chrome.tabs.reload(tabs[currentIndex].id);
chrome.tabs.reload(tabs[leftIndex].id);
});
})
})

Map json to menu in Openui5

In w2ui I can map a json to a sidebar http://w2ui.com/web/demos/#!sidebar/sidebar-1
Can I do it in openui5?
I want the same result.
Obviously I do not want a tree but a list of items that swipe right if I tap on an item (and visualize a sub-menu list) and slide left if I press back button (and visualize the menu at upper level).
I think it's possible, but as far as I know you have to do some manual labor:
Detect whether your node has one or more child nodes, and based on that set the sap.m.ListType to Navigation or not
If your root node (f.i., "/items") has child nodes (f.i., "childs"), you need to re-bind your list to this child path ("/items/<index_of_parent_node>/childs)
To get the swiping effect, you probably need to encapsulate the list in a sap.m.Page
Depending on the node level you're in, you need to hide/display your back button, and by pressing it bind your list to the parent path
However, if there's a cleaner, simpler approach I would love to hear it too!
I solved my problem:
Every time that i click on a menu item i call this function into view controller:
//when click on item
onPressMenuItem: function(evt) {
var selectedItem=evt.getSource().getBindingContext().getObject();
var objAction=getActionWhenPressMenuItem(selectedItem, this.getView().getModel());
console.log(objAction);
if(objAction.hasNextSidebar==true){ // sub menu
var model = new sap.ui.model.json.JSONModel();
model.setData(objAction.nextSidebar);
var oSplitApp=sap.ui.core.Core().byId("splitApp");
var nextView = sap.ui.xmlview("general.master.menuMaster");
nextView.setModel(model);
nextView.byId("idPageSidebar").setTitle(selectedItem.text);
oSplitApp.addMasterPage(nextView);
oSplitApp.toMaster(nextView);
}else{ // open operation detail
var idDetail =objAction.opDetail;
var targetApp = getAppBySelectionId(idDetail);
if(targetApp.masterView!=null){//if app has own master
sap.ui.getCore().getEventBus().publish("navMaster", "to", {
idView: targetApp.masterView
});
}
if(targetApp.detailView!=null){//if app has own detail
sap.ui.getCore().getEventBus().publish("navDetail", "to", {
//titleOfDetailPage: selectedItem.text,
idView: targetApp.detailView,
//idCall: selectedItem
});
}
}
},
I create every time a new istance of the menu on a new page.

Titanium tabs accumulating when opening new windows

I have a list of courses in rows like this:
Whenever I click a row, a new tab is created, and a new window is added to that tab showing the course info.
Then if I press back, it goes back to the courses window, which is great, but when I click another course it adds that to the list of tabs, so it starts looking like this:
Whereas, there should only be two tabs here, the Courses tab and Get Courses tab.
In get_courses.js (the file that deals with making the rows) I have this event listener which creates a new tab every time a row is clicked (which I'm sure is where my mistake is, I'm just not sure how to fix it):
table.addEventListener("click",function(e){
var courseInfo_window = Titanium.UI.createWindow({
title:e.rowData.title,
url:'get_courseInfo.js',
courseIMISCode: e.rowData.courseIMISCode
});
var courseInfo_tab = Titanium.UI.createTab({
title:'Course Info',
window:courseInfo_window
});
Titanium.UI.currentTabGroup.addTab(courseInfo_tab);
});
Which I want to be there to create a Course Info tab, but then in get_courseInfo.js I have this, possibly redundant code:
Ti.UI.currentTabGroup.activeTab.open(courseInfo_window);
Which, in my noob mind seems necessary to open my courseInfo_window, but is accumulating the tabs in the bottom (as shown in the image earlier).
TL;DR: What do I need to do (probably in get_courses.js) to update the Course Info tab instead of opening a new tab for each row click?
You can access tabs in TabGroup through tabs property. However, it would be easier to keep reference to tab which you created outside of event listener and modify inside:
var courseInfo_tab = null;
table.addEventListener("click",function(e){
var courseInfo_window = Titanium.UI.createWindow({
title:e.rowData.title,
url:'get_courseInfo.js',
courseIMISCode: e.rowData.courseIMISCode
});
if (courseInfo_tab === null) {
courseInfo_tab = Titanium.UI.createTab({
title:'Course Info',
window:courseInfo_window
});
Titanium.UI.currentTabGroup.addTab(courseInfo_tab);
} else {
courseInfo_tab.window = courseInfo_window;
}
});

Selectively remove Chrome browsing history

Is it possible to selectively remove items from Google Chrome browsing history? I have a website from my history that wants to be the default everytime I start a search with a specific letter, but I often reference my history to re-find things.
So I would like to remove all history from, say, www.pythonismyfavoritest.com without removing everything; is that possible?
Try searching www.pythonismyfavoritest.com in the search bar in chrome://history/ and then remove each item by clicking the check box in the left and then hitting the "remove selected items" button.
The chrome history api works with url such chrome://history/#q=hello&p=0
Here's something I wrote in JavaScript. It works through the Console Debugger. I tried using it in a bookmark but I get no response from the page.
** // UPDATE (07.28.15)
I added a shorter approach provided by #Denis Gorbachev to the checkbox targeting, which helped shorten some of this code. I also added "auto-stop" functionality, meaning the loop will stop once it has finally cleared the list.
** // UPDATE (08.20.14)I made a few changes to the code, to make it more user friendly. Other users may not be code-savvy, and others may simply prefer convenience. Therefore, I whipped up a couple buttons (start/stop) to control the usage; as well as address some "ASSERTION FAILED" exceptions/errors that were being thrown when attempted to run the script loop.. Enjoy!!
In your address bar, type in the following address to to the meat of the history page.. It's normally loaded in an iframe, with the left-side menu loaded in another frame.. // **
chrome://history-frame/
Next, load your Console Debugger/Viewer by pressing Ctrl+Shift+J(For Mac users, ⌘+⌥+J)
You can also press F12 and select the "Console" tab.
In the Console Debugger/Viewer, copy & paste the following code:
function removeItems() {
removeButton = document.getElementById('remove-selected');
overlayWindow = document.getElementById('overlay');
//revision (07.28.15): Replaced the For Loop targeting the checkboxes, thanks to Denis Gorbachev via comments (02.19.15)
Array.prototype.forEach.call(document.querySelectorAll("input[type=checkbox]"), function(node) {node.checked = "checked"})
setTimeout(function () {
if (removeButton.getAttribute("disabled") !== null) {
removeButton.removeAttribute("disabled")
}
/* revision (08.20.14): no longer binding to that condition, button should no longer be disabled, so click! */
if ((overlayWindow.hasAttribute("hidden")) && (overlayWindow.getAttribute("hidden") !== false)) {
removeButton.click();
}
/* revision (08.20.14): new Interval, to check against the overlay DIV containing the confirmation "Remove" button */
/* Attempting to click the button while the DIV's "hidden" attribute is in effect will cause FAILED ASSERTION */
stopButton = setInterval(function () {
if (overlayWindow.hasAttribute("hidden")) {
if (overlayWindow.getAttribute("hidden") == "false") {
hidden = false
} else {
hidden = true
}
} else {
hidden = false
}
if (!hidden) {
document.getElementById("alertOverlayOk").click();
clearInterval(stopButton)
}
}, 250)
}, 250)
}
//revision (08.20.14): Lets build our buttons to control this so we no longer need the console
//stop button (08.20.14)
var stopButton = document.createElement('button');
stopButton.setAttribute('id', "stopButton");
stopButton.innerHTML = "Stop";
stopButton.style.background = "#800";
stopButton.style.color = "#fff";
stopButton.style.display = "none";
stopButton.onclick = function () {
clearInterval(window.clearAllFiltered);
document.getElementById("stopButton").style.display = "none";
document.getElementById("startButton").style.display = ""
};
//start button (08.20.14)
var startButton = document.createElement('button');
startButton.setAttribute('id', "startButton");
startButton.innerHTML = "Start";
startButton.style.background = "#090";
startButton.style.color = "#fff";
startButton.onclick = function () {
window.clearAllFiltered = setInterval(function () {
/* revision (07.28.15): Stop the Loop automatically if there are no more items to remove */
if(document.getElementById("results-header").innerText=="No search results found."){
document.getElementById("stopButton").click();
}
if (document.getElementById("loading-spinner").getAttribute("hidden") !== null) {
removeItems()
}
}, 250); //adjust Time Here (1500 [millisec] = 1.5sec)
document.getElementById("stopButton").style.display = "";
document.getElementById("startButton").style.display = "none"
};
/* revision (08.20.14): Now we add our buttons, and we're ready to go! */
editingControls = document.getElementById('editing-controls');
editingControls.appendChild(stopButton);
editingControls.appendChild(startButton);
This removeItems function will select loop through all form inputs and check all checkboxes, enable the "Remove Selected Items" button and click it. After a half-second, it'll check if the "Are You Sure" prompt is displayed and, if so, click the "Yes/Remove" button automatically for you so that it will load a new list of items to do this process all over again..
The item is looped using the variable "clearAllFiltered", which is a setInterval loop, which is checking for the status of the "Loading" screen..
To start erasing your filtered history items, you can now click the green Start button.
** // UPDATE (07.28.2015) It will now stop on ITS OWN.
To stop the loop manually, you can now click the red Stop button. Simple as that!
1) Go to your history settings ( chrome://history/ )
2) In the top right hand corner will be a search bar with a 'Search History" button
3) Type in the sitename you want to remove from history, then click the button
4) Click the box on the first one, then scroll to the bottom of the page
5) Press and hold the Shift key, then click the last box (This will check all on that page)
6) Scroll back up and select the 'Remove Selected Items" Button
7) Repeat steps 4-6 until all your Youtube History is gone.
Hopefully Chrome will update this clear history feature, but for now this seems to be the fastest option
Easy way is Shift+Delete.
For example when you type "you", "youtube.com" will be shown as selected in suggestions. Just click Shift+Delete. Then retype "you" and you will see no "youtube.com" in that list anymore.
If you are talking about getting rid of the suggested search/auto-completion... then removing specific items from your chrome://history won't do it (in my experience). I want to fill in more detail to the answer #LacOniC gave.
In the screenshot you can see I typed "ba" and Chrome is suggesting completion based on my browsing history (the items in green).
In my experience, removing specific items from your history will not remove them from showing up in this address bar auto-completion.
To quickly remove these auto complete items:
Start typing a few letters that generate the offending suggestion.
Use your keyboard's arrow keys to select the suggestion you don't like (selected item is highlighted blue in screenshot).
Press shift+delete on windows or shift+fn+delete on mac to remove the selected item.