I am trying to simulate keydown event in Google chrome console. The site of my interest is web.whatsapp.com and the element of concern is document.getElementsByClassName("input-search")[0];
What I am trying to do is that as one types some text in that field, the contact list shown below that field gets updated with contacts containing the content in that text field.
Before trying anything else, I just set focus to this text field using this answer.
Things I tried are:
https://stackoverflow.com/a/12187302/1291122 - Nothing happens and no element is updated in the contact list shown.
https://stackoverflow.com/a/4176116/1291122 - Again, the same result.
https://stackoverflow.com/a/10520017/1291122 - Nothing happens. Same result
There were a few other sources as well. But nothing has worked. How do I simulate the exact effect (of typing some text in the text field and seeing the contact list update) using JavaScript the console?
My chrome version is the latest one as of the date of writing the answer- 41.0.2272.101
EDIT:
Here is one of the sample codes which I have tried. (From answer 3 above)
setTimeout(function () {
$(".input-search").focus();
Podium = {};
Podium.keydown = function(k) {
var oEvent = document.createEvent('KeyboardEvent');
// Chromium Hack
Object.defineProperty(oEvent, 'keyCode', {
get : function() {
return this.keyCodeVal;
}
});
Object.defineProperty(oEvent, 'which', {
get : function() {
return this.keyCodeVal;
}
});
if (oEvent.initKeyboardEvent) {
oEvent.initKeyboardEvent("keydown", true, true, document.defaultView, false, false, false, false, k, k);
} else {
oEvent.initKeyEvent("keydown", true, true, document.defaultView, false, false, false, false, k, 0);
}
oEvent.keyCodeVal = k;
if (oEvent.keyCode !== k) {
alert("keyCode mismatch " + oEvent.keyCode + "(" + oEvent.which + ")");
}
document.dispatchEvent(oEvent);
}
Podium.keydown(83);
}, 5000);
Simply put this code in your chrome browser console(for web.whatsapp.com) and hit enter. Then immediately click on any part of your webpage(to transfer focus). After 5 seconds you would see the cursor on that text field. But key down event does not get invoked.
As I'm working on manipulating web.whatsapp.com with javascript, you can take a look at this function I created to type some text in the search input:
function searchContact(text)
{
var input = document.getElementsByClassName("input input-search")[0];
input.value = "";
var evt = document.createEvent("TextEvent");
evt.initTextEvent ("textInput", true, true, window, text, 0, "en-US");
input.focus();
input.dispatchEvent(evt);
}
input is the input element. evt is the typing event. text is the text you want to search.
This function does the following:
get the input -> clear it -> create a keyboard typing event -> focus the input -> apply the event on the input
EDIT: Since the wrriting of this answer, Whatsapp Web was updated and so this solution does not work anymore in Whatsapp Web. (might be useful for other places or projects)
Related
I have a requirement to capture events user performs on SAP UI5 app and playback same events when required.
I have developed a small UI5 app with few text fields, buttons, and links. I am using DOM events to capture the events. I save element ID and type of command (click, input) in my local JSONModel. When playback is required, I use saved data to perform same events again.
I am able to capture and playback text input fields but when I click button or link in playback, it clicks the button, but does not call function defined in controller on press event of button.
Can someone help me on this? In below example during playback, button click on submit works fine but it does not call function defined in controller back.
Example code
View file has button defined
var Submit = new sap.m.Button("Submit", {
text: 'Submit',
enabled: true,
press: function(oEvt) {
oController.OnPressSubmit(oEvt);
}
});
Controller has function defined
OnPressSubmit: function(oEvt){ /* Perform action */ }
Another .js file injected in index file, capture events like below
document.addEventListener("input", myInputFunction);
function myInputFunction(evt) {
if (event.target.localName.length > 0) {
recordingData.push({
"type": event.target.localName,
"command": event.type,
"name": event.target.id,
"value": event.target.value
});
}
sendData(recordingData);
};
In Playback
function playDataBack(Data) {
for (var i = 0; i < playbackData.length; i++) {
if (playbackData[i].command == 'input');
document.getElementById(playbackData[i].name).value = playbackData[[i]].value;
if (playbackData[i].command == 'click') {
var targBtn = document.querySelector ("#" + playbackData[i].name);
var clickEvent = document.createEvent ('MouseEvents');
clickEvent.initEvent ('click', true, true);
targBtn.dispatchEvent (clickEvent);
}
};
}
Did you include the following code outside your button creation?
oController = this;
Once you have done this assignment you can create your button and the oController will be known inside the 'press' event.
var Submit = new sap.m.Button("Submit", {
text: 'Submit',
enabled: true,
press: function(oEvt) {
oController.OnPressSubmit(oEvt);
}
});
By the way, not that it does anything to your code itself, but if you follow naming conventions I would advice you to start your functions/methods with a lowercase :)
Kr,
Kristoff
I have this simple small peace of code which generate an exception : (only in chrome)
Uncaught Error: NotFoundError: DOM Exception 8
Scenario : If a user visited a textbox and didn't put a value , he will be notify when bluring.
And the textbox will be wrapped with a red div. And if he clicks - (in order to put a value) - the red div is removed ( by unwrap the textbox).
So
I have a textbox.
This textbox has a blur handler attched.
When a blur occurs , I'm checking if a value has been entered.
if a value has been entered : everything is ok. nothing is done.
if not :
I alert the user
I wrap the textbox , with a red border
I attach a click event handler so that if the user clicks on the text box (in order to put a value )
the border disappears .
The problem :
When the user was alerted and a red-div wraps the textbox , every time I click on the textbox (in order to put a value) - Im getting the exception ( and obviously things are messed up)
Question :
Why is it happenning , and how can I fix it ?
The code : ( JSBIN )
$("body").on("blur", ".myTb", function () {
if (!$(this).val()) {
alert('you must enter something!');
doWork($(this))
}
});
function doWork(obj) {
var t = $("<div class='divError'/>");
obj.wrap(t);
obj.on('click', function () {
obj.unwrap();
});
}
p.s.:
1) I want to keep the idea of wrapping an element with a red div and to remove it when - user clicks (in order to put a value). (because this is a small part of my plugin which already works like this)
2) There is no problem in FF
3) chrome version : 25.0.1364.97 m
4) jquery: 1.8
I think the problem is, that you wrap the input field multiple times. As soon as you test if the error wrapper already exists, the error is gone:
$("body").on("blur", ".myTb", function () {
if (!$(this).val()) {
doWork($(this));
}
});
function doWork(obj) {
var t = $("<div class='divError'/>"),
hasError = obj.closest('.divError').length;
if(!hasError) {
alert('you must enter something!');
obj.wrap(t);
}
//console.log(obj);
obj.on('click', function () {
console.log(obj);
obj.unwrap();
obj.focus(); // be sure to set focus to the input element
});
}
Updated test is here.
The problem is that the blur event fires when you unwrap the input element. It's safer to use .one() in this case:
function blurOn()
{
$("body").one("blur", ".myTb", function () {
if (!$(this).val()) {
alert('you must enter something!');
doWork($(this));
}
});
}
function doWork(obj)
{
var t = $("<div class='divError'/>");
obj.wrap(t);
obj.one('focus', function () {
obj.unwrap().focus();
blurOn(); // enable blur event handler again
});
}
blurOn();
Demo
I am using requiredFieldValidator for my TextEditor. Using the onValidationError event as given below, i set the title attribute of my cell to the error message so that a tooltip will be displayed as 'This is a required field'.
var handleValidationError = function(e, args) {
var validationResult = args.validationResults;
var activeCellNode = args.cellNode;
var editor = args.editor;
var errorMessage = validationResult.msg
$(activeCellNode).live('mouseover mouseout', function(event) {
if (event.type == 'mouseover') {
$(activeCellNode).attr("title", errorMessage);
} else {
$(activeCellNode).attr("title", "");
}
});
grid.onValidationError.subscribe(handleValidationError);
Successfully, the tooltip is displayed when there is some validation error.
But the problem is When the same cell is given a correct value and validation succeeds, the previous tooltip appears again.
How do I remove that tooltip on successful validation?
I have found a solution for this issue and it works fine.
By going through the slick.grid.js code, i understood that OnValidationError event will be triggered only when the 'valid' value from the validator is false.
My idea was to fire the onValidationError event whenever validator is called i.e on both validation success and failure, and to check for 'valid' value and handle the tooltip according to that value.
STEPS:
In slick.grid.js, I added the trigger for onValidationError event when 'valid' from validator is true also.
(i.e) add the below given code before return statement in if(validationResults.valid) in slick.grid.js
trigger(self.onValidationError, {
editor: currentEditor,
cellNode: activeCellNode,
validationResults: validationResults,
row: activeRow,
cell: activeCell,
column: column
});
2. In the onValidationError event handler of your slickgrid,get the value of the parameter 'valid'. If true, it means validation is success and remove tooltip i.e remove
title attribute for that node. If 'valid' is false, it means
validation has failed and add tooltip.i.e set the title attribute to
error message. By doing this, the tooltip of the previous
onValidationError will not appear on the same node. The code goes as
follows:
grid.onValidationError.subscribe(function(e, args) {
var validationResult = args.validationResults;
var activeCellNode = args.cellNode;
var editor = args.editor;
var errorMessage = validationResult.msg;
var valid_result = validationResult.valid;
if (!valid_result) {
$(activeCellNode).attr("title", errorMessage);
}
else {
$(activeCellNode).attr("title", "");
}
});
Hope this solution will help others for this issue.
HAPPY LEARNING!!!
Rather than editing the slick grid js - I've submitted a request for this change - in the meantime you can subscribe to the following events to remove the previous validation display:
grid.OnCellChange.Subscribe(delegate(EventData e, object a)
{
// Hide tooltip
});
grid.OnActiveCellChanged.Subscribe(delegate(EventData e, object a)
{
// Hide tooltip
});
grid.OnBeforeCellEditorDestroy.Subscribe(delegate(EventData e, object a)
{
// Hide tooltip
});
A much more appropriate way to implement this is to subscribe to the onBeforeCellEditorDestroy event and clean up the state (i.e. clear the tooltip) there.
I wasn't able to determine the current cell in OnBeforeCellEditorDestroy, so I just cleared the title in onCellChange, which fires before onValidationError. For example:
grid.onCellChange.subscribe(function (e, args) {
$(grid.getCellNode(args.row, args.cell)).children("input").attr( "title", "");
});
Does anybody know why after clicking outside the search field and hiding autocomplete results a focus activate one more time? See please at http://layot.prestatrend.com/
Type for example just 3 letters at search field 'ipo'. Thanks for any reply!
I guess it is just the behavior of the plugin to re-focus the input if the suggestion menu was visible.
When you click outside (or use TAB to unfocus) the input, the "blur" event is triggered:
.blur(function() {
hasFocus = 0;
if (!config.mouseDownOnSelect) {
hideResults();
}
})
Executing hideResults' executes another functionhideResultsNow` which makes this check:
var wasVisible = select.visible();
...
if (wasVisible)
// position cursor at end of input field
$.Autocompleter.Selection(input, input.value.length, input.value.length);
wasVisible is true because the suggestion menu is open.
The job of $.Autocompleter.Selection is to set the text selection in the input and at the end, it focuses the input:
$.Autocompleter.Selection = function(field, start, end) {
if (field.createTextRange) {
...
} else if (field.setSelectionRange) {
...
} else {
...
}
field.focus();
};
If you click again outside the input, the variable wasVisible is false, because the suggestion menu is not open anymore, and the $.Autocompleter.Selection is not executed so the input is not re-focused.
The only way I found: Destroy the autocomplete on focus event for re initializing it.
function defaultFocusAction(e, options) {
if($(e.currentTarget).val() == '') {
$(e.currentTarget).autocomplete('destroy');
$(e.currentTarget).autocomplete(options);
}
$(e.currentTarget).trigger('keydown.autocomplete');
}
var options = {
autoFocus : false,
delay : 0,
minLength: 0,
source: ['foo', 'bar']
};
$('input.autocomplete').autocomplete(options).focus(function(e) {
defaultFocusAction(e, options);
});
NEW Fiddle: http://jsfiddle.net/martinnormark/jBZfs/14/ - new isolated example. See how the change event is not fired for Amount 2! **
I have a jQuery plugin for formatting a number in a currency format, as you type.
You can see it in action in this fiddle: http://jsfiddle.net/martinnormark/Rv4Ug/1/
The problem is, if you enter a value of at least 4 digits (causing the need to thousand separator: 1178 becomes 1,178), the change event dies. As long as you stay below 4 digits, not causing a new format, the change event is fired.
In the fiddle, try to enter 12, then 123. You should see a text reading 'change event raised'. And then enter 1234 - and the change event is not fired.
This will have something to do with the manipulation of the input element's value in a keyup event handler:
$this.on("keyup.autoformatcurrency", function(event) {
if ($.inArray(event.keyCode, keyCodes) > -1) {
formatCurrency($(this), true);
}
});
And the formatCurrency function:
function formatCurrency($this, setCaretPosition) {
var rawValue = $this.val(),
floatValue = Globalize.parseFloat(rawValue);
if ($.isNumeric(floatValue)) {
var formattedValue = Globalize.format(floatValue, settings.formatString),
caretPosition = 0;
if (setCaretPosition) {
caretPosition = $this.caret().end + (formattedValue.length - rawValue.length);
}
$this.val(formattedValue);
if (setCaretPosition) {
$this.caret(caretPosition, caretPosition);
}
}
}
(for full source, see the file on Github: https://github.com/martinnormark/jquery-format-currency/blob/master/src/jquery.formatcurrency.js )
The question is, if there's a way to make sure the change event will be fired?
UPDATE - Current state in browsers
Chrome: Change event fired, if number is below 4 digits.
Safari, IE: Change event is never fired, as long the value is set programmatically. Enter letters instead of numbers will trigger the change event.
Firefox: Works!
Opera: Works!
The easiest way would be, to trigger the change event from within the keyup function:
$this.on("keyup.autoformatcurrency", function(event) {
if ($.inArray(event.keyCode, keyCodes) > -1) {
formatCurrency($(this), true);
$(this).change();
}
});