Getting a response from a modal dialog using a promise - javascript

I am currently working on a dialog in order to replace the browser‘s original alert and confirm dialogs since I do not like them. My dialog is very flexible in it‘s use.
So my function is called msgBox and it has got the following syntax:
msgBox (prompt, title, buttons, modal, gradient)
All params are optional. In that case the function uses default values.
So far it works excellent already. Please see the code below.
I want to achieve now, getting as result the button that is clicked by the user to assign it to a variable or use it in an If-statement.
For example:
let response = msgBox("Load Settings?", "Confirm", ["Yes","No", "Restore defaults"]);
or
if (msgBox("Load file?", "Confirm", ["Yes","No", "Search"]) == 'Yes') {
// do some stuff
}
I want the dialog work this way, that it returns'false' in case it is non-modal and the user clicked on an area outside, otherwise it should return the clicked button as string in order to evaluate it.
Here is the code so far:
let isModal = true;
let msgBoxAnswer = null;
// #####################################################################################
// PURPOSE: Displays a modal | modeless dialog with dynamical buttons
//
// PARAMETER: - prompt = prompt text
// - titel = Titelzeie des Dialogs
// - buttons = Button-Array, sepatated by komma - Default = 'Ok'
// - modal = dialog modal | modeless - default = modal
// - gradient = optional: gradient of the titlebar
// RETURNS: : the value of the clicked button as string
// #####################################################################################
async function asyncMsgBox(prompt, title, buttons = ['Ok'], modal = true, gradient) {
// do some init stuff...
msgBoxAnswer = null;
if (prompt == null) {prompt = ''}
if (title == null || title.trim() == '') {
title = document.getElementsByTagName("title")[0].innerHTML;
}
isModal = modal;
let classnames = 'overlay';
if (modal) { classnames += ' dark'}
// search for the parent container (usually it's the <body>)
let parent = document.getElementsByTagName('body')[0];
parent.innerHTML += `<div id="msgBoxBG" class="${classnames}" onclick="closeDialog('cancel')"></div>`;
// catching an empty button-array
if (buttons[0] == '') {buttons[0] = 'Ok'}
// first create the buttons!
// otherwise the <div> is going to be closed automatically
let btnCode ='';
for (let i = 0; i < buttons.length; i++) {
const btn = buttons[i];
btnCode += `<button class="btnMsgbox" onclick="closeDialog('${btn}')">${btn}</button>`;
}
classnames = 'titlebar';
if (gradient) { classnames += ' gradient'}
let container = $('msgBoxBG');
container.innerHTML = `
<div class="dialog">
<div class ="${classnames}">
<h2 id="msgCaption">${title}</h2>
</div>
<p id="msgPrompt">${prompt}</p>
${btnCode}
</div>`;
try {
// HERE START THE PROBLEMS...
let answer = await closeDialog();
return answer; // resolve()
} catch(err){
return false; // reject()
}
}
function closeDialog(response){
return new Promise(function(resolve, reject) {
if (response) {
if (isModal && response == 'cancel') {return};
if (!isModal && response == 'cancel') {
$('msgBoxBG').remove();
reject('false');
} else if (response !='cancel') {
$('msgBoxBG').remove();
resolve(response);
} else {
return;
}
}
});
}
The problem is, that await closeDialog() finds the response-parameter 'undefined' at the first call and returns before the user is able to click on any button at all, which should call the same function.
I must add that I am not very experienced in Javascript yet. So if anyone has another suggestion or solution how to solve the problem, I am open to learn.
Thanks in advance for your help!

Related

AEM logout using jquery and modal

I have created a sign_in button in aem and trying to call a modal on the sign_in anchor tag which will call my modal.js. But when I click on anchor tag the modal doesn't pop out and my url changes to https:localhost:4502/content/my-website/home.html#sign_out. I am not that good with jquery so I don't know where I am going wrong
here is code for reference.
sign_in/out button .html
<div data-sly-use.placeholderTemplate="core/wcm/components/commons/v1/templates.html"
data-sly-test.hasContent="${properties.signInLabel != '' && properties.signInXfPath != '' && properties.signOutLabel != '' && properties.signOutXfPath != '' }"
class="ranosys-sign-in-buttons"
data-current-user-url="/libs/granite/security/currentuser.json">
<span
class="xyz-sign-in-buttons__button xyz-sign-in-buttons__button--greeting"
id="ranosysGreetingLabel"
>${properties.greetingLabel # i18n}</span>
<a href="#sign-in"
class="xyz-sign-in-buttons__button xyz-sign-in-buttons__button--sign-in"
data-modal-url="${ properties.signInXfPath # selectors='content', extension = 'html'}"
data-sly-test="${properties.signInLabel != '' }">${properties.signInLabel}</a>
<a href="#sign-out"
class="xyz-sign-in-buttons__button xyz-sign-out-buttons__button--sign-out"
data-modal-url="${ properties.signOutXfPath # selectors='content', extension = 'html'}"
data-sly-test="${properties.signOutLabel != '' }">${properties.signOutLabel}</a>
</div>
<sly data-sly-call="${placeholderTemplate.placeholder # isEmpty=!hasContent}"></sly>
**sign_in/out_button.js**
import $ from "jquery";
// alert("hiii");
const currentUserUrl = $('.xyz-sign-in-buttons').data('current-user-url'),
signIn = $('[href="#sign-in"]'),
signOut = $('[href="#sign-out"]'),
greetingLabel = $('#ranosysGreetingLabel'),
greetingText = greetingLabel.text(),
body = $('body');
$.getJSON(currentUserUrl + "?nocache=" + new Date().getTime(), function(currentUser) {
const isAnonymous = 'anonymous' === currentUser.authorizableId;
if(isAnonymous) {
signIn.show();
body.addClass('anonymous');
} else {
signOut.show();
greetingLabel.text(greetingText + ", " + currentUser.name);
greetingLabel.show();
}
});
**modal.js**
import $ from "jquery";
let visible = false;
function showModal(e) {
e.preventDefault();
const xfUrl = $(this).data('modal-url');
if (visible || !xfUrl) { return; }
const showModalEvt = new Event('xyz-modal-show');
const body = document.querySelector('body');
$.get(xfUrl, function (data) {
const modal = $('<div id="xyz-modal"/>');
$('body').append(modal.append(data));
modal.fadeIn(300, function() { visible = true; });
visible = true;
// dispatch event to indicate that the modal has been shown
// used by sign-in-form.js to dynamically update a successful sign-in redirect to the current page
body.dispatchEvent(showModalEvt);
});
return false;
}
function hideModal(e) {
const modal = $('#xyz-modal');
// if the target of the click isn't the modal nor a descendant of the modal
if (visible && modal && !modal.is(e.target) && modal.has(e.target).length === 0) {
e.preventDefault();
modal.fadeOut(200, function(){
modal.remove();
visible = false;
});
return false;
}
}
/*eslint no-use-before-define: ["error", { "functions": false }]*/
/**
* Handle clicking of the Sign In button
*/
$('body').on('click', '[data-modal-url]', showModal);
/**
* Handle clicking "off-modal" to hide it
*/
$(document).on('click', (hideModal));
Seems you are fetching HTML from XF; if you wanted logout thru form based auth of AEM usage.
#1 - You can use below anchor for example; add anchor tag with below href in the XF.
Log Out
also you hit(/system/sling/logout.html) thru ajax as well.
#2 - you can write you custom logout servlet and on button click event over modal, can hit the servlet to logout.
you can also take an example of - org.apache.sling.auth.core.impl.LogoutServlet

Pop up removed completly from DOM

I have created the below function that uses bootstrapalert where a pop up comes up that holds random data from a database table. But after I trigger the event and close the window I need to refresh the page in order for it to work again. I don't seem to find the issue in the code that causes this problem. Any suggestions for improvement?
<script>
var alertList = document.querySelectorAll(".alert");
alertList.forEach(function (alert) {
new bootstrap.Alert(alert);
});
function randomName() {
if (
document.getElementById("randomNamePopUp").dataset.showned == "false"
) {
document.getElementById("randomNamePopUp").style.display = "block";
document.getElementById("randomNamePopUp").dataset.showned = "true";
} else {
//window.location.href=window.location.href+"?showRandom=true";
}
}
const urlParams1 = new URLSearchParams(window.location.search);
const myParam = urlParams1.get("showRandom");
if (myParam == "true") {
randomName();
}
</script>

How to Fix 'One Closing Button Closes All Modals'

I'm trying to create a vanilla JavaScript Modal that has the capability of being customized by the User, when instantiating it from the HTML file (or JS file). However, when it comes to dealing with the close() function to close the modal, instead of closing ONE modal at a time, using its close button, the close button of the FIRST modal closes ALL modals of the page. I'm not sure what I'm doing wrong...
I've researched other similar vanilla JavaScript, customizable modal libraries, but most of them use either jQuery, some framework, or include a lot of complications that I am not familiar with (I'm still a beginner). I've researched on GitHub, CodePen, Google, and on here; but I have yet to find a solution that satisfies what I need.
Since the code is quite long, I'd suggest you go directly to my CodePen account, where you can have the full code.
https://codepen.io/jdriviere/pen/zYOyJvv?editors=0011
But here is my close() function:
Modal.prototype.close = function() {
let modal = document.getElementById(this.options.id);
let modalBody = modal.children[0];
// Delete elements from Modal Body
for (let i = 0; i < modalBody.children.length; i++) {
modalBody.removeChild(modalBody.children[i]);
} // End of LOOP
// Delete Modal Body from Modal
modal.removeChild(modalBody);
// Delete Modal from DOM
modal.style.display = 'none';
document.body.removeChild(modal);
return this;
};
I would expect the code to close ONE modal at a time, and preferably the modal that has the proper ID (which should be either assigned by the User or by default have a "NoID" ID). Instead, if I close subsequent modals, it closes them; but if I close the FIRST one, it closes ALL of them. Also, is there a way to init() the Modal functionalities as soon as you create the modal instance (I hate manually initiating them)? If so, please include your solution here too, if not much asked.
Been at it for quite some time now. Your help would be greatly appreciated.
Thank you. :)
You have couple of mistakes in your code:
Always use a proper id pattern for the HTML element. You have used n/a for the modal that does not have id property in their options object. Using such id will break the query selector when you use jQuery.
Since, you are calling the init() function twice and in each call for init() the closeBtn is selecting both the close buttons of two modals and assigning the click event handler to each of them twice. That was the reason when you clicked on one button the click event for another button was executing itself. So, what you can do is, only associate a click function once only to that close button of the modal for which the init() function was called. I used let closeBtn = document.querySelector('#'+this.options.id + ' .modal-close'); to select that particular close button inside that init() function.
Overall your JS code will look like:
/**
* Blueprint function (class) that describes a Modal object.
* #param {Object} options Object parameter containing elements that describe the Modal.
* #returns {Object} options Returns options from current modal object.
*/
function Modal(options) {
// If constructor params is available
if (options) {
this.options = options;
} else {
this.options = {};
} // End of IF-ELSE
// Add to options object
if (options.id) {
// Check type of ID entry
if (typeof options.id === 'number') {
this.options.id = options.id.toString();
} else {
this.options.id = options.id;
} // End of IF-ELSE
} else if (options.id === undefined) {
this.options.id = 'NA';
} // End of IF-ELSE
if (options.name) {
this.options.name = options.name;
} // End of IF
if (options.closable) {
this.options.closable = options.closable;
} // End of IF
return this;
};
// Prototypes
/**
* Displays some information concerning the current Modal object.
* #returns {Object} this Returns current modal object.
*/
Modal.prototype.open = function() {
let demo = document.getElementById('demo');
return this;
};
/**
* Creates an instance of a Modal object with the specified object elements.
* #returns {Object} this Returns current Modal object.
*/
Modal.prototype.create = function() {
// Create Modal Element
let modal = document.createElement('div');
let modalBody = document.createElement('div');
// Create Modal
!modal.classList.contains('modal') ?
modal.classList.add('modal') :
modal.classList.add('');
modal.id = this.options.id || 'noID';
// Create modal body element
!modalBody.classList.contains('modal-body') ?
modalBody.classList.add('modal-body') :
modalBody.classList.add('');document.querySelector('#' + this.options.id + ' .modal-close');
modal.appendChild(modalBody);
// Adding modal sub-elements
if (this.options.title) {
let modalTitle = document.createElement('h2');
!modalTitle.classList.contains('modal-title') ?
modalTitle.classList.add('modal-title') :
modalTitle.classList.add('');
modalTitle.textContent = this.options.title;
modalBody.appendChild(modalTitle);
console.log('Added title!');
} // End of IF
if (this.options.subtitle) {
let modalSubtitle = document.createElement('h4');
!modalSubtitle.classList.contains('modal-subtitle') ?
modalSubtitle.classList.add('modal-subtitle') :
modalSubtitle.classList.add('');
modalSubtitle.textContent = this.options.subtitle;
modalBody.appendChild(modalSubtitle);
console.log('Added subtitle!');
} // End of IF
if (this.options.content) {
let modalContent = document.createElement('p');
!modalContent.classList.contains('modal-content') ?
modalContent.classList.add('modal-content') :
modalContent.classList.add('');
modalContent.textContent = this.options.content;
modalBody.appendChild(modalContent);
console.log('Added contents!');
} // End of IF
if (this.options.closable) {
let modalClose = document.createElement('span');
!modalClose.classList.contains('modal-close') ?
modalClose.classList.add('modal-close') :
modalClose.classList.add('');
modalClose.innerHTML = '×';
modalBody.appendChild(modalClose);
console.log('Close button added!');
} // End of IF
document.body.appendChild(modal);
console.log('Modal created with ID', modal.id);
return this;
};
/**
* Closes the current Modal object.
* #returns {Object} this Returns current Modal object.
*/
Modal.prototype.close = function() {
let modal = document.getElementById(this.options.id);
let modalBody = modal.children[0];
// Delete elements from Modal Body
for (let i = 0; i < modalBody.children.length; i++) {
modalBody.removeChild(modalBody.children[i]);
} // End of LOOP
// Delete Modal Body from Modal
modal.removeChild(modalBody);
// Delete Modal from DOM
modal.style.display = 'none';
document.body.removeChild(modal);
return this;
};
/**
* Initializes the inner functions of the modal, such as the closing capacity.
* #returns {Object} this Returns current Modal object.
*/
Modal.prototype.init = function(e) {
// let closeBtnAll = document.querySelectorAll('.modal-close');
let closeBtn = document.querySelector('#'+this.options.id + ' .modal-close');
// Assign close() function to all close buttons
closeBtn.addEventListener('click', () => {
if (this.options.closable) {
this.close();
}
})
// Press ESC to close ALL modals
return this;
};
// Create a Modal object
let modal1 = new Modal({
id: 'post1',
name: 'modal',
title: 'First Post',
subtitle: 'I contain all the elements',
content: 'This is awesome!',
closable: true
});
let modal2 = new Modal({
title: 'Second Post',
subtitle: 'Trying new things',
content: 'Hehehehehe',
closable: true
});
modal1.open();
modal1.create();
modal1.init();
modal2.open();
modal2.create();
modal2.init();
Just replace the above JS code in your codepen and try. It will work.
The problem is the init-function:
/**
* Initializes the inner functions of the modal, such as the closing capacity.
* #returns {Object} this Returns current Modal object.
*/
Modal.prototype.init = function() {
// let closeBtnAll = document.querySelectorAll('.modal-close');
let modal = document.getElementById(this.options.id);
let closeBtn = modal.querySelector('.modal-close');
// Assign close() function to all close buttons
closeBtn.addEventListener('click', () => {
console.log(this.options);
if (this.options.closable) {
this.close();
}
})
// Press ESC to close ALL modals
return this;
};
If you dont specify that you want to use the eventlistener on the current modal then it will be set to both modals.

How to redirect back to index page and display modal pop up as per redirecting? PHP

i have an index page which asks for input. after submit button is clicked, the input is processed in another .php file (process includes using imagecreatefromjpeg and mysql queries). now, it needs to redirect to index again and show a modal popup saying thank you. i am able to redirect to index page again using this code:
if (!empty($name) && !empty($email) && !empty($office_id) && !empty($title) && !empty($story)) {
$save_sql = "INSERT INTO `tbl_amadeuscontest` (filename, name, email, office_id, title, story, time) VALUES ('$img_newname','$name','$email','$office_id','$title','$story','$sql_date')";
$query = mysql_query($save_sql,$con) or die(mysql_error("Could not write information to the database"));
if (mysql_affected_rows($con) !== 0) {
header('Location: ' . $uploadForm);
}
mysqli_close($con);
}
basically, it is the header('Location: ' . $uploadForm); that does the job. but how can i overlay a modal popup saying thank you on it at the same time? do i need to call the js. finction? or do i need to echo the HTML? where do i need to place the codes? thanks.
i have some HTML codes for modal popup here:
HTML
`
<div class="modal-inner">
<img src="http://mysite.com/modal/images/thanku-post.jpg" />
</div>
<!-- Use Hash-Bang to maintain scroll position when closing modal -->
<a href="#!" class="modal-close" title="Close this modal"
data-dismiss="modal">×</a>
</section>
<script src="js/modal.js"></script>`
EDIT 1
modal.js
`(function(global) {
'use strict';
// Storage variable
var modal = {};
// Store for currently active element
modal.lastActive = undefined;
modal.activeElement = undefined;
// Polyfill addEventListener for IE8 (only very basic)
modal._addEventListener = function (element, event, callback) {
if (element.addEventListener) {
element.addEventListener(event, callback, false);
} else {
element.attachEvent('on' + event, callback);
}
};
// Hide overlay when ESC is pressed
modal._addEventListener(document, 'keyup', function (event) {
var hash = window.location.hash.replace('#', '');
// If hash is not set
if (hash === '' || hash === '!') {
return;
}
// If key ESC is pressed
if (event.keyCode === 27) {
window.location.hash = '!';
if (modal.lastActive) {
return false;
}
// Unfocus
modal.removeFocus();
}
}, false);
// Convenience function to trigger event
modal._dispatchEvent = function (event, modal) {
var eventTigger;
if (!document.createEvent) {
return;
}
eventTigger = document.createEvent('Event');
eventTigger.initEvent(event, true, true);
eventTigger.customData = { 'modal': modal };
document.dispatchEvent(eventTigger);
};
// When showing overlay, prevent background from scrolling
modal.mainHandler = function () {
var hash = window.location.hash.replace('#', '');
var modalElement = document.getElementById(hash);
var htmlClasses = document.documentElement.className;
var modalChild;
var oldModal;
// If the hash element exists
if (modalElement) {
// Get first element in selected element
modalChild = modalElement.children[0];
// When we deal with a modal and body-class `has-overlay` is not set
if (modalChild && modalChild.className.match(/modal-inner/)) {
if (!htmlClasses.match(/has-overlay/)) {
// Set an html class to prevent scrolling
document.documentElement.className += ' has-overlay';
}
// Unmark previous active element
if (modal.activeElement) {
oldModal = modal.activeElement;
oldModal.className = oldModal.className.replace(' is-active', '');
}
// Mark modal as active
modalElement.className += ' is-active';
modal.activeElement = modalElement;
// Set the focus to the modal
modal.setFocus(hash);
// Fire an event
modal._dispatchEvent('cssmodal:show', modal.activeElement);
}
} else {
document.documentElement.className =
htmlClasses.replace(' has-overlay', '');
// If activeElement is already defined, delete it
if (modal.activeElement) {
modal.activeElement.className =
modal.activeElement.className.replace(' is-active', '');
// Fire an event
modal._dispatchEvent('cssmodal:hide', modal.activeElement);
// Reset active element
modal.activeElement = null;
// Unfocus
modal.removeFocus();
}
}
};
modal._addEventListener(window, 'hashchange', modal.mainHandler);
modal._addEventListener(window, 'load', modal.mainHandler);
modal.setFocus = function () {
if (modal.activeElement) {
// Set element with last focus
modal.lastActive = document.activeElement;
// New focussing
modal.activeElement.focus();
}
};
// Unfocus
modal.removeFocus = function () {
if (modal.lastActive) {
modal.lastActive.focus();
}
};
// Export CSSModal into global space
global.CSSModal = modal;
}(window));`
please note that $uploadForm means $uploadForm = 'http://' . $_SERVER['HTTP_HOST'] . $directory_self . 'index.php';
thanks in advance for your answer. hope you can help me to sort it out.
You can just pass a ?openModal=1 variable to your index page. In your view file, write a conditional that will show your modal. I don't know how your modal is working but either just make the css appear or run your js script that will toggle it on from there.
in your redirect php file
header('Location: ' . $uploadForm . '?modal=1');
in your html
<?php if($_GET['modal'] == 1){ ?>
do something to make your modal appear
<?php } ?>
Quick and dirty answer. Modify your other.php file to do something like this:
header('Location:' . $uploadForm . '?thanks=1');
Then in your index.php, at the bottom, near where the body tag closes, do this:
<?php if (isset($_GET['thanks']) && 1 == $_GET['thanks']) { ?>
<script type='text/javascript'>
alert('Thanks!');
</script>
<?php } ?>
</body> <!-- end of body -->
You can do whatever kind of fancy Javascript you want inside that script tag.
The idea here is simple: when your index.php is given thanks=1 in the query, it shows the modal pop-up. You engineer your other .php to be the only time you expect thanks=1 to be given.

Problems to run Jquery code on button click on my Wizard-step Jquery code

I am using Wizard-step for my form in a view, My project is on MVC3.
I have a form that is made on 3 steps which means I have three tags for each step in my form
and two buttons that are following:
<p><input type="button" id="next-step" class="next-step-client-val" name="next-step" value="Next" /></p><
<p><input type="button" value="Back id="back-step" name="back-step"></p>
In my first step I have only a bunch of TextBoxes, DropDownlists and TextAreas, second step have alot of client-side functionality, one example is that user can move rows from a table to another one etc.. And I have a Jquery validation that is following:
var customTbl = $('#CustomPickedTable');
var has1 = customTbl.find('td[data-row="1"]').is('*');
var has2 = customTbl.find('td[data-row="2"]').is('*');
var has3 = customTbl.find('td[data-row="3"]').is('*');
var has4 = customTbl.find('td[data-row="4"]').is('*');
if ((has1 === true) && (has2 === true) && (has3 === true) && (has4 === true)) {
jAlerts("Saved", "Info");
} else {
jAlert('You have to move atleast one row from each table', "Varning"); ;
return false
}
On the 3th step its just a review on what was created and my next-step button submits the form, when a user clicks on it.
What I want to be able to do is that when a user is on the 2th step and clicks on next-step button the jquery validation above should run. With my Wizard-step code I cant do that beacuse it uses next-step button selector for everything. Is there any solutions for this?
I have tried to put my Jquery validation code inside
$("#next-step").click(function () {
}
But then my jquery validation code run everytime a user clicks on next button, beacuse my tables are shown in the form but hidden, the validation triggers on first step when a user click on next. So that solution didnt work.
This is my Wizard-step Jquery Code and right now I have my Jquery validation in the bottom which means that when im on 3th step and click on next-step button it will validate and then post. But I dont want it to be like that. I want the validation to happen on the 2th step.
Here is the code:
$(function () {
$(".wizard-step:first").fadeIn(); // show first step
// attach backStep button handler
// hide on first step
$("#back-step").hide().click(function () {
var $step = $(".wizard-step:visible"); // get current step
if ($step.prev().hasClass("wizard-step")) { // is there any previous step?
$step.hide().prev().fadeIn(4500); // show it and hide current step
// disable backstep button?
if (!$step.prev().prev().hasClass("wizard-step")) {
$("#back-step").hide();
}
}
});
// attach nextStep button handler
$("#next-step").click(function () {
var $step = $(".wizard-step:visible"); // get current step
var validator = $("form").validate(); // obtain validator
var anyError = false;
$step.find("select").each(function () {
if (!this.disabled && !validator.element(this)) { // validate every input element inside this step
anyError = true;
}
});
$step.find("input").each(function () {
if (!validator.element(this)) { // validate every input element inside this step
anyError = true;
}
});
$("#next-step").click(function () {
if (!validator.element(this)) { // validate every input element inside this step
anyError = true;
}
});
if (anyError)
return false; // exit if any error found
if ($step.next().hasClass("confirm")) { // is it confirmation?
// show confirmation asynchronously
$.post("/wizard/confirm", $("form").serialize(), function (r) {
// inject response in confirmation step
$(".wizard-step.confirm").html(r);
});
}
if ($step.next().hasClass("wizard-step")) { // is there any next step?
$step.hide().next().fadeIn(4500); // show it and hide current step
$("#back-step").show(); // recall to show backStep button
}
else { // this is last step, submit form
var selectedQuestions = $("#SelectedQuestions");
var selectedCustomQuestions = $("#SelectedCustomQuestions");
var currentIds = new Array();
var currentText = new Array();
$("#CustomPickedTable td[data-question-id]").each(function () {
var clickedId = $(this).attr("data-question-id");
currentIds.push(clickedId);
});
$('#CustomPickedTable td[data-attr-id]').each(function () {
var ClickedText = $(this).html();
currentText.push(ClickedText);
});
selectedCustomQuestions.val(currentText.join("|"));
selectedQuestions.val(currentIds.join(","));
var customTbl = $('#CustomPickedTable');
var has1 = customTbl.find('td[data-row="1"]').is('*');
var has2 = customTbl.find('td[data-row="2"]').is('*');
var has3 = customTbl.find('td[data-row="3"]').is('*');
var has4 = customTbl.find('td[data-row="4"]').is('*');
if ((has1 === true) && (has2 === true) && (has3 === true) && (has4 === true)) {
jAlerts("saved", "Info");
} else {
jAlert('You have to move atleast one row from each table', "Varning"); ;
}
return false;
}
});
My html code looks something like this:
<div class="wizard-step>
//step 1 content
</div>
<div class="wizard-step>
//step 2 content
</div>
<div class="wizard-step>
//step 3 content
</div>
<p><input type="button" id="next-step" class="next-step-client-val" name="next-step" value="Next" /></p><
<p><input type="button" value="Back id="back-step" name="back-step"></p>
I think it would be better if you detect at which wizard step you are using jquery .index() function. This way you can do the validation in your next step click handler only if you are on second step moving on to the third step. The code would look something like this :
$("#next-step").click(function () {
var $step = $(".wizard-step:visible"); // get current step
var stepIndex = $(".wizard-step").index($step); //index returns 0 based index so second step would be 1.
var validator = $("form").validate(); // obtain validator
var anyError = false;
$step.find("select").each(function () {
if (!this.disabled && !validator.element(this)) { // validate every input element inside this step
anyError = true;
}
});
$step.find("input").each(function () {
if (!validator.element(this)) { // validate every input element inside this step
anyError = true;
}
});
if (anyError)
return false; // exit if any error found
if(stepIndex == 1) //if you are on second step then validate your table
{
var customTbl = $('#CustomPickedTable');
var has1 = customTbl.find('td[data-row="1"]').is('*');
var has2 = customTbl.find('td[data-row="2"]').is('*');
var has3 = customTbl.find('td[data-row="3"]').is('*');
var has4 = customTbl.find('td[data-row="4"]').is('*');
if ((has1 === true) && (has2 === true) && (has3 === true) && (has4 === true)) {
jAlerts("Saved", "Info");
} else {
jAlert('You have to move atleast one row from each table', "Varning"); ;
return false
}
}
else if ($step.next().hasClass("confirm")) { // is it confirmation?
// show confirmation asynchronously
$.post("/wizard/confirm", $("form").serialize(), function (r) {
// inject response in confirmation step
$(".wizard-step.confirm").html(r);
});
}
if ($step.next().hasClass("wizard-step")) { // is there any next step?
$step.hide().next().fadeIn(4500); // show it and hide current step
$("#back-step").show(); // recall to show backStep button
}
else { // this is last step, submit form
var selectedQuestions = $("#SelectedQuestions");
var selectedCustomQuestions = $("#SelectedCustomQuestions");
var currentIds = new Array();
var currentText = new Array();
$("#CustomPickedTable td[data-question-id]").each(function () {
var clickedId = $(this).attr("data-question-id");
currentIds.push(clickedId);
});
$('#CustomPickedTable td[data-attr-id]').each(function () {
var ClickedText = $(this).html();
currentText.push(ClickedText);
});
}
});
I think you could approach this problem by refactoring the code
// validate the inputs in a form
// #param {string|object} jquery selector or jquery object
function validateStep (selector){
var $step = $(selector);
var validator = $("form").validate();
var anyError = false;
$step.find("select").each(function () {
if (!this.disabled && !validator.element(this)) {
anyError = true;
}
$step.find("input").each(function () {
if (!validator.element(this)) {
anyError = true;
}
if (!validator.element(this)) {
anyError = true;
}
return anyError;
}
This way you could validate the second step by calling
// this works because jquery returns an array of objects
// as a result of the css selector we call it with
// the eq() function accepts an index value that returns
// the jquery object at that position
// see. http://api.jquery.com/eq-selector/
validateStep($('.wizard-step').eq(1));
Or the first
validateStep('.wizard-step:first');
Etc
We could incorporate this into your code like this -
$('#next-step').click(function (event){
var $step = $('.wizard-step');
if(validateStep($step.filter(':visible'))){
// go to the next step
if ($step.next().hasClass("wizard-step")) {
$step.hide().next().fadeIn(4500);
$("#back-step").show();
} else {
// submit form
}
}
});
NB: You can read more about jQuery selectors here http://api.jquery.com/category/selectors/

Categories

Resources