Is there a way we can include a keypress in the URL? We have a usecase where a webpage shows an additional information pane when a user presses 'i' on her keyboard. We want to show this additional information pane by default, without the user having to press the key 'i'.
Simply visiting this URL should automatically trigger a press on the 'i' key and show the information pane by default. Is there a way to construct such a URL?
EDIT: To provide more clarity, note that we do not control the webpage in question here. We're simply providing a URL such as www.google.com to our users, visiting it and pressing 'i' unhides the information pane class. We want to avoid having our users press 'i', by providing them a URL that automatically triggers a keypress event, something along the lines www.google.com?&keypress=i.
why don't you call something like this onLoad:
var keyboardEvent = document.createEvent("KeyboardEvent");
var initMethod = typeof keyboardEvent.initKeyboardEvent !== 'undefined'
? "initKeyboardEvent" : "initKeyEvent";
keyboardEvent[initMethod](
"keydown", // event type : keydown, keyup, keypress
true, // bubbles
true, // cancelable
window, // viewArg: should be window
false, // ctrlKeyArg
false, // altKeyArg
false, // shiftKeyArg
false, // metaKeyArg
40, // keyCodeArg : unsigned long the virtual key code,
else 0
0 // charCodeArgs : unsigned long the Unicode character
// associated with the depressed key, else 0
);
document.dispatchEvent(keyboardEvent);
Wrap all of this in an onLoad call and you will be able to make a keypress on page load. Make sure to replace 40 with the keyCode of 'i'.
The snippet has been taken from here
Related
I have an array of divs which can be selected (change background colour on click to signify that to the user).
I want a way to submit the ids of all of these divs to my app, though can't see a 'nice' way of doing this; at the moment the only thing I can see to do is have a button that onclick triggers a javascript function that gets the id's and sends them back to my server in a POST.
Is there a way of creating a multiple select input on a form which uses divs instead of checkboxes or a multi-select list, or a better way of doing what I'm attempting?
Assuming you add the class selected when a user 'selects' the div:
var data = {};
$(".classOfDivs.selected").each(function(){
data[$(this).prop('id')] = 'true';
}
$.ajax({
url : 'ajaxPage.php',
type : 'POST',
dataType : 'text',
cache: false,
data: data,
success : function(text){alert('Saved: '+text);},
error: function(){alert('Did not reach server');}
});
Use the success function to process the returned text as needed. dataType can be changed to html, JSON, etc. See the .ajax() documentation.
Have a hidden input for each div, all with the same name but with a different id. When a div is clicked update the corresponding hidden input with the id. Then when you submit through a standard form POST all of those values will be available through the name you specified.
Since this is an app, what you could do is store everything in HTML5 localstorage using the JQuery javascript library.
Here's how to do it step by step:
Create a jquery array
on click, get div id and store it in the array with a key/value pair
if clicked again, remove it from the array
have some event listener like a "submit" button to store the value of your array to localstorage
Here is a jsfiddle I had that has exactly what you are talking about: http://jsfiddle.net/CR47/bqfXN/1/
It goes into a little more depth but the jquery should be exactly what you need.
The reason this is better than submitting with POST or using ajax is because since you say this is an app, you will be able to use this method offline, where as post or ajax would require a connection to a server running php.
var skinCare=[]; //the array
$('.skinCare').click(function(){ //onclick
var value = event.target.className.split(" ")[0]; //get classname, you would get id
var index = skinCare.indexOf(value); //gets where the location in
//the array this code is
if($(this).hasClass('selected')){ //when a div is clicked it gets
//$('.skinCare').removeClass('selected'); //the class "selected" and adds
skinCare.splice(index, 1); //to array, then another click
} else if($.inArray(value, skinCare) == -1){ //removes it from array
skinCare.push(value);
}
});
$('.submitbutton').click(function(){
localStorage.setItem('Skin Care', JSON.stringify(skinCare));
});
I am using an iFrame to load a page whose url is specified in a text box. Here is my code :
<iframe id="import_url_iframe">
</iframe>
I use jQuery change event to get the change of the url in the text box :
$("#wiki_form_url").change(function(){
var value = $(this).val();
$("#import_url_iframe").attr("src", value);
});
This works fine if I click outside after specifying the url in the text box. But, I need to make this so when I write the url in the text box, it should show the page in iFrame (without any click outside). How can I accomplish that ?
Use an keydown event, possibly with a delay so that it loads after a delay (i.e. when the user hasn't typed for X seconds). So:
var timeout = null;
$("#wiki_form_url").on('keydown', function(){
timeout = setTimeout(function(){
// load URL here
}, 1000);
});
And implementing #JCOC611's suggestion as well, taking code from here, add this code as well:
$("#wiki_form_url").on('keydown', function (e){
if(e.keyCode == 13){
timeout = null;
// Load URL here
}
})'
You could take it further still, and add handlers for when the text box loses focus
$("#wiki_form_url").on('focusout', function (){
timeout = null;
// Load URL here
})'
Is it possible to send the server only the last 3 words in the textarea and to autofill the best result, letting the user keep typing in (similar to Google auto complete)?
I want the behavior to be:
N[ew]
New[er]
New(SPACE)[er]
New [York]
New c[ar]
New cat [food]
New cat (TAB) [food]
New cat food [makes]
...
New cat food is good for your cat's [health]
(clarification: the [square brackets] indicates the suggestion that is automatically being typed in, the bold text indicates the part being sent to the server, (TAB) and (SPACE) indicates tab and space key presses)
I already a have function on the server for predicting the next word (using Markov chains) and I have integrated jQuery UI autocomplete, but currently it just sends all the text to the server and creates a list with all the suggestions to choose from, once you choose it changes the whole text.
So it eventually comes to these issues:
How to send only the last part?
How to append + select the suggested word?
How to select on Tab key?
Okay - here is the solution (and here is the result):
1 + 2: Instead of managing a single input box, I use two identical size textarea's, the first (#text-area) is enables and with transparent background and the other (#suggestions) is disabled and with gray text color. I use the source callback to do all the work:
$('#text-area').autocomplete({ ...
source: function( request, response ) {
if (request.term.length < 3) {
return false;
}
$.getJSON( $SCRIPT_ROOT + '/_get_word', {
term: request.term
}, function(data) {
$('#suggestions').val(data.result) //suggestion is the disabled textarea
}
);
return false;
},
...
});
});
3: the tab key selection is done with triggering the autocomplete search event:
$('#text-area').live( "keydown",'textarea', function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB) {
event.preventDefault();
$('#text-area').val($('#suggestions').val());
$("#text-area").autocomplete('search', $('#text-area').val());
}
});
I have searched everywhere and cannot find a clear example of how to use Googles UI Builder and apps script. I have no clue what I'm missing. I think this should be simple :v/ YES, I've read all Googles docs, watched vids etc - several times - there is no combination of GUIB (Google's UI Builder) and a callback handler function, that I can find.
EDIT: there are examples for SpreadSheets - not GSites
What I need to do:
I would like to embed a textbox and button to collect a search phrase from a user, on a Google site page. I have built the very simple UI with a single flowpanel, textbox and button, but can only ever get "Undefined" returned from Logger.log() no matter what I do (see code below).
A bit of a rant:
I have been very careful to name, and call by the right names. I've tried using a formpanel BUT in GUIB, you can only put ONE widget in it?! ...AND a submit button will only go into a formpanel - huh - I can't put my text box in as well!? (Why bother with the formpanel then - I don't get that! ...yeah I know about doPost() automatically being called on submit). I want the widgets to remain active and not disappear after one use, so maybe formpanel/submitbutton won't work anyway - or isn't the right way to do it?
Down to business:
At any rate, what I've tried is to put the regular button and text box in a flowpanel with the following code...
EDIT: I deleted my original content here and reposted this section...
// Google Sites and UIBuilder (GUIB) - kgingeri (Karl)
// - this script is embedded in a GSite page via: Insert -> Apps Script Gadget.
//
// Withing GUIB I have defined:
// - a FlowPanel named 'pnlMain'
// - inside that a textBox named 'tbxQuery' and a button called 'btnSearch'
// - for btnSearch, I have defined (in the Events subsection) a callback function
// btnSearchHandler (see it below doGet() here. I expanded the [+] beside that
// and entered 'tbxQuery'
//
// the GUIB compnent tree looks like this...
//
// [-] testGui
// [-] pnlMain
// btnSearch
// tbxQuery
//
// btnSearch Event section looks something like this...
//
// Events
// On Mouse Clicks
// [X][btnSearchHandler][-]
// [tbxQuery ]<--'
// [Add Server]
// ...
//
// So...
// 1) when the page is opened, the doGet() function is called, showing the defined UI
// 2) when text is entered into the textBox and the button is clicked
// 3) the data from tbxQuery is **SUPPOSED TO BE** returned as e.parameter.tbxQuery
// in the function 'btnSearchHandler(e)' **BUT IS NOT** :v(
//
// (this functionality appears to work in a spreadsheet?! - weird?!)
//
// [ predefined function --- Google calls on page open ]
//
// ...this works 'as advertised' ;v)
//
function doGet(e) {
var app = UiApp.createApplication();
app.add(app.loadComponent("testGui")); // ...the title that shows in G/UIBuilder
return app;
}
//
// [ callBack for when a button is clicked ]
//
// ...I always get 'Resp: [Undefined]' returned in the View -> Logs menu?!
// ...I also tried to put 'pnlMain' in the Event [+] param, no go :v(
//
function btnSearchHandler(e) {
var resp = e.parameter.tbxQuery // ...the data I want in the textBox widget
Logger.log('Resp: [' + e.parameter.tbxQuery + ']');
// ...more code to come, once this works!
}
I've also tried adding code to manually set handlers etc in doGet(), and not use GUIB Event settings, but to no avail either.
Conclusion?
What Gives? Do I have to hand-code the GUIs and not use GUIB? I know it's a simple one this time, but if I can get this working I can sure see being much nicer to build other apps with GUIB! Can anyone give me or point me to a clear example?!
Thanks for reading!
here is a shared spreadsheet with an example of GUI builder
when you're in the GUI builder look at the properties of the element you want to trigger a function, at the end of the parameter list there is an 'EVENT' properties where you can add the function name and the callbackElements as well. !
Hoping it's clear enough,
cheers,
Serge
EDIT : if you want to have a look at a more complex example please open this one (create a copy of it to make it editable) or see it working here, I think you might be convinced that the GUI builder is a really powerfull tool .
Many thanks to Serge Insas!!
The answer is as shown below - I had missed two things:
the small [+] beside the On Mouse Click server handler - to add
a parameter to return
the Name is what is used NOT ID - set in
Input Fields section of tbxQuery
(NOTE: non-data elements don't have names - so fplMain has only an ID, but still works)
So, here is the resulting code, and comments describing GUIB settings:
// Google Sites and UIBuilder (GUIB) - kgingeri (Karl)
// - this script is embedded in a GSite page via: Insert -> Apps Script Gadget.
//
// Withing GUIB I have defined:
// - a FlowPanel named 'fplMain'
// - inside that, a textBox named 'tbxQuery' (see Input Fields section - this in NOT ID)
// and a button called 'btnSearch'
// - for btnSearch, I have defined (in the Events subsection) a callback function
// btnSearchHandler (see it below doGet() here). I expanded the [+] beside that,
// and entered "fplMain" as the return param (it will return all data elements)
//
// the GUIB compnent tree looks like this...
//
// [-] SearchGui
// [-] fplMain
// btnSearch
// tbxQuery
//
// "tbxQuery" Input Fields param, "Name"... **THIS MUST BE SET!
//
// Input Fields
// ...
// Name
// [tbxQuery ]
//
// "btnSearch" Event section looks like this...
//
// Events
// On Mouse Clicks
// [X][btnSearchHandler][-]
// [fplMain ]<--'
// [Add Server]
// ...
//
// So...
// 1) when the page is opened, the doGet() function is called, showing the defined UI
// 2) when text is entered into the textBox and the button is clicked
// 3) the data from tbxQuery is returned as e.parameter.tbxQuery (as would be any other
// params under the flow panel "fplMain") in the function 'btnSearchHandler(e)'
//
// [ predefined function --- Google calls on page open ]
//
function doGet(e) {
var app = UiApp.createApplication();
app.add(app.loadComponent("SearchGUI")); // ...the title you choose in G/UIBuilder
return app;
}
//
// [ callBack for when a button is clicked ]
//
function btnSearchHandler(e) {
var resp = e.parameter.tbxQuery // ...the data in the textBox widget
Logger.log('Resp: [' + e.parameter.tbxQuery + ']');
//
// ...more code goes here, to do something with the returned data
//
}
I have tried to follow the examples on the Safari Developer Site.
The documentation suggests adding an event listener like so:
window.addEventListener('storage', storage_handler, false);
And then setting your handler function like this:
function storage_handler(evt)
{
alert('The modified key was '+evt.key);
alert('The original value was '+evt.oldValue);
alert('The new value is '+evt.newValue);
alert('The URL of the page that made the change was '+evt.url);
alert('The window where the change was made was '+evt.source);
}
But I can't seem to get this code to work on my machine (OS X 10.6, Safari 5.01) nor on Safari on my iPhone 3GS (iOS 4.02).
This article offers a separate method:
window.onload = function() {
...
document.body.setAttribute("onstorage", "handleOnStorage();");
}
function handleOnStorage() {
if (window.event && window.event.key.indexOf("index::") == 0){
$("stats").innerHTML = "";
displayStats();
}
}
But I haven't had any luck with that either.
Am I doing something wrong? Is this a bug?
After investigating further (and with the help from a friend) I discovered that the storage_handler method is called not when the value of a localstorage value changes on the page in my current window or tab, but when it changes in another tab.
For example, if I have the two tabs open, and have controls in the pages in each tab to change localstorage settings, then when I hit the control in the first tab, the storage_handler method is called in the other tab.
If you want to perform some action after the objects are saved in localstorage on the same page you can manually call the function after calling localStorage.setItem and call the same function from the storage eventlistener to handle multiple tabs.
I realize this is asking about Safari but, per the Mozilla Developer Network, the StorageEvent is only fired if the web storage object is changed from outside the page, e.g., in another tab.
https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API
Scroll down to "Responding to storage changes with the StorageEvent".
(I would have added this as a comment to the accepted answer but I don't have the rep for that.)
You can send a storage event every time you set the local storage
const favorites: null | string =
localStorage.getItem(favoritesKey);
localStorage.setItem(
favoriteKey,
JSON.stringify(
favorites === null
? [id]
: [...JSON.parse(favorites), id]
)
);
window.dispatchEvent(new Event("storage"));
Then the following will trigger
useEffect(() => {
const listener = () => {
const favorites: null | string = localStorage.getItem(favoriteKey);
if (favorites !== null) {
setState(JSON.parse(favorites));
}
};
window.addEventListener("storage", listener);
return () => {
window.removeEventListener("storage", listener);
};
}, []);