Keyboard input in web-component-tester not working - polymer

I'm trying to test our polymer component which has an iron-input in it. To test things like max-length and filtering of allowed patterns I would like to test for certain keyboard inputs.
Somehow this does not seem to work, the value of the iron-input element stays the same.
I tried these methods:
// from iron-test-helpers
MockInteractions.pressAndReleaseKeyOn(input, undefined, [], '2');
// generic way
var e = document.createEvent('TextEvent');
e.initTextEvent('textInput', true, true, null, 'Bob');
input.dispatchEvent(e);
//check input.value (native) and input.bindValue (iron-input var, set after input event is triggered)
console.log(input.value);
console.log(input.bindValue);
assert.equal(input.bindValue, '123456');

Related

How to represent a state machine with HTML elements?

On a web page I wish to display an element which depends on the state of some JavaScript. State like in a state machine. Currently the possible states are these (but I may add more):
input: display some input elements for the user to set. The user can click a button to start some JavaScript processing and move to the working state.
working: display a progress bar informing the user that the script is running. The user can cancel the computation (moving back to the input state) or the computation can end (moving to either the result or error state).
result: display the computation result. The user can go back to input with a button.
error: display the error. The user can go back to input with a button.
The JavaScript part is ready and working, but I'm unsure how to do this in HTML + CSS.
Current solution and its issue
Currently I've been doing it with classes: I set a class to a common ancestor element with the same name of the state and I display the right elements based on it. Something like this:
const parent=document.querySelector("#parent");
let timer=null;
function input(){
parent.classList.remove("working","result","error");
parent.classList.add("input");
}
function run(){
parent.classList.remove("input");
parent.classList.add("working");
timer=setTimeout(result,1500)
}
function stop(){
clearTimeout(timer);
input();
}
function result(){
parent.classList.remove("working");
if(Math.random()>0.5){parent.classList.add("result");}
else{parent.classList.add("error");}
}
input();
#input{display:none;}
#working{display:none;}
#result{display:none;}
#error{display:none;}
#parent.input #input{display:block;}
#parent.working #working{display:block;}
#parent.result #result{display:block;}
#parent.error #error{display:block;}
<div id="parent">
<div id="input">INPUT. RUN</div>
<div id="working">WORKING. STOP</div>
<div id="result">RESULT. RESTART</div>
<div id="error">ERROR. RESTART</div>
</div>
This solution works but it feels unstable: in theory it would be possible for the parent element to have no classes (in which case nothing is displayed) or multiple ones (in which case you'd see multiple states at once). This shouldn't happen, but the only thing preventing it is the correctness of my script.
Question
Are there better ways to implement this idea of states, so that the HTML elements can't end up in inconsistent states?
Let’s consider the role which HTML plays in a state machine on the web. A machine has moving parts, it is dynamic, so the core of any machine on the web must be implemented in Javascript. HTML is useful only to provide the interface between the user and the machine. It’s a subtle distinction but it fundamentally changes the way you write it.
Have you ever used React? React provides the framework to create entire web applications as “state machines”. React’s mantra is “UI is a function of state”. In a React app, you have a single variable which contains the current state, rendering code which builds the UI based on the state, and core code (mostly event handlers) which updates the state.
Even if you don’t want to build in React, you can use the same general idea:
keep the current state in a Javascript variable (typically you’d use an object, but in this case we only need a string)
write a rendering function which reads the state and then builds the appropriate HTML to represent that state
in the event handlers for your links, do any operations which are required, update the state and call the rendering function
let state = null
let timer = null
// core code
const input = () => {
state = 'input'
render()
}
const run = () => {
state = 'working'
render()
timer = setTimeout(result,1500)
}
const stop = () => {
clearTimeout(timer)
state = 'input'
render()
}
const result = () => {
if(Math.random()>0.5)
state = 'result'
else
state = 'error'
render()
}
// rendering code
const render = () => {
let x = state
switch(state) {
case 'input':
x += ' run'
break
case 'working':
x += ' stop'
break
case 'result':
x += ' restart'
break
case 'error':
x += ' restart'
break
}
document.getElementById('container').innerHTML = x
}
// initialisation code
state = 'input'
render()
<div id="container"></div>

Tabulator - Cell.setValue creating recursive loop for custom formatter, table not saving data

I'll try to be as brief as possible as my situation is unique and I am a fairly new programmer.
TL:DR - Cannot get the row to update, table does not remember initial values when editing, cell.setValue() creates recursive loop, cell.getRow().update() seems to do nothing, row does not resize in the event of editing working (still does not hold on to previous values)), unsure if mutator or cellEdit() callback are potential solutions.
I have JSON data populating my table from an AJAX call to a Java backend. One of the columns can either be one item, a list of multiple items, or none at all. I am using a custom formatter to populate that cell with the list of items, followed by icons to remove those items...
Some text here X
Some other text X
And some more X
When clicking the X icon, it should remove the item, and when clicking the text, it will drop down a list to choose another option.
Some text here X
Some other text X
Added another line X <----removed the previous item and selected a new
The problem I am having is that the table does not continuously hold onto previous values nor concatenates them with new selections. I have written some code to take care of the concatenation issue, but it still does not save that info within the table. I have tried to use cell.setValue() but this creates a recursive loop as all my code is within the custom formatter. I have also tried cell.getRow().update() but this seems to do nothing.
Also, clicking into the drop down and clicking away without selecting a value will still send the previous value as though it was clicked again. I was able to get it to function once, but it only changed the most recent values and did not include the original ones and it did not resize the row to be smaller.
I am unsure if a custom mutator would solve my issue, or even how to get the mutator to interact with the formatter to update the cell every time a change has been made. I also have a cellEdited: function(){} callback that is going to be designed to take the entire row of information as a JSON object to save it within a DAO and considered that I might be able to solve the issue there?
Here is my code for that column. This currently will load the page with the initial design yet does not work with editing. "cell.setValue()" and "cell.getRow().update()" are currently not included because they weren't working properly...
title: "Groups",
field: "associatedGroups",
variableHeight: true,
headerFilter: true,
headerFilterPlaceholder: "Search by Group...",
formatter: function (cell, formatterParams, onRendered) {
var data = [];
var newValue = cell.getValue();
var oldValue = cell.getOldValue();
var newValueIsArray = $.isArray(newValue);
var oldValueIsArray = $.isArray(oldValue);
if (oldValue !== null && newValue !== null) {
if (!oldValueIsArray && newValueIsArray) {
data = data.concat(newValue);
data.unshift(oldValue);
} else if (oldValueIsArray && !newValueIsArray) {
data = data.concat(oldValue);
data.push(newValue);
} else {
data.push(oldValue);
data.push(newValue);
}
} else {
data = newValue;
}
<!-------------------Value of "data" used here to determine visual layout----------------->
},
editor: "select",
responsive:
0,
editorParams:
{
values: groupNames
}
,
sorter: "string",
width:
212
},

Trigger keypress through URL

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

Toggle switch to pass unchecked value

I'm using a checkbox to create a toggle switch as shown in this tutorial
The switch lives in a form where questions can be added dynamically. On submission the form posts as array of each answer back to the page to be processed however as the off switch doesn't pass a value back to the form the answers get out of sync with the answers for the other text fields. Is there any way to set a value for the off switch, i.e. when a check box is left unchecked?
I've tried to use the following to set my off checkboxes to off however it just seems to animate all the switches to on on form submission, anyone any ideas as to what I'm doing wrong?
$('form').submit(function(e){
var b = $("input:checkbox:not(:checked)");
$(b).each(function () {
$(this).val(0); //Set whatever value you need for 'not checked'
$(this).attr("checked", true);
});
return true;
});
You probably want to use Javascript to set a value for each checkbox "switch" in one of two ways:
Option 1: in the html of the switch elements/checkboxes, set the value attribute to zero by default. Then add a javascript click handler for the toggle to check its current value and toggle to the opposite state/value.
Option 2: add Javascript to the form's submit handler (on submit) that checks for any switch elements which have no values and set them to zero before processing form.
Either way should pass a value at all times, and your form should be able to keep track of all input states.
This snippet did the trick, as Anson suggested this finds all the checkboxes and sets them to either on or off on form submission:
$('form').submit(function () {
$(this).find('input[type="checkbox"]').each( function () {
var checkbox = $(this);
if( checkbox.is(':checked')) {
checkbox.attr('value','1');
} else {
checkbox.after().append(checkbox.clone().attr({type:'hidden', value:0}));
checkbox.prop('disabled', true);
}
})
});

Checking whether a checkbox is checked

I have not found any inbuilt function for checking whether a checkbox is set true or false,
isChecked() is not available is apps-script (if i am right).
Any idea on how to find it or we shall have a value change handler to count the number of times the value changed and find if it is checked or not?
You should assign your checkbox a name so that you can retrieve its value in a handler function with e.parameter.checkboxname : this value is boolean.
var chkmode = app.createCheckBox("description").setName("chk1").setId("chk1")
with the ID you can modify its state from the handler function (or from any other) if necessary (getElementbyId())
note that the handler can be on the checkbox itself (a change handler) or on any other element in the UI, depending on your needs.
I might be wrong, however I believe there is a problem with the checkBox status, even though its status looks like boolean, it doesn't behave like boolean but like string
if you print in a spreadsheet e.parameter.myCheckBox you will get TRUE or FALSE
if you print in a spreadsheet e.parameter you will get the whole object and see myCheckBox=true or myCheckBox=false
however, if (e.parameter.myCheckBox) will always return True
the workaround I am using is: if (e.parameter.myCheckBox == "true") will return the actual myCheckBox status
Just in case, I am opening a new ticket in the issue tracker
I hope this would help you
ps. confirmed with Google, e.parameter.myCheckBox is a string, not a boolean
if you want to use it as boolean it would be like (e.parameter.myCheckBox == "true")
var handler = app.createServerClickHandler('tellStatus');
and then (as example showing it in a label)
function tellStatus(e){
var app = UiApp.getActiveApplication();
app.getElementById('yourStatusLabel').setText('Checkbox checked: ' + e.parameter.yourCheckbox)
return app;
}
You should use handler function look like below.
I found example from https://sites.google.com/site/scriptsexamples/learn-by-example/uiapp-examples-code-snippets/check-box
if(e.parameter['checkbox_isChecked_'] == 'true'){
itemsSelected+= e.parameter['checkbox_value_']+',';
}