How test Select2(Multi-select) in protractor? - protractor

I have a Select2(Multi-select),I want to type admin and select it.
this my HTML code :
<select class="js-select2" multiple="multiple">
<option> admin </option>
<option> John Doe </option>
</select>
this is my test code :
describe('when select admin and press save button', function () {
beforeAll(function () {
browser.get('http://example');
element(by.css("*[id='technician'] + span.select2")).click();
browser.sleep(1000);
element(by.css(".select2-search__field")).sendKeys('admin');
browser.sleep(1000);
element(by.css('.select2-results__options li:nth-of-type(1)')).click();
element(by.buttonText('save')).click();
});
it('You must see a successful message', function () {
expect(element(by.css(".alert")).getText()).toContain('Settings saved successfully');
});
});
When I execute the code, Protractor gives this message :
Failed: element not interactable
Where did i make mistakes ? and What should i do ?

Select2 is a jQuery plugin, which implement dropdown with css & javascript, it's not native dropdown which implement purely by select.
For such CSS dropdown, the visible option does not comes from select and the select is invisible or visible but with very small size (like 1 * 1 size) prevent user to operate it.
Below code example test on the demo from Select2 site
describe('handsontable', function(){
it('input text into cell', function(){
browser.ignoreSynchronization = true;
browser.get('https://select2.org/selections');
browser.sleep(3000);
// click to make the input box and options display out
element(by.css('select.js-example-basic-multiple-limit + span' +
' .select2-selection--multiple')).click();
browse.sleep(1000);
element(by.css("select.js-example-basic-multiple-limit + span input"))
.sendKeys('Hawaii');
element(by.xpath("//li[#role='treeitem'][text()='Hawaii']")).click();
browser.sleep(3000);
});
})

Related

PopUp closes before showing Contact Form 7's after submit text

I am using elementor's popup in wordpress to show my CF7 form. My issue is that the popup closes before it can show the after submit confirmation text.
What could I do in such a situation? That text is very important.
You need to reinitialize the form after the opening of the popup.
You can add a html widget in the page where the popup opens (Or in the footer, if opens in any part of the website) and paste the following code:
<script>
window.addEventListener('DOMContentLoaded', function() {
// More information about elementor popup events
// here https://developers.elementor.com/elementor-pro-2-7-popup-events/
jQuery(document).on('elementor/popup/show', () => {
wpcf7.init(jQuery(".wpcf7-form")[0]);
});
});
</script>
Or even modify the functions.php (In the child theme if is necessary):
// Stop Elementor Popup from Closing after CF7 submission with no validation
function elementor_popup_cf7_fix() {
?>
<script type='text/javascript'>
window.addEventListener('DOMContentLoaded', function() {
jQuery(document).on('elementor/popup/show', () => {
for(var i = 0; i < jQuery(".wpcf7-form").length ; i++) {
wpcf7.init(jQuery(".wpcf7-form")[i]);
}
});
});
</script>
<?php
}
add_action( 'wp_footer', 'elementor_popup_cf7_fix' );
Source: https://github.com/elementor/elementor/issues/7798

Select: Limit number of selected options

I'm using ANT Design's Select component in multiple select mode. After two options are selected (see screenshot) I'd like to prevent any more from being selected. The field should not be disabled, so that you can deselect an option and select another.
I've tried the onFocus event, but it doesn't provide an event that I could use to preventDefault or otherwise keep from opening the dropdown. I've also tried adding a ref and calling blur() whenever the onFocus event is called. This closes the dropdown, but it's still visible for a second.
Does anyone know of a way to accomplish this?
If 3 or more options selected then with a simple condition you can disable other options.
Store selected options in state and while displaying options disable them based on condition.
https://codesandbox.io/s/happy-leftpad-lu84g
Sample code
import React, { useState } from "react";
import { Select } from "antd";
const { Option } = Select;
const opts = ["a11", "b12", "c13", "d14", "e15"];
const Selectmultiple = () => {
const [optionsSelected, setOptionsSelected] = useState([]);
const handleChange = value => {
console.log(`selected ${value}`);
setOptionsSelected(value);
};
return (
<div>
<Select
mode="multiple"
style={{ width: "100%" }}
placeholder="Please select"
onChange={handleChange}
>
{opts.map(item => (
<Option
disabled={
optionsSelected.length > 1
? optionsSelected.includes(item)
? false
: true
: false
}
key={item}
>
{item}
</Option>
))}
</Select>
</div>
);
};
I solved this problem using "open" prop:
const isMaxValues = value.length === limit;
<Select
mode="multiple"
disabled={false}
{...(isMaxValues && { open: false, onDropdownVisibleChange: handleShowError })}
>
{renderOptions()}
</Select>
So you still able to remove/deselect some options
Also you can provide isMaxValues option to renderOptions method and disable Options to be selected(if you need dropdown to be visible)

How implementing a directive to validate another field (custom form in angularjs)

I have a validation custom form, I use validate-message-character="{{compose.limitCharacter - compose.message.length}}" in a select and textarea like this
<form class="form-horizontal" role="form" name="composeForm" >
<select ng-change="limitComposeCharacter()" ng-selected="compose.profile"
ng-model="compose.profile" ng-options="userId in profiles" name="profile"
validate-message-character="{{compose.limitCharacter - compose.message.length}}" required>
</select>
number Character: {{compose.limitCharacter - compose.message.length}}
<textarea class="form-control" ng-model="compose.message" name="message"
validate-message-character="{{compose.limitCharacter - compose.message.length}}"
required></textarea>
Form validity: {{composeForm.$valid}}
I have something like this:
1° Select User has compose.limitCharacter = 100
2° Select User has compose.limitCharacter = 200 etc etc.
This is my directive to check number Character is > 0
angular.module('App')
.directive('validateMessageCharacter', function () {
return {
require: 'ngModel',
link: function postLink(scope, element, attrs, c) {
scope.$watch(attrs.ngModel, function() {
console.log(attrs.validateMessageCharacter);
if(attrs.validateMessageCharacter < 0)
{
c.$setValidity('maxCharacter', false);
c.$invalid = true;
}else{
c.$setValidity('maxCharacter', true);
c.$invalid = false;
}
});
}
};
});
It doesn't work proply when change select without change the textarea
some advice?
First, using an advice from the angular google group, I changed the scope.$watch to attr.$observe.
Second, the reason it validated only after typing text is that the text area is a required field.
Your code works here:
http://plnkr.co/edit/YvsuLoHzX9eqb7FhDgXA?p=preview

mootools select box focus

I have a select box
<select>
<option value="0">0 mins</option>
<option value="1">1 mins</option>
<option value="2">2 mins</option>
</select>
and I want to fire an event when the visitor either clicks on a value or clicks anywhere else on the page -i.e loss of focus on the select box
I've fiddled about for four hours now with no joy. I'm now down to this:
var c = 0;
$("selectTime").addEvent('click', function() {
if (c++ % 2 == 1) {
console.log(c);
//$(this).blur();
}
});
$('selectTime').click(function() {
if ($('select').is(':blur')) {
c = 1;
} else {
c = 0;
}
});
any ideas?
thanks
The mootools syntax for adding multiple events to same element is:
$('myElementID').addEvents({
blur: function(){
alert('blur');
},
click: function(){
alert('click');
}
});
Example with you code
You could though use just the change event, which fires when the element is changed. Like:
$('myElement').addEvent('change', function(){
alert('Select changed');
});
Example
Note that part of your code is using jQuery syntax, part is using MooTools syntax.

Google Autocomplete - enter to select

I have Google Autocomplete set up for a text field of an HTML form, and it's working perfectly.
However, when the list of suggestions appear, and you use the arrows to scroll and select using enter, it submits the form, though there are still boxes to fill in. If you click to select a suggestion it works fine, but pressing enter submits.
How can I control this? How can I stop enter from submitting the form, and instead be the selection of a suggestion from autocomplete?
Thanks!
{S}
You can use preventDefault to stop the form being submitted when enter is hit, I used something like this:
var input = document.getElementById('inputId');
google.maps.event.addDomListener(input, 'keydown', function(event) {
if (event.keyCode === 13) {
event.preventDefault();
}
});
Using the Google events handling seems like the proper solution but it's not working for me. This jQuery solution is working for me:
$('#inputId').keydown(function (e) {
if (e.which == 13 && $('.pac-container:visible').length) return false;
});
.pac-container is the div that holds the Autocomplete matches. The idea is that when the matches are visible, the Enter key will just choose the active match. But when the matches are hidden (i.e. a place has been chosen) it will submit the form.
I've amalgamated the first two answers from #sren and #mmalone to produce this:
var input= document.getElementById('inputId');
google.maps.event.addDomListener(input, 'keydown', function(e) {
if (e.keyCode == 13 && $('.pac-container:visible').length) {
e.preventDefault();
}
});
works perfectly on the page. prevents the form from being submitted when the suggestion container (.pac-container) is visible. So now, an option from the autocomplete dropdown is selected when the users presses the enter key, and they have to press it again to submit the form.
My main reason for using this workaround is because I found that if the form is sent as soon as an option is selected, via the enter key, the latitude and longitude values were not being passed fast enough into their hidden form elements.
All credit to the original answers.
This one worked for me:
google.maps.event.addDomListener(input, 'keydown', e => {
// If it's Enter
if (e.keyCode === 13) {
// Select all Google's dropdown DOM nodes (can be multiple)
const googleDOMNodes = document.getElementsByClassName('pac-container');
// Check if any of them are visible (using ES6 here for conciseness)
const googleDOMNodeIsVisible = (
Array.from(googleDOMNodes).some(node => node.offsetParent !== null)
);
// If one is visible - preventDefault
if (googleDOMNodeIsVisible) e.preventDefault();
}
});
Can be easily converted from ES6 to any browser-compatible code.
The problem I had with #sren's answer was that it blocks the submit event always. I liked #mmalone's answer but it behaved randomly, as in sometimes when I hit ENTER to select the location, the handler ran after the container is hidden. So, here's what I ended up doing
var location_being_changed,
input = document.getElementById("js-my-input"),
autocomplete = new google.maps.places.Autocomplete(input),
onPlaceChange = function () {
location_being_changed = false;
};
google.maps.event.addListener( this.autocomplete,
'place_changed',
onPlaceChange );
google.maps.event.addDomListener(input, 'keydown', function (e) {
if (e.keyCode === 13) {
if (location_being_changed) {
e.preventDefault();
e.stopPropagation();
}
} else {
// means the user is probably typing
location_being_changed = true;
}
});
// Form Submit Handler
$('.js-my-form').on('submit', function (e) {
e.preventDefault();
$('.js-display').text("Yay form got submitted");
});
<p class="js-display"></p>
<form class="js-my-form">
<input type="text" id="js-my-input" />
<button type="submit">Submit</button>
</form>
<!-- External Libraries -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="//maps.googleapis.com/maps/api/js?sensor=false&libraries=places"></script>
The flag ensures that if the location is being changed & user hits enter, the event is blocked. Eventually the flag is set to false by google map's place_changed event, which then allows the form to be submitted on hitting the enter key.
Here's a simple code that worked well for me (uses no jquery).
const googleAutcompleteField = this.renderer.selectRootElement(this.elem.nativeElement);
this.selectOnEnter(googleAutcompleteField);
This piece of code, to follow the code above, is used to implement google maps autocomplete (with or without the Enter key functionality sought in this question):
this.autocomplete = new google.maps.places.Autocomplete(googleAutcompleteField, this.googleMapsOptions);
this.autocomplete.setFields(['address_component', 'formatted_address', 'geometry']);
this.autocomplete.addListener('place_changed', () => {
this.zone.run(() => {
this.googleMapsData.emit([this.autocomplete.getPlace()]);
})
})
selectOnEnter (called above in the first piece of code) defined:
selectOnEnter(inputField) {
inputField.addEventListener("keydown", (event) => {
const selectedItem = document.getElementsByClassName('pac-item-selected');
if (event.key == "Enter" && selectedItem.length != 0) {
event.preventDefault();
}
})
}
This code makes the google maps autocomplete field select whichever item user selects with the down arrow keypress. Once user selects an option with a press of the Enter key, nothing happens. User has to press Enter again to trigger onSubmit() or other command
You can do it in vanilla :
element.addEventListener('keydown', function(e) {
const gPlaceChoices = document.querySelector('.pac-container')
// No choices element ?
if (null === gPlaceChoices) {
return
}
// Get choices visivility
let visibility = window.getComputedStyle(gPlaceChoices).display
// In this case, enter key will do nothing
if ('none' !== visibility && e.keyCode === 13) {
e.preventDefault();
}
})
I tweaked Alex's code, because it broke in the browser. This works perfect for me:
google.maps.event.addDomListener(
document.getElementById('YOUR_ELEMENT_ID'),
'keydown',
function(e) {
// If it's Enter
if (e.keyCode === 13) {
// Select all Google's dropdown DOM nodes (can be multiple)
const googleDOMNodes = document.getElementsByClassName('pac-container');
//If multiple nodes, prevent form submit.
if (googleDOMNodes.length > 0){
e.preventDefault();
}
//Remove Google's drop down elements, so that future form submit requests work.
removeElementsByClass('pac-container');
}
}
);
function removeElementsByClass(className){
var elements = document.getElementsByClassName(className);
while(elements.length > 0){
elements[0].parentNode.removeChild(elements[0]);
}
}
I've tried the above short answers but they didn't work for me, and the long answers I didn't want to try them, so I've created the following code which worked pretty well for me. See Demo
Suppose this is your form:
<form action="" method="">
<input type="text" name="place" id="google-places-searchbox" placeholder="Enter place name"><br><br>
<input type="text" name="field-1" placeholder="Field 1"><br><br>
<input type="text" name="field-2" placeholder="Field 2"><br><br>
<button type="submit">Submit</button>
</form>
Then the following javascript code will solve the problem:
var placesSearchbox = $("#google-places-searchbox");
placesSearchbox.on("focus blur", function() {
$(this).closest("form").toggleClass('prevent_submit');
});
placesSearchbox.closest("form").on("submit", function(e) {
if (placesSearchbox.closest("form").hasClass('prevent_submit')) {
e.preventDefault();
return false;
}
});
And here is how the full code looks like in the HTML page (Note that you need to replace the YOUR_API_KEY with your google api key):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Prevent form submission when choosing a place from google places autocomplete searchbox</title>
</head>
<body>
<form action="" method="">
<input type="text" name="place" id="google-places-searchbox" placeholder="Enter place name"><br><br>
<input type="text" name="field-1" placeholder="Field 1"><br><br>
<input type="text" name="field-2" placeholder="Field 2"><br><br>
<button type="submit">Submit</button>
</form>
<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<!-- Google Maps -->
<!-- Note that you need to replace the next YOUR_API_KEY with your api key -->
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places"
async defer></script>
<script>
var input = document.getElementById("google-places-searchbox");
var searchBox = new google.maps.places.SearchBox(input);
var placesSearchbox = $("#google-places-searchbox");
placesSearchbox.on("focus blur", function() {
$(this).closest("form").toggleClass('prevent_submit');
});
placesSearchbox.closest("form").on("submit", function(e) {
if (placesSearchbox.closest("form").hasClass('prevent_submit')) {
e.preventDefault();
return false;
}
});
</script>
</body>
</html>
$("#myinput").on("keydown", function(e) {
if (e.which == 13) {
if($(".pac-item").length>0)
{
$(".pac-item-selected").trigger("click");
}
}
Use $('.pac-item:first').trigger('click'); if you want to select first result