I have a form that calculates as it is filled. I want to fill that form via casper and get the result.
In my form, I am doing the calculation on blur of each field. How can I fire a blur event using casperJS?
According to the specs you can just trigger native blur function:
casper.evaluate(function(){
document.querySelector('.some-element').blur();
});
Consider this simple HTML form:
<form id="example">
<input name="value_one" type="text" onblur="addition()">
<input name="value_two" type="text" onblur="addition()">
</form>
Let's say that the following JavaScript function is fired onblur:
function addition() {
var value_one = document.getElementsByName('value_one')[0].value;
var value_two = document.getElementsByName('value_two')[0].value;
var result = document.getElementById('result');
result.textContent = parseInt(value_one) + parseInt(value_two);
}
You can use the following CasperJS script to obtain the result:
var casper = require('casper').create();
casper.start('https://www.example.com/', function () {
this.fill('#example', {
value_one: '5',
value_two: '10',
});
this.echo(this.getElementInfo('#result').text); // Result: 15
});
casper.run();
Related
I have a form that is passing a string to a search page that uses that string to query an API and display results. When I submit the form, the URL is x/search/string?slug=string. I am looking for a way to keep the URL cleaner and have it be x/search/string.
My form code:
<script lang="ts">
let slug = '';
</script>
<form action={`search/${slug}`}>
<input bind:value={slug} name="slug" type="text" />
<button type="submit" />
</form>
My +page.server.ts code:
export const load: PageServerLoad = async ({fetch, params}) =>{
const fetchSearchResults = async (slug:string) => {
const res = await fetch(`https://openlibrary.org/search.json?q=${slug}`)
const data = await res.json();
return {data};
}
return {
results: fetchSearchResults(params.slug)
}
}
The URL x/search/string?slug=string provides the same results as x/search/string but I am positive I am doing something wrong. Any help or links to some examples that would help would be greatly appreciated.
The input in the form is sent as part of the form request, for GET that results in query parameters.
There are multiple options, e.g. remove the name attribute.
You could also move the element out of the form, but I would not recommend that, as it breaks things like being able to press Enter to submit the form.
I am using Date Range Picker to select to dates now when I select the dates, I update the inputs with dates value respectively.
The inputs I have binded with v-model and created a function in watch attribute of component to observe the change in model.
But when the inputs are updated with the javascript function no change can be observed in the model but the value of my input fields are updated.
// My Input Fields
<input type="text" name="updateStartDate" v-model="updateDateRange.start">
<input type="text" name="updateEndDate" v-model="updateDateRange.end">
//My javascript Function
$('input[rel=dateRangePickerX]').daterangepicker({
'autoApply': true,
'drops': 'up',
'startDate': moment().add(90, 'days').calendar(),
'endDate': moment().add(97, 'days').calendar(),
locale: { cancelLabel: 'Clear' }
},
function (start, end, label) {
$('input[name="updateStartDate"]').val(start.format('MM/DD/YYYY'));
$('input[name="updateEndDate"]').val(end.format('MM/DD/YYYY'));
});
// My watch attribute in Component
watch : {
'updateDateRange.end' : function (val) {
console.log('In Watch Function');
console.log(this.dateRanges);
if(val != '' && this.updateDateRange.start != '' && this.updateDateRangeIndex != ''){
console.log(val);
console.log(this.updateDateRange.start);
console.log(this.updateDateRangeIndex);
this.dateRanges[this.updateDateRangeIndex] = this.updateDateRange;
this.updateDateRangeIndex = '';
this.updateDateRange.start = '';
this.updateDateRange.end = '';
console.log(this.dateRanges);
}
}
}
I don't like to mix jQuery and Vue because jQuery messes up the DOM. Even more, I find it completely unnecessary.
Simple only with native Vue you can do it like this:
<input type="text" name="updateStartDate" v-model="startDate" #input="onInput()">
<input type="text" name="updateStartDate" v-model="endDate" #input="onInput()">
methods: {
onInput(e): function () {
// this will be called on change of value
}
}
Further to set the value and update the DOM simply update startDate and/or endDate variables and DOM will update accordingly.
You need to work with your model and not fiddle with the bound DOM element. You have bound the elements to viewmodel items:
<input type="text" name="updateStartDate" v-model="updateDateRange.start">
<input type="text" name="updateEndDate" v-model="updateDateRange.end">
then you use jQuery to set the field values
$('input[name="updateStartDate"]').val(start.format('MM/DD/YYYY'));
$('input[name="updateEndDate"]').val(end.format('MM/DD/YYYY'));
but you should be setting the bound values instead:
updateDateRange.start = start.format('MM/DD/YYYY');
updateDateRange.end = end.format('MM/DD/YYYY');
I've written a class that extends dijit.Tree to include a radio button alongside each node. I'm using it in a form to show a folder tree from which the user can select a folder. Here is the code:
define("my/Tree/RadioButton",
['dojo/_base/declare', 'dijit/Tree', 'dijit/form/RadioButton', 'dojo/dom-construct', 'dojo/_base/connect', 'dojo/on', 'dojo/_base/lang'],
function (declare, Tree, RadioButton, domConstruct, connect, on, lang){
var TreeNode = declare(Tree._TreeNode, {
_radiobutton: null,
postCreate: function(){
this._createRadioButton();
this.inherited(arguments);
},
_createRadioButton: function(){
this._radiobutton = new RadioButton({
name: this.tree.name,
value: this.tree.model.store.getIdentity(this.item) + '',
checked: false
});
domConstruct.place(this._radiobutton.domNode, this.iconNode, 'before');
if (this.tree.model.store.hasAttribute(this.item, 'checked')) {
var attrValue = this.tree.model.store.getValue(this.item, 'checked');
if (attrValue === true) {
this._radiobutton.set('checked', true);
}
}
connect.connect(this._radiobutton, 'onClick', this, function(){
// set any checked items as unchecked in the store
this.tree.model.store.fetch({
query: {checked: true},
onItem: lang.hitch(this.tree.model.store, function(item){
console.log('found checked item ' + this.getValue(item, 'name'));
this.setValue(item, 'checked', false);
})
});
// check the one that was clicked on
var radioValue = this._radiobutton.get('value');
this.tree.model.store.setValue(this.item, 'checked', true);
});
}
});
return declare(Tree, {
_createTreeNode: function(/*Object*/ args){
return new TreeNode(args);
}
});
});
The issue is that when the form is submitted, the value that is submitted is always the value of the first radio button that was selected, even if other radio buttons are subsequently clicked on.
I can see by inspecting the dom that the value attribute for the checked radio button has the correct value. But what gets submitted is always the initially selected value.
I have a similar class that uses the checkbox widget instead and that one works fine.
Edit based on some feedback I created an even simpler version of this class that doesn't track the checked state using attribute in the store:
define("my/Tree/RadioButton",
['dojo/_base/declare', 'dijit/Tree', 'dijit/form/RadioButton', 'dojo/dom-construct'],
function (declare, Tree, RadioButton, domConstruct){
var TreeNode = declare(Tree._TreeNode, {
_radiobutton: null,
postCreate: function(){
this._createRadioButton();
this.inherited(arguments);
},
_createRadioButton: function(){
this._radiobutton = new RadioButton({
name: this.tree.name,
value: this.tree.model.store.getIdentity(this.item) + '',
checked: false
});
domConstruct.place(this._radiobutton.domNode, this.iconNode, 'before');
}
});
return declare(Tree, {
_createTreeNode: function(/*Object*/ args){
return new TreeNode(args);
}
});
});
but even this still has the same issue - whichever radio button the user clicks on first is the value that will be submitted, regardless of what other buttons are subsequently clicked.
I managed to workaround this issue by hooking on to the onchange event for the radio buttons. The hook explicitly sets checked to false on the unchecked radio button, which seems to fix the problem. I'm unsure why this is required though.
I have this exact same problem. It used to work in older Dojos. Specifically, ALL of the radioButtons incorrectly return true on "dijit.byId("whatever").checked" during the onClicked function. When checked manually after the onClicked function finishes using FireBug console, the above property returns the correct values. I think it is a bug, and I only worked around it by having a different onClicked function for each button, like so:
<form id="locateForm">
<label for="locate">Locate:</label><br />
<input type="radio" dojoType="dijit.form.RadioButton" name="locate" id="locateAddress" value="Address" checked="checked" onClick="enableLocate1();" />
<label for="locateAddress">Address</label>
<input type="radio" dojoType="dijit.form.RadioButton" name="locate" id="locatePlace" value="Place" onClick="enableLocate2();" />
<label for="locatePlace">Place</label>
</form>
I have a page with 7 dijit FilteringSelect widgets that I want to connect to stores fetched from the server if the user clicks on the widget or the widget otherwise gains focus. I want the event to fire one time.
If I add onfocus="loadDropDown(this)" to my markup, it executes every time the widget gains focus, as you would expect.
I'm trying to use dojo to fire the event one time using on.once(). The function to use dojo event handling is running but the event handler function never gets called when a widget gains focus.
Any pointers?
This is my markup
<select data-dojo-type="dijit.form.FilteringSelect"
type="text" intermediateChanges="false"
data-dojo-props="required:false, pageSize:20, placeholder: '---'"
scrollOnFocus="true" name="CJ1lxA" style="width: 40em;"
id="searchAgency">
</select>
This is to regester the events
function registerDDLoad(){
require(["dojo/on", "dijit", "dojo/ready"], function(on, dijit, ready){
ready(function(){
var dropDown = dijit.byId("searchAgency");
on.once(dropDown, "onfocus", function() {
loadDropDown(dropDown);
});
dropDown = dijit.byId("searchLocation");
on.once(dropDown, "onfocus", function() {
loadDropDown(dropDown);
});
dropDown = dijit.byId("searchCounty");
on.once(dropDown, "onfocus", function() {
loadDropDown(dropDown);
});
dropDown = dijit.byId("searchRep");
on.once(dropDown, "onfocus", function() {
loadDropDown(dropDown);
});
dropDown = dijit.byId("searchSenate");
on.once(dropDown, "onfocus", function() {
loadDropDown(dropDown);
});
dropDown = dijit.byId("searchStatus");
on.once(dropDown, "onfocus", function() {
loadDropDown(dropDown);
});
dropDown = dijit.byId("searchAE");
on.once(dropDown, "onfocus", function() {
loadDropDown(dropDown);
});
});
});
}
registerDDLoad();
The dojo event class, dojo/on expects events to be specified without the 'on':
onFocus = focus
onClick = click
onMouseOut = mouseout
...
I think changing that should fix your problem. I've copied your code into test area on jsFiddle, so you can play around with it.
NB: Since you are re-using the dropdown variable, it will always equal the last filteringSelect (id=searchAE) and never the earlier ones.
I need to create a function with this:
onMouseDown to add that class,onChange that other class and onBlur last class.
With ".animate" is more wonderful, but is ok even without.
onMouseDown="this.className='styleDropDownClick';
onChange="this.className='styleDropDown'";
onBlur="this.className='styleDropDown';
If anyoane can help me , thank's.
Try the following functions:
function styleDropDownClick() {
var textForm = document.forms["textForm"];
textForm.fname.setAttribute("class", "styleDropDownClick");
}
function styleDropDown() {
var textForm = document.forms["textForm"];
textForm.fname.setAttribute("class", "styleDropDown");
}
This works with the following HTML:
<form id="textForm">
<input type="text" class="styleDropDown" name="fname"
onBlur="styleDropDown()" onChange="styleDropDown()" onMouseDown="styleDropDownClick()" value="test"/>
<input type="text" class="styleDropDown" name="fname2" value="test2"/>
</form>
Fixed! My problew was that the child of select is not expanding with auto width or a given width.
$("select").click(function () {
$(this).children().addClass("cooling");
});
here is an example, it works only for IE
http://jsfiddle.net/DCjYA/132/