Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I have created an extension that integrates with the omnibox. When I have typed in the keyword + space and then the phrase to send to the extension, I can see that the top row in the omnibox says "Run my-extenison-name command:"
What exactly is this? Can I use this somehow to maybe call methods in my extension?
It would be really nice if it was possible, but I can't find any info on this.
"Run <your-extension-name> command" is simply the "Default" default suggestion for your extension's omnibox. It's basically the placeholder for what is currently entered, and should indicate what will happen if the user presses enter at that point ("search my site for 'x'"). To change it, just add this to your background page
chrome.omnibox.setDefaultSuggestion({"description" : "your description here"});
You can use "%s" in there as well as a placeholder for what the user is typing in.
Jason was right in how you can use onInputEntered to react to the user entering something into the omnibox.
When the user selects the command, any listeners you've added to the onInputEntered event will be fired.
See: http://code.google.com/chrome/extensions/omnibox.html#event-onInputEntered
So yes, you can have Omnibox commands call methods in your extension, just by adding a listener to that event, like so:
chrome.omnibox.onInputEntered.addListener(function(text) {
console.log('User entered command: ' + text);
};
You can also get notifications of the user's omnibox activity while they're typing, or if they cancel typing, by adding listeners for the other events listed on the page linked above.
I do this for my Chrome extension Lil’ Launch which has no use for the default suggestion (it only searches your bookmarks).
The full source is on Github, but the general idea is this. The callback for chrome.omnibox.onInputEntered gets passed either the content property of your selection or the value of the user input if the suggestion is the default one. So I append a known string to the front of all the content properties and check for that same string when chrome.omnibox.onInputEntered fires. It needs to be something that the use is unlikely to type, otherwise the matching will break.
var resultsList = [], // Accessible from the callback scope
unlikely = "GOSHDARNYOUCHROME"; // Our unlikely to be typed String
chrome.omnibox.onInputChanged.addListener(
function(text, suggest) {
var searchResults = chrome.bookmarks.search(text, function(searchResults) {
resultsList = [];
for (var i = 0; i < searchResults.length; i++) {
resultsList.push({
content: unlikely + item.url, // Prepend our unlikely string to the URL
description: "bar"
});
};
// Chrome adds a completely useless default suggestion in our case
// So set the default and slice it off the suggestions
chrome.omnibox.setDefaultSuggestion({ description: resultsList[0].description });
suggest(resultsList.slice(1, -1));
})
}
);
chrome.omnibox.onInputEntered.addListener(
function(text) {
// If text doesn't have unlikely prepended its the stupid default
if(text.substring(0, unlikely.length) !== unlikely) {
text = resultsList[0].content;
}
text = text.substring(unlikely.length); // Trim the unlikely string
// Do something with text
}
);
Stupid, but effective.
Related
My extension has a context menu with items. What I'd like it to do: is when I right-click an editable html element (eg input or textarea) and then select and click on an item in my menu - some value defined by my extension gets entered into the input.
For now I have realised that with document.activeElement.value = myValue.
With simple inputs it works alright.
Problems start when there is an input with custom onChange event handling, eg a calendar or a phone input, or currency input - that transforms user-input in some way.
Since I am setting a value directly onto the element - the handling logic gets omitted, which causes all manner of problems.
Since javascript doesn't allow for KeySend-like features - what are my options here?
I have thought about testing tools like Puppeteer or Cypress - but they all seem not to be packageable into an extension. Puppeteer does have such an option, but it still requires a node instance running to connect to. And I would like my extension to be solely client-sided and distributed in Chrome webstore - so I cannot ask my users to spin up a node server.
There is a built-in DOM method document.execCommand.
In case of an extension, use this code in the content script.
// some.selector may be `input` or `[contenteditable]` for richly formatted inputs
const el = document.querySelector('some.selector');
el.focus();
document.execCommand('insertText', false, 'new text');
el.dispatchEvent(new Event('change', {bubbles: true})); // usually not needed
It imitates physical user input into the currently focused DOM element so all the necessary events will be fired (like beforeinput, input) with isTrusted field set to true. On some pages the change event should be additionally dispatched as shown above.
You may want to select the current text to replace it entirely instead of appending:
replaceValue('some.selector', 'new text');
function replaceValue(selector, value) {
const el = document.querySelector(selector);
if (el) {
el.focus();
el.select();
if (!document.execCommand('insertText', false, value)) {
// Fallback for Firefox: just replace the value
el.value = 'new text';
}
el.dispatchEvent(new Event('change', {bubbles: true})); // usually not needed
}
return el;
}
Note that despite execCommand being marked as obsolete in 2020, it'll work in the foreseeable future because a new editing API specification is not finished yet, and knowing how slow such things usually move it may take another 5-20 years.
#wOxxOm, thank you very much !
I used your code solved my problem which has bothered me for long time. I googled many code and article for nearly one month.
It works on Facebook and many strong website.
Because execCommand has depredated, I try below code it works well, include Facebook.
function imitateKeyInput(el, keyChar) {
if (el) {
const keyboardEventInit = {bubbles:false, cancelable:false, composed:false, key:'', code:'', location:0};
el.dispatchEvent(new KeyboardEvent("keydown", keyboardEventInit));
el.value = keyChar;
el.dispatchEvent(new KeyboardEvent("keyup", keyboardEventInit));
el.dispatchEvent(new Event('change', {bubbles: true})); // usually not needed
} else {
console.log("el is null");
}
}
The following code can only work on ordinary websites, but it is invalid for strong website.
function fireKeyEvent(el, evtType, keyChar) {
el.addEventListener(evtType, function(e) {el.value += e.key;}, false);
el.focus();
const keyboardEventInit = {bubbles:false, cancelable:false, composed:false, key:keyChar, code:'', location:0};
var evtObj = new KeyboardEvent(evtType, keyboardEventInit);
el.dispatchEvent(evtObj);
}
I hope someone can help me with this.
I have built an application that uses node.js to fulfil my intent in dialogflow.
For example, I have an intent with one required action:
It goes to my fulfilment:
// Handle the Dialogflow intent named 'Default Welcome Intent'.
app.intent(DEFAULT_INTENT, (conv, params) => {
let categoryId = params.category;
let options = {
'method': 'GET',
'url': apiUrl + 'questions/categories/' + categoryId + '/scenario',
'json': true
};
return request(options).then(response => {
// TODO: What happens if there is more than one question?
let question = response[0];
conv.ask(question.text);
}, error => {
conv.ask('There was an issue with the request: ' + options.url);
});
});
As you can see, this asks a question based on the category sent to the fulfilment.
The problem I have is that the response I want from the user is different for each question.
Once they have responded, it will also have a fulfilment that will ask another question.
Is it possible to do it this way and if so, can someone give me an example of how? If not, can someone help me work out what the alternative is?
The approach you're using makes sense. The key thing to remember is that Intents capture what the user says, not how you handle what they say. You can influence which Intent gets triggered by setting an Input Context, and making sure you have previously set an Output Context for it.
One possible approach would be that for each question you're asking, you set a corresponding Output Context for that question. You can then have one or more Intents that take this as the Input Context. These are otherwise regular Intents, so you'd handle them normally. You might want to clear the context (by setting its lifespan to 0) after it matches, so you don't accidentally match it later.
For example, if your question contains, not only the text of the question, but also the context name of the question, the code might look something like this:
conv.ask( question.text );
conv.contexts.set( question.contextName, 5 );
Let's say that the question object looks something like this
{
text: "What is your favorite color?",
contextName: "color-favorite"
}
You might have a Dialogflow Intent that handles this that looks something like this
Note that the Output Context has explicitly set it to 0, which will remove it. You can also do this in your fulfillment code with something like
conv.contexts.delete( 'color-favorite' );
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
When adding text to a webpage best practice would be to use localization resources, or at least copy/paste text out of a program like Word (or any other grammar/spell checker). That being said there are "always" a couple words here and there where a developer just "updates it."
My question, how do other people check for typos on their webpages? I have a solution (Which I will post as a possible answer), but looking for other ideas.
You can add a function in your javascript library to grab all text and put it in a textbox, which on a browser like chrome will then trigger the native spellchecker.
function SpellCheck()
{
var ta=document.createElement('textarea');
var s=document.createAttribute('style');
s.nodeValue='width:100%;height:100em;';
ta.setAttributeNode(s);
ta.appendChild(document.createTextNode(document.body.innerText));
document.body.appendChild(ta);
ta.focus();
for (var i = 1; i <= ta.value.length; i++)
ta.setSelectionRange(i, i);
}
Code from #JohnLBevan blog post (posted on 2011/03/28)
I made the comment above, then I used the idea from the first answer to add this to my dev environment:
function showPageSource()
{
var text = document.body.innerText;
var textarea = document.createElement('TEXTAREA');
textarea.style.position = 'absolute';
textarea.style.opacity = 0.95;
textarea.style.zIndex = 999;
textarea.style.top = '25px';
textarea.style.left = '25px';
textarea.style.width = 'calc(100% - 50px)';
textarea.style.height = '500px';
textarea.value = text;
document.body.appendChild(textarea);
textarea.addEventListener('click', function (e)
{
e.stopPropagation();
}, false);
document.body.addEventListener('click', function (e)
{
textarea.parentNode.removeChild(textarea);
}, false);
}
And then a tag like this to show the sauce:
SHOW PAGE SOURCE
Shows a fair amount of crap from the navigation - but I can live with that.
I am writing a Google extension. Here my content script modifies a page based on a list of keywords requested from background. But the new innerHTML does not show up on the screen. I've kluged it with an alert so I can see the keywords before deciding to actually send a message, but it is not how the routine should work. Here's the code:
// MESSAGE.JS //
//alert("Message Page");
var keyWordList= new Array();
var firstMessage="Hello!";
var contentMessage=document.getElementById("message");
contentMessage.value=firstMessage;
var msgComments=document.getElementsByClassName("comment");
msgComments[1].value="Hello Worlds!";//marker to see what happens
chrome.extension.sendRequest({cmd: "sendKeyWords"}, function(response) {
keyWordList=response.keyWordsFound;
//alert(keyWordList.length+" key words.");//did we get any keywords back?
var keyWords="";
for (var i = 0; i<keyWordList.length; ++i)
{
keyWords=keyWords+" "+keyWordList[i];
}
//alert (keyWords);//let's see what we got
document.getElementsByClassName("comment")[1].firstChild.innerHTML=keyWords;
alert (document.getElementsByClassName("comment")[1].firstChild.innerHTML);// this is a band aid - keyWords does not show up in tab
});
document.onclick= function(event) {
//only one button to click in page
document.onload=self.close();
};
What do I have to do so that the text area that is modified actually appears in the tab?
(Answering my own question) This problem really has two parts. The simplest part is that I was trying to modify a text node by setting its value like this:
msgComments1.value="Hello Worlds!"; //marker to see what happens
To make it work, simply set the innerHTML to a string value like this:
msgComment1.innerHTML="Hello Worlds!"; //now it works.
The second part of the problem is that the asynchronous call to chrome.extension.sendRequest requires a callback to update the innerHTML when the reply is received. I posted a question in this regard earlier and have answered it myself after finding a solution in an previous post by #serg.
I have already added 5 cammands in a form and I want to add a sixth but It does not display the sixth?
I am posting my codes below.
public Command getOk_Lastjourney() {
if (Ok_Lastjourney == null) {
// write pre-init user code here
Ok_Lastjourney = new Command("Last Journey", Command.OK, 0);
// write post-init user code here
}
return Ok_Lastjourney;
}
public Form getFrm_planjourney() {
if (frm_planjourney == null) {
// write pre-init user code here
frm_planjourney = new Form("Plan journey", new Item[] { getTxt_From(), getTxt_To(), getCg_usertype(), getCg_userpref(), getCg_searchalgo() });
frm_planjourney.addCommand(getExt_planjourney());
frm_planjourney.addCommand(getOk_planjourney());
frm_planjourney.addCommand(getOk_planFare());
frm_planjourney.addCommand(getOk_planDistance());
frm_planjourney.addCommand(getOk_planTime());
frm_planjourney.addCommand(getOk_planRoute());
frm_planjourney.setCommandListener(this);
// write post-init user code here
System.out.println("Appending.....");
System.out.println("Append completed...");
System.out.println(frm_planjourney.size());
frm_planjourney.setItemStateListener(this);
}
return frm_planjourney;
}
Given System.out.println I assume you were debugging with emulator, right? in that case it would be really helpful to provide a screen shot showing how exactly does not display the sixth looks like.
Most likely you just got too many commands to fit to area allocated so that some of them are not shown until scrolled. There is also a chance that sixth command was reassigned to some other soft-button and you didn't notice that. Or there's something else - hard to tell with details you provided.
A general note - handling six actions with commands might be not the best choice in MIDP UI. For stuff like that, consider using lcdui List API instead. IMPLICIT kind of lists allow for more reliable and user friendly design than commands.