I'm having a problem with the following situation.
I have an ascx which contains a submit button for a search criteria and I am trying to call a validation function in a js file I've used throughout the site (this is the first time I'm using it in an ascx).
Now I've just tried this:
<script type="text/javascript" src="js/jquery-1.3.2.js"></script>
<script type="text/javascript" src="js/jsAdmin_Generic_SystemValidation.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$(".submitBtn").click(function (e) {
alert("test");
alert($.Validate());
alert("test 2");
});
});
</script>
The file is being referenced correctly as I am already seeing posts in Firebug that are done by it.
This is the function:
jQuery.extend({
Validate: function () {
var requiredElements = $('.required').length; // Get the number of elements with class required
$('.required').each(function () {
// If value of textbox is empty and have not
// yet been validated then validate all required
// elements. i.e.
if (($(this).val() == "") || ($(this).hasClass("validationError")) || ($(this).hasClass("validationAlert")) || ($(this).hasClass("validationOk") == false)) {
validate($(this));
}
});
if ($('.validationOk').length == requiredElements) {
return true;
} else {
return false;
}
},
// Another extended function, this function
// is used for pages with the edit-in-place
// feature implemented.
validateElement: function (obj) {
var elementId = obj.attr("id"); // id of the button clicked.
var flag = 0;
if (elementId.toLowerCase() == "paymentmethodid") {
// Case elementId = paymentMethodId then check all the
// elements with css class starting with openStorage
var requiredElements = $(document).find("input[class*='openStorage']").length; // Get the number of elements with css class starting with openStorage
// Loop through all the elements with css class containing
// openStorage abd validate each element.
$(document).find("input[class*='openStorage']").each(function () {
if (($(this).val() == "") || ($(this).hasClass("validationError")) || ($(this).hasClass("validationAlert"))) {
validate($(this));
}
if ($(this).hasClass("validationOk")) {
flag++;
} else if (($(this).hasClass("validationError")) || ($(this).hasClass("validationAlert"))) {
flag--;
}
});
// If all elements are valid return true else return false
if (flag == requiredElements) {
return true;
} else {
return false;
}
} else if (elementId.toLowerCase() == "registeredfortax") {
if (($('.TaxRegistrationNumber').val() == "") || ($('.TaxRegistrationNumber').hasClass("validationError")) || ($('.TaxRegistrationNumber').hasClass("validationAlert"))) {
validate($('.TaxRegistrationNumber'));
}
if ($('.TaxRegistrationNumber').hasClass("validationOk")) {
return true;
} else {
return false;
}
} else {
var elementClass = "." + elementId;
if (($(elementClass).val() == "") || ($(elementClass).hasClass("validationError")) || ($(elementClass).hasClass("validationAlert")) || ($(elementClass).hasClass("validationOk") == false)) {
validate($(elementClass));
}
if ($(elementClass).hasClass("validationOk") && ($(elementClass).hasClass("required"))) {
return true;
} else if ($(elementClass).hasClass("required") == false) {
return true;
}else {
return false;
}
}
}
});
Now at first I was getting "Validate() is not a function" in firebug. Since I did that alert testing, I am getting the first alert, then nothing with no errors.
Can anyone shed some light?
Thanks
Are you using the extend method properly? ...
http://api.jquery.com/jQuery.extend/
Related
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 ...',
});
});
I want to write a function loggedIn() in file auth.service.ts to check the token from local storage, and then verify it with firebase/php-jwt in server side. But the code in Typescript gives an infinite loop. Here is my code:
auth.service.ts
loggedIn(){
const token: string = localStorage.getItem('id_token');
if (token == null) {
return false;
}
else {
const subs = this.http.post('http://localhost/url/to/myPHP.php', {"token":token})
.map(res=>res.json()).subscribe(data=>{
if(data.valid){
this.valid = true;
} else {
this.valid = false;
}
},
err=>console.log(err));
if (this.valid){
console.log("Valid");
return true;
} else {
console.log("Invalid");
return false;
}
}
}
Given token: valid token.
Result: give no error but infinite console.log of 'Valid' as well as return true, until the Apache down.
Given token: invalid token
Result: give no error but infinite console.log of 'Invalid' as well as return false, until the Apache down.
What I have tried:
loggedIn(){
const token: string = localStorage.getItem('id_token');
if (token == null) {
return false;
}
else {
const subs = this.http.post('http://localhost/url/to/myPHP.php', {"token":token})
.map(res=>res.json()).subscribe(data=>{
if(data.valid){
this.valid = true;
} else {
this.valid = false;
}
},
err=>console.log(err));
if (this.valid){
console.log("Valid");
console.log(this.valid);
return true;
} else {
console.log("Invalid");
console.log(this.valid);
return false;
}
subs.unsubscribe();
return true;
}
}
The line subs.unsubscribe(); did stop the loop, yet it will literally unsubscribe the Observable<Response> and the code inside .subscribe() will not run. Please help.
Edit: Usage of loggedIn()
*ngIf="authService.loggedIn()
for 4 times in navbar component.
Inside auth.guard.ts
canActivate(){
if (this.authService.validToken){
return true;
} else {
this.router.navigate(['/login']);
return false;
}
}
In app.module.ts
{path:'profile', component:ProfileComponent, canActivate:[AuthGuard]}
I finally solve the problem. The problem with my code: .subscribe() is an async call (which actually scheduled for last/later execution). This is the situation:ngOnInit() : which located in component < ts > file
ngOnInit(){
this.authService.loggedIn();
console.log("10");
}
loggedIn() : which located in auth.service.ts file
loggedIn(){
const token: string = localStorage.getItem('id_token');
if (token == null) {
return false;
}
else {
const subs = this.http.post('http://localhost/url/to/myPHP.php', {"token":token})
.map(res=>res.json()).subscribe(data=>{
if(data.valid){
console.log("1");
} else {
console.log("2");
}
console.log("3")
},
err=>console.log(err));
}
}
and then the result will be :
1013 which mean, anything you do inside the subscribe will change only after you need it (in many cases). So we need to do whatever we need to, inside the subscribe(), and fire it only when needed. In my case, I want to fire it if any changes apply to token inside local storage.
This is my solution
As I want it always check with the token. I used DoCheck()
Inside auth.service.ts
verifyToken(authToken) {
const body = {token:authToken};
return this.http.post('http://localhost/url/to/myPHP.php',body)
.map(res => res.json());
}
tokenExist(): boolean {
const token: string = localStorage.getItem('id_token');
if (token == null) {
return false;
} else {
return true;
}
}
Inside navbar.component.ts
ngOnInit() {
this.curToken = localStorage.getItem('id_token');
this.loggedIn(this.curToken);
}
ngDoCheck(){
if (this.curToken != localStorage.getItem('id_token')){
this.curToken = localStorage.getItem('id_token');
this.loggedIn(this.curToken);
}
}
loggedIn(token){
if(this.authService.tokenExist()){
this.authService.verifyToken(token).subscribe(data=>{
if(data.valid){
this.validLogin = true;
} else {
console.log("Invalid Token");
this.validLogin = false;
}
});
} else {
console.log("Token Missing");
this.validLogin = false;
}
}
Of course, don't forget to implement DoCheck in the line
export class NavbarComponent implements OnInit, DoCheck
I have jqgrid on asp .NET web page.
When page is loaded and grid loads its data, after it receives json, before data is shown on grid, I get error message from IE:
Internet Explorer 11.0.9600.17728
It wants me to add about:blank to Trusted Sites.
When i click "close" rows appear.
Row`s html is as follows:
<a onclick="
OpenWindow('/13_1/Workflow.TasksWebPresUnit/TaskDetails/Index/?
taskDn=WFL///70000/.321360&isModal=True&
returnUrl=/13_1/Workflow.TasksWebPresUnit&
userId=5&
componentsToSet=test*testc', 'Details', '90%', '0', false, '¡',true);"
href="#">P01.07 Verification
</a>
No matter what I put in onclick, can be "blahblah", same with href, can be "foobar",
<a onclick="
abcd"
href="xyz">P01.07 Verification
</a>
i get that error window.
But, when I construct row's html that it not contain "onclick=sth", then i do not get this error.
Is there any way to stop IE from warning user or maybe I`m doing somethiong wrong?
Any help / clarification appreciated.
p.s. If i add about:blank to trusted sites, the problem is gone, but i don`t understand fully if this is secure solution.
Update 1: script
function OpenWindow(url, title, width, height, checkValue, multiSepar, showCloseButton) {
var progressIndImg = GLOBAL_CSS_PATH + '/Technology/modal/images/waiting.gif';
if (checkValue) {
var queryVals = parseQueryString(url);
var relatedComp = queryVals['componentToFill'];
var relatedVal = document.getElementById(relatedComp);
if (relatedVal.value != null && relatedVal.value != '') {
var win = dhtmlmodal.open('ModalBox', 'iframe', url, title, 'width=' + width + ', height=' + height + ',center=1,resize=1,scrolling=1', '', progressIndImg, showCloseButton);
win.onclose = function () {
return true;
}
}
} else {
var win = dhtmlmodal.open('ModalBox', 'iframe', url, title, 'width=' + width + ', height=' + height + ',center=1,resize=1,scrolling=1', '', progressIndImg, showCloseButton);
win.onclose = function () {
return true;
}
}
// } else {
// setInterval(checkForMessages, 200);
// }
// var ie7 = (navigator.appVersion.indexOf('MSIE 7.') == -1) ? false : true;
// if (ie7 != true) {
var onmessage = function (e) {
try {
var objects = JSON.parse(e.data);
if (window.addEventListener) {
window.removeEventListener('message', onmessage, false);
}
else if (window.attachEvent) {
window.detachEvent('onmessage', onmessage);
}
if (objects['methodName'] != null)
window[objects['methodName']](objects);
else
FillData(objects, true, multiSepar);
var close = objects['close'];
if (close == 'true') {
win.hide();
win.close();
}
}
catch (err) {
if (console)
console.error(err);
}
};
if (window.addEventListener) {
window.addEventListener('message', onmessage, false);
} else if (window.attachEvent) {
window.attachEvent('onmessage', onmessage);
}
Is it possible to hide events that are inside background events so that the user cannot see it?
if yes what is the way to do it ?
var isValidEvent = function(start,end,id){
return $("#calendar").fullCalendar('clientEvents', function (event) {
return (event.rendering === "background" && id!='test' &&
(start>event.start) && (end<event.end)) ;
}).length > 0;
};
eventRender:function(event, element, view) if(isValidEvent(event.start,event.end,event.id)){
$(element).hide();
},
As of the docs, eventRender callback should either return an event OR false if the event should be hidden:
eventRender:function(event, element, view)
if(isValidEvent(event.start,event.end,event.id)){
return event;
}
else {
return false;
}
},
I haven't tested yet as I don't need it, but should work that way.
I got it like this:
eventRender:function(event, element, view){
var array= new Array();
array = $("#calendar").fullCalendar('clientEvents','test');
for(i of array){
if(event.source.url=="events.php" && moment(event.start)>=moment(i.start) && moment(event.end)<=moment(i.end)){
return false;
}
} }
How can I prevent events with conflict time? Is there any variable to set up?
No, there is not a variable to set, but you can use something like clientEvents which retrieves events that fullcalendar has in memory. You can use the function below in the eventDrop. In the case below it uses a function to filter out whether the event will have have an overlap or not.
function checkOverlap(event) {
var start = new Date(event.start);
var end = new Date(event.end);
var overlap = $('#calendar').fullCalendar('clientEvents', function(ev) {
if( ev == event)
return false;
var estart = new Date(ev.start);
var eend = new Date(ev.end);
return (Math.round(estart)/1000 < Math.round(end)/1000 && Math.round(eend) > Math.round(start));
});
if (overlap.length){
//either move this event to available timeslot or remove it
}
}
you can add eventOverlap : false in the celendar config,
http://fullcalendar.io/docs/event_ui/eventOverlap/
Correct overlap checking.
eventDrop: function(event, dayDelta, minuteDelta, allDay, revertFunc, jsEvent, ui, view) {
/// deny overlap of event
var start = new Date(event.start);
var end = new Date(event.end);
var overlap = $('#calendar').fullCalendar('clientEvents', function(ev) {
if( ev == event) {
return false;
}
var estart = new Date(ev.start);
var eend = new Date(ev.end);
return (
( Math.round(start) > Math.round(estart) && Math.round(start) < Math.round(eend) )
||
( Math.round(end) > Math.round(estart) && Math.round(end) < Math.round(eend) )
||
( Math.round(start) < Math.round(estart) && Math.round(end) > Math.round(eend) )
);
});
if (overlap.length){
revertFunc();
return false;
}
}
Add custom property in the event object overlap:false for example your event object will be
`{
title:'Event',
start: '2017-01-04T16:30:00',
end: '2017-01-04T16:40:00',
overlap:false
}`
Now override selectOverlap function,
selectOverlap: function(event) {
if(event.ranges && event.ranges.length >0) {
return (event.ranges.filter(function(range){
return (event.start.isBefore(range.end) &&
event.end.isAfter(range.start));
}).length)>0;
}
else {
return !!event && event.overlap;
}
},
It will not let the another event to override the already placed event.
This does the trick. It also handles resizing overlapping events
var calendar = new Calendar(calendarEl, {
selectOverlap: false,
eventOverlap: false
}
});