Only number appears in the phone field of the form - wordpress

I have a form on this site that I'm going to leave the link to, I managed to put a code to create a phone mask in the field, but I need the user to type only numbers and not letters.
if anyone can help i would appreciate it.
Link Form: https://www.viverbemcorretora.com.br/
The site was created in wordpress
this is the js code of the website:
(function ($, window, document, undefined) {
"use strict";
const input = document.querySelector(".phone");
const forminator_number_format = {
run: function (event, form_id) {
var _form = "#forminator-module-" + form_id,
_form_el = $(_form);
if (0 === _form_el.length) return;
// Custom Phone Format = xxx-xxx-xxxx
let _phones = _form_el.find(".phone .forminator-input");
if (_phones.length) {
_phones.each(function () {
let _id = _form + " #" + $(this).attr("id");
new Cleave(_id, {
// prefix: '+',
delimiters: ["(", ") ", "-"],
blocks: [0, 2, 5, 4],
uppercase: true,
});
});
}
},
};
$(document).ready(function () {
$(document).on("after.load.forminator", forminator_number_format.run);
$(".forminator-custom-form").each(function () {
forminator_number_format.run(null, $(this).data("form-id"));
});
});
})(jQuery, window, document);

Listen for the key pressed and check against an array of valid keys, like all numbers (numbers and keypad), backspace and delete. If not one of those then preventDefault();
let phoneInput = document.querySelector('#input-phone');
let validKeys = [8,46,48,49,50,51,52,53,53,54,55,56,57,96,97,98,99,100,101,102,103,104,105]
phoneInput.addEventListener('keydown', (e) => {
let pressedKey = e.keyCode
if (!validKeys.includes(pressedKey)) {
e.preventDefault();
}
})
<label for="phone">Phone:</label>
<input type="text" name="phone" id="input-phone" />

Related

Simple pug html form, make it send immediately on change of value rather than wait for submit button

I have a very simple pug file:
for item in itemList
form(method='post', action='/change')
table
tr
td(width=100)
td(width=200)
| #{item.name}
input(type='hidden', name='field' value=item.name)
input(type='hidden', name='style' value='doublevalue')
td(width=100)
input(type='number', name='value' min=-20.0 max=80.00 step=0.01 value=+item.value)
td(width=100)
input(type='submit', value='Update')
p end
As you can see it produces a few trivial forms like this:
(Each form is one 'line' which is a simple table.)
(On the script side, it just reads each 'line' from a MySQL table, there are 10 or so of them.)
So on the www page, the user either
types in new number (say "8")
or clicks the small arrows (say Up, changing it to 7.2 in the example)
then the user must
click submit
and it sends the post.
Quite simply, I would like it to be that when the user
clicks a small arrows (say Up, changing it to 7.2 in the example)
it immediately sends a submit-post.
How do I achieve this?
(It would be fine if the send happens, any time the user types something in the field, and/or, when the user clicks the Small Up And Down Buttons. Either/both is fine.)
May be relevant:
My pug file (and all my pug files) have this sophisticated line of code as line 1:
include TOP.pug
And I have a marvellous file called TOP.pug:
html
head
style.
html {
font-family: sans-serif
}
td {
font-family: monospace
}
body
I have a solution with javascript.
// check if there are input[type="number"] to prevent errors
if (document.querySelector('input[type="number"]')) {
// add event for each of them
document.querySelectorAll('input[type="number"]').forEach(function(el) {
el.addEventListener('change', function (e) {
// on change submit the parent (closest) form
e.currentTarget.closest('form').submit()
});
});
}
Actually it is short but if you want to support Internet Explorer you have to add the polyfill script too. Internet Explorer does not support closest() with this snippet below we teach it.
// polyfills for matches() and closest()
if (!Element.prototype.matches)
Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
if (!Element.prototype.closest) {
Element.prototype.closest = function(s) {
var el = this;
do {
if (el.matches(s)) return el;
el = el.parentElement || el.parentNode;
} while (el !== null && el.nodeType === 1);
return null;
};
}
Ajax form submit to node.js
If you are interested in an ajax solution I put some code below just to blow your mind ;-) It should work instantly, I use it on one of my sites. You could use jQuery and save lines of code but I like it pure. (The ajax function and polyfills are utils so paste it anywhere)
HTML (example)
<form>
<input type="hidden" name="field" value="field1">
<input type="hidden" name="style" value="style1">
<input type="number" name="value">
<input type="submit" value="update">
</form>
<form>
<input type="hidden" name="field" value="field2">
<input type="hidden" name="style" value="style2">
<input type="number" name="value">
<input type="submit" value="update">
</form>
Javascript: event listener and prepare ajax call (note the callbacks).
// check if there are forms to prevent errors
if (document.querySelector('form')) {
// add submit event for each form
document.querySelectorAll('form').forEach(function (el) {
el.addEventListener('submit', function (e) {
e.currentTarget.preventDefault();
submitData(e.currentTarget);
});
});
}
// check if there are input[type="number"] to prevent errors
if (document.querySelector('input[type="number"]')) {
// add change event for each of them
document.querySelectorAll('input[type="number"]').forEach(function (el) {
el.addEventListener('change', function (e) {
submitData(e.currentTarget.closest('form'));
});
});
}
// collect form data and send it
function submitData(form) {
// send data through (global) ajax function
ajax({
url: '/change',
method: 'POST',
data: {
field: form.querySelector('input[name="field"]').value,
style: form.querySelector('input[name="style"]').value,
value: form.querySelector('input[name="value"]').value,
},
// callback on success
success: function (response) {
// HERE COMES THE RESPONSE
console.log(response);
// error is defined in (node.js res.json({error: ...}))
if (response.error) {
// make something red
form.style.border = '1px solid red';
}
if (!response.error) {
// everything ok, make it green
form.style.border = '1px solid green';
}
// remove above styling
setTimeout(function () {
form.style.border = 'none';
}, 1000);
},
// callback on error
error: function (error) {
console.log('server error occurred: ' + error)
}
});
}
As told javascript utils (paste it anywhere like a library)
// reusable ajax function
function ajax(obj) {
let a = {};
a.url = '';
a.method = 'GET';
a.data = null;
a.dataString = '';
a.async = true;
a.postHeaders = [
['Content-type', 'application/x-www-form-urlencoded'],
['X-Requested-With', 'XMLHttpRequest']
];
a.getHeaders = [
['X-Requested-With', 'XMLHttpRequest']
];
a = Object.assign(a, obj);
a.method = a.method.toUpperCase();
if (typeof a.data === 'string')
a.dataString = encodeURIComponent(a.data);
else
for (let item in a.data) a.dataString += item + '=' + encodeURIComponent(a.data[item]) + '&';
let xhReq = new XMLHttpRequest();
if (window.ActiveXObject) xhReq = new ActiveXObject('Microsoft.XMLHTTP');
if (a.method == 'GET') {
if (typeof a.data !== 'undefined' && a.data !== null) a.url = a.url + '?' + a.dataString;
xhReq.open(a.method, a.url, a.async);
for (let x = 0; x < a.getHeaders.length; x++) xhReq.setRequestHeader(a.getHeaders[x][0], a.getHeaders[x][1]);
xhReq.send(null);
}
else {
xhReq.open(a.method, a.url, a.async);
for (let x = 0; x < a.postHeaders.length; x++) xhReq.setRequestHeader(a.postHeaders[x][0], a.postHeaders[x][1]);
xhReq.send(a.dataString);
}
xhReq.onreadystatechange = function () {
if (xhReq.readyState == 4) {
let response;
try {
response = JSON.parse(xhReq.responseText)
} catch (e) {
response = xhReq.responseText;
}
//console.log(response);
if (xhReq.status == 200) {
obj.success(response);
}
else {
obj.error(response);
}
}
}
}
// (one more) polyfill for Object.assign
if (typeof Object.assign !== 'function') {
// Must be writable: true, enumerable: false, configurable: true
Object.defineProperty(Object, 'assign', {
value: function assign(target, varArgs) {
// .length of function is 2
if (target === null || target === undefined) {
throw new TypeError('Cannot convert undefined or null to object');
}
var to = Object(target);
for (var index = 1; index < arguments.length; index++) {
var nextSource = arguments[index];
if (nextSource !== null && nextSource !== undefined) {
for (var nextKey in nextSource) {
// Avoid bugs when hasOwnProperty is shadowed
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
to[nextKey] = nextSource[nextKey];
}
}
}
}
return to;
},
writable: true,
configurable: true
});
}
// polyfills for matches() and closest()
if (!Element.prototype.matches)
Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
if (!Element.prototype.closest) {
Element.prototype.closest = function (s) {
var el = this;
do {
if (el.matches(s)) return el;
el = el.parentElement || el.parentNode;
} while (el !== null && el.nodeType === 1);
return null;
};
}
In node.js (e.g. express route)
// the route in node.js
app.post('/change', (req, res) => {
// your logic here
let field = req.body.field;
let style = req.body.style;
let value = req.body.value;
// ...
// response result
res.json({
databaseError: false, // or true
additionalStuff: 'message, markup and other things ...',
});
});

Ionic refresher get's fired automatically on page load?

Ionic refresher seems to be refreshing the page without being manually calling the doRefresh. I would like the refresher to only execute when the "pull down" action is done.
Seems like doRefresh is executed on "ionviewdidload" function automatically.
<ion-refresher (ionRefresh)="doRefresh($event);">
<ion-refresher-content
pullingText="Pull to refresh" pullingIcon="arrow-dropdown"
refreshingSpinner="circles"
refreshingText="..fetching">
</ion-refresher-content>
</ion-refresher>
home.ts
doRefresh(refresher) {
console.log('the current tab that is set = ' + this.tabSelId);
console.log('testing');
this.user = JSON.parse(window.localStorage.getItem('user'));
let self_ = this;
let devicePos = null;
let devicelat = null;
let devicelong = null;
Geolocation.getCurrentPosition().then((position) => {
// self_.loadingData(devicePos);
devicelat = position.coords.latitude;
devicelong = position.coords.longitude;
self_.get_all_posts(devicelat, devicelong, self_.tabSelId);
refresher.complete();
}, (err) => {
console.log('failed to get lat and long :' + err);
self_.get_all_posts(devicelat, devicelong, self_.tabSelId);
// self_.filter_posts_by_type(self_.tabSelId);
// loading.dismiss();
// refresher.complete();
});
}
on my ionviewdidload function (home.ts):
ionViewDidLoad(){
this.user = JSON.parse(window.localStorage.getItem('user'));
let self_ = this;
let devicePos = null;
console.log('the current tab that is set = '+this.tabSelId);
let devicelat = null;
let devicelong = null;
Geolocation.getCurrentPosition().then((position) => {
devicelat = position.coords.latitude;
devicelong = position.coords.longitude;
console.log('%c executing when position is got successfully ', 'background: #222; color: #bada55');
self_.get_all_posts(devicelat, devicelong, self_.tabSelId);
console.log('executing when position is got successfully');
}, (err) => {
console.log('failed to get lat and long :' + err);
devicelat = 28.318237;
devicelong = 111.168137;
self_.get_all_posts(devicelat, devicelong, self_.tabSelId);
});
is it the default behaviour when using
"ion-refresher"
I would like the refresher to only fire when "pull down" action is done.
Don't know why the doRefresh() function is being executed when the app is loaded (the first time only)
In your Html use like..
<ion-refresher slot="fixed" (ionRefresh)="doRefresh($event)">
<ion-refresher-content pullingIcon="arrow-dropdown" pullingText="Pull to refresh" refreshingSpinner="circles"
refreshingText="Refreshing...">
</ion-refresher-content>
</ion-refresher>
In .ts use like...
doRefresh(event) {
this.userPost();
setTimeout(() => {
event.target.complete();
}, 2000);
}

Vue doesn't update when computed data change

Context: I have a list of posts with tags, categories from wordpress api. I display these posts with Vue and using computed with a search box to filter the result based on titre, description, tags, and categories
Problem: I am trying to update a computed list when user click on a list of tag available. I add the get and set for computed data like this:
var vm = new Vue({
el: '#blogs',
data: {
search: '',
posts: [],
filterPosts: []
},
beforeMount: function() {
// It should call the data and update
callData();
},
computed: {
filterPosts: {
get: function() {
var self = this;
return self.posts.filter(function(post){
var query = self.search.toLowerCase();
var title = post.title.toLowerCase();
var content = post.content.toLowerCase();
var date = post.date.toLowerCase();
var categories = '';
post.categories.forEach(function(category) {
categories += category.name.toLowerCase();
});
var tags = '';
post.tags.forEach(function(tag){
tags += tag.name.toLowerCase();
});
return title.indexOf(query) !== -1 ||content.indexOf(query) !== -1 || date.indexOf(query) !== -1 || categories.indexOf(query) !== -1 || tags.indexOf(query) !== -1;
});
},
set: function (newValue) {
console.log(newValue);
this.filterPosts = Object.assign({}, newValue);
}
}
},
methods: {
filterByTag: function(tag, event) {
event.preventDefault();
var self = this;
self.filterPosts = self.posts.filter(function(post){
var tags = '';
post.tags.forEach(function(tag){
tags += tag.name.toLowerCase();
});
return tags.indexOf(tag.toLowerCase()) !== -1;
});
}
}
}); // Vue instance
The console.log always output new data based on the function I wrote on methods but Vue didn't re-render the view. I think I didn't do the right way or thought like Vue. Could you please give some insight?
Edit 1
Add full code.
I tried to add filterPosts in data but I received this error from Vue: The computed property "filterPosts" is already defined in data.
Your setter is actually not setting anything, it only logs the new value. You need to store it somewhere.
For example you can store it in the component's data:
data: {
value: 'foo',
},
computed: {
otherValue: {
get() { /*...*/ },
set(newVal) { this.value = newVal },
},
},
But this is definitely not the only possibility, if you use Vuex, the setter can dispatch an action that will then make the computed value get updated. The component will eventually catch the update and show the new value.
computed: {
value: {
get() {
return this.$store.getters.externalData;
},
set(newVal) {
return this.$store.dispatch('modifyingAction', newVal);
},
},
},
The bottomline is you have to trigger a data change in the setter, otherwise your component will not be updated nor will it trigger any rerender.
EDIT (The original answer was updated with full code):
The answer is that unless you want to manually change the list filteredPosts without altering posts, you don't need a get and set function for your computed variable. The behaviour you want can be acheived with this:
const vm = new Vue({
data() {
return {
search: '',
posts: [],
// these should probably be props, or you won't be able to edit the list easily. The result is the same anyway.
};
},
computed: {
filteredPosts() {
return this.posts.filter(function(post) {
... // do the filtering
});
},
},
template: "<ul><li v-for='post in filteredPosts'>{{ post.content }}</li></ul>",
});
This way, if you change the posts or the search variable in data, filteredPosts will get recomputed, and a re-render will be triggered.
After going around and around, I found a solution, I think it may be the right way with Vue now: Update the computed data through its dependencies properties or data.
The set method didn't work for this case so I add an activeTag in data, when I click on a tag, it will change the activeTag and notify the computed filterPost recheck and re-render. Please tell me if we have another way to update the computed data.
var vm = new Vue({
el: '#blogs',
data: {
search: '',
posts: [],
tags: [],
activeTag: ''
},
beforeMount: function() {
// It should call the data and update
callData();
},
computed: {
filterPosts: {
get: function() {
var self = this;
return self.posts.filter(function(post){
var query = self.search.toLowerCase();
var title = post.title.toLowerCase();
var content = post.content.toLowerCase();
var date = post.date.toLowerCase();
var categories = '';
post.categories.forEach(function(category) {
categories += category.name.toLowerCase();
});
var tags = '';
post.tags.forEach(function(tag){
tags += tag.name.toLowerCase();
});
var activeTag = self.activeTag;
if (activeTag !== '') {
return tags.indexOf(activeTag.toLowerCase()) !== -1;
}else{
return title.indexOf(query) !== -1 ||content.indexOf(query) !== -1 || date.indexOf(query) !== -1 || categories.indexOf(query) !== -1 || tags.indexOf(query) !== -1;
}
});
},
set: function (newValue) {
console.log(newValue);
}
}
},
methods: {
filterByTag: function(tag, event) {
event.preventDefault();
var self = this;
self.activeTag = tag;
}
}
}); // Vue instance
Try something like:
data: {
myValue: 'OK'
},
computed: {
filterPosts: {
get: function () {
return this.myValue + ' is OK'
}
set: function (newValue) {
this.myValue = newValue
}
}
}
More:
https://v2.vuejs.org/v2/guide/computed.html#Computed-Setter

$scope issue on ngGridEventEndCellEdit event when i rollback data

I probably misunderstood something but here is my problem on plunker.
I put the relevant code here anyway:
var app = angular.module('myApp', ['ngGrid']);
app.controller('MyCtrl', function($scope) {
var cellNameEditable =
'<cell-template model=COL_FIELD input=COL_FIELD entity=row.entity></cell-template>';
var cellNameDisplay =
'<div class="ngCellText" ng-class="col.colIndex()">{{row.getProperty(col.field)}}</div>';
$scope.myData= [{"id":1,"code":"1","name":"Ain"},{"id":2,"code":"2","name":"Aisne"},{"id":3,"code":"3","name":"Allier"},{"id":4,"code":"5","name":"Hautes-Alpes"},{"id":5,"code":"4","name":"Alpes-de-Haute-Provence"},{"id":6,"code":"6","name":"Alpes-Maritimes"},{"id":7,"code":"7","name":"Ardèche"},{"id":8,"code":"8","name":"Ardennes"},{"id":9,"code":"9","name":"Ariège"},{"id":10,"code":"10","name":"Aube"}];
$scope.gridOptions = {
data: 'myData',
multiSelect: false,
enableCellSelection: true,
enableRowSelection: false,
enableCellEditOnFocus: false,
rowHeight: 100,
columnDefs: [
{field:'id', displayName:'Id', visible: false},
{field:'code', displayName:'Code', enableCellEdit:true},
{
field:'name', displayName:'Name', enableCellEdit:true,
cellTemplate: cellNameDisplay,
editableCellTemplate: cellNameEditable
}
]
};
});
app.directive('cellTemplate', function () {
var cellTemplate =
'<div><form name="myForm" class="simple-form" novalidate>' +
'<input type="text" name="myField" ng-input="localInput" ng-model="localModel" entity="entity" required/>' +
'<span ng-show="myForm.myField.$error.required"> REQUIRED</span>' +
'localModel = {{localModel}} localInput = {{localInput}} entity = {{entity}}' +
'</form></div>';
return {
template: cellTemplate,
restrict: 'E',
scope: {
localModel:'=model',
localInput:'=input',
entity:'=entity'
},
controller: function ($scope) {
$scope.$on('ngGridEventStartCellEdit', function (event) {
console.log('cellTemplate controller - ngGridEventStartCellEdit fired');
$scope.oldEntity = angular.copy(event.currentScope.entity);
$scope.oldValue = angular.copy(event.currentScope.localModel);
});
$scope.$on('ngGridEventEndCellEdit', function(event) {
console.log('ngGridEventEndCellEdit fired');
if(event.currentScope.myForm.$valid) {
if(!angular.equals($scope.oldEntity, event.currentScope.entity)) {
alert('data saved !');
}
} else {
$scope.localModel = angular.copy($scope.oldValue);
$scope.localInput = angular.copy($scope.oldValue);
$scope.entity = angular.copy($scope.oldEntity);
}
});
}
};
});
Then explanations:
I have a ng-grid and based on the official example named "Excel-like Editing
Example" but with enableCellEditOnFocus option turned to false.
The cell "name" is defined in a directive containing a form to handle
data validation before updating the model.
I want to implement this behavior: When a user put invalid data, the
directive display error message and when the user leave the field, the
directive rollback data. If everything ok then I let the data updated.
The rollback part does not work. On the given plunker line 67 to 72 (last block on the code given here) it
fails to retore data. But my binding is with "=" so it should. Or maybe
because I am on the ngGridEventEndCellEdit event it breaks the links ?
I really don't understand why it fail.
So to reproduce my issue: enter in modification on a name cell, delete
all the data, REQUIRED is shown, then go out from the cell -> model is
not rolled back.
If you use a custom template, you should emit ngGridEventEndCellEdit event.

input text return event in Meteor

I want to capture the event of a user pressing enter on an input of type="text" when they are filling out a form. This is done all over the web, yet the answer eludes me.
This is what I have so far:
In the html file, I have a text input like so:
<input type="text" size=50 class="newlink">
In the Javascript file, I am trying to capture the the user pressing enter to effectively submit the form. I am then grabbing the text from the input and going to stash it in the database:
Template.newLink.events = {
'submit input.newLink': function () {
var url = template.find(".newLink").value;
// add to database
}
};
The submit event is emitted from forms, not single input elements.
The built in event map for meteor is documented here: http://docs.meteor.com/#eventmaps.
You'll have to listen for a keyboard event (keydown, keypress, keyup). Within the event handler, check, if it's the return/enter key (Keycode 13), and proceed on success.
Template.newLink.events = {
'keypress input.newLink': function (evt, template) {
if (evt.which === 13) {
var url = template.find(".newLink").value;
// add to database
}
}
};
You could look into how this is achieved in the todos example (client/todos.js).
It uses a generic event handler for input fields (as seen below). You can browse the rest of the code for usage.
////////// Helpers for in-place editing //////////
// Returns an event map that handles the "escape" and "return" keys and
// "blur" events on a text input (given by selector) and interprets them
// as "ok" or "cancel".
var okCancelEvents = function (selector, callbacks) {
var ok = callbacks.ok || function () {};
var cancel = callbacks.cancel || function () {};
var events = {};
events['keyup '+selector+', keydown '+selector+', focusout '+selector] =
function (evt) {
if (evt.type === "keydown" && evt.which === 27) {
// escape = cancel
cancel.call(this, evt);
} else if (evt.type === "keyup" && evt.which === 13 ||
evt.type === "focusout") {
// blur/return/enter = ok/submit if non-empty
var value = String(evt.target.value || "");
if (value)
ok.call(this, value, evt);
else
cancel.call(this, evt);
}
};
return events;
};
I used this js function once to suppress the user using the return key in the text field to submit the form data. Perhaps you could modify it to suit the capture?
function stopRKey(evt) { // Stop return key functioning in text field.
var evt = (evt) ? evt : ((event) ? event : null);
var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
if ((evt.keyCode == 13) && (node.type=="text")) { return false; }
}
document.onkeypress = stopRKey;
You can also use event.currentTarget.value
Template.newLink.events = {
'keypress input.newLink': function (evt) {
if (evt.which === 13) {
var url = event.currentTarget.value;
// add to database
}
}
};

Resources