Hello everyone so I want to show and hide a button using jQuery, but only if a variable is true for example.
Ex:
var st1wch1 = false;
$(document).ready(function(){
$("#choice1").click(function(){
var st1wch1 = true
state1_1warrior()
});
});
$(document).ready(function(){
if(st1wch1 == false){
$("button#choice1").show()
}
else if(st1wch1 == true){
$("button#choice1").hide()
}
})
But for some reason it never hides, any ideas??? Thanks in Advance.
The most simple way to do it may be this:
$(document).ready(function(){
$("#choice1").click(function(){
$("button#choice1").toggle()
});
});
The logic you've implemented to show or hide the element is defined within the document ready event, which is raised before the user has a chance to click on the button and raise the event handler which toggles your global variable.
You probably wanted to hide and show when the element is clicked?
$("#choice1").click(function(){
$(this).toggle();
});
After changing the variable, you code does not go through the if else conditions. Put that show and hide condition inside a function like below
function toggleButton(){
if(st1wch1 == false){
$("button#choice1").show()
}
else if(st1wch1 == true){
$("button#choice1").hide()
}
}
and then call this function everytime you change the variable's value.
You must place your code inside the click handler.
I think you want to add at least 2 buttons later, and you want to toggle just a part of them or something like this.
var st1wch1 = false;
$(document).ready(function(){
$("#choice1").click(function(){
if(st1wch1 == false){
st1wch1 = true;
$("button#choice1").show()
}
else if(st1wch1 == true){
st1wch1 = false;
$("button#choice1").hide()
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="choice1">choice1</button>
You can use toggle:
var st1wch1 = true;
$('#choice1').toggle(condition);
Side note: Don't use things like
if (st1wch1 === true)
Do:
if (st1wch1)
and (for the == false / === false case):
if (!st1wch1)
document.ready() is only called when the page initially loads, so it evaluates the if/else statement when you load the page and then never again. Clicking the element doesn't rerun the if else statement.
To get the behavior you want you can either do
$("#choice1").click(function(){
$(this).toggle();
});
or
$("#choice1").click(function(){
evaluateBoolean();
});
function evaluateBoolean(){
if(st1wch1 == false){
$("button#choice1").show()
}
else if(st1wch1 == true){
$("button#choice1").hide()
}
}
You can use toggleClass.
$('#button').toggleClass('hidden', condition);
Created css class with display: none;
I would like to be able to check if a checkbox has been checked against a value in local storage. If it is checked I would like to apply a background colour to a part of the page.
Page to apply CSS http://upskillapps.com/resources/1.png
My local storage data looks like the following:
Local storage data http://upskillapps.com/resources/2.png
If the completion checkbox is active I would like to apply a green background and if not an orange background.
I have the following code so far but am new to JS and so it needs a lot of work:
function highlightComplete() {
if (DevPlan.completion == 'true') {
info-row.addClass('background-green');
} else if (DevPlan.completion == 'false') {
info-row.addClass('background-orange');
}
}
Any help would be greatly appreciated.
Here's an example for you:
$(document).ready(function () {
//this function executes on page load
if (!localStorage.getItem('color')) { //if our value does not already exist, we'll default it to green
localStorage.setItem('color', 'green');
$('#div').addClass('green');
} else { //our value exists already
if (localStorage.getItem('color') == 'green') {
$('#div').addClass('green');
} else {
$('#div').addClass('red');
}
}
});
$('button').click(function () {
var color = localStorage.getItem('color');
if (color == 'green') {
$('#div').removeClass().addClass('red');
color = 'red';
} else {
$('#div').removeClass().addClass('green');
color = 'green';
}
localStorage.setItem('color', color);
});
Basically, the idea here is to check for the value on page load and set your CSS based on that, then wait for user input to change the value and CSS together.
Here's what this code looks like in action: http://output.jsbin.com/yexahatoye
Thank you very much Michael Parker for your help.
I now have a solution after fiddling about for a while and learning a lot in the process:
for (var i = 0; i < devPlan.length; i++) {
var item = devPlan[i].tables.completion[0].active;
if (item == true) {
$('#' + i).find('.info-row').addClass('background-green');
}
else {
$('#' + i).find('.info-row').addClass('background-amber');
}
}
To apply the CSS I have used the table row ID to apply the CSS. Hopefully it helps someone else.
I have this two HTML Form buttons with an onclick action associated to each one.
<input type=button name=sel value="Select all" onclick="alert('Error!');">
<input type=button name=desel value="Deselect all" onclick="alert('Error!');">
Unfortunately this action changes from time to time. It can be
onclick="";>
or
onclick="alert('Error!');"
or
onclick="checkAll('stato_nave');"
I'm trying to write some javascript code that verifies what is the function invoked and change it if needed:
var button=document.getElementsByName('sel')[0];
// I don't want to change it when it is empty or calls the 'checkAll' function
if( button.getAttribute("onclick") != "checkAll('stato_nave');" &&
button.getAttribute("onclick") != ""){
//modify button
document.getElementsByName('sel')[0].setAttribute("onclick","set(1)");
document.getElementsByName('desel')[0].setAttribute("onclick","set(0)");
} //set(1) and set(0) being two irrelevant function
Unfortunately none of this work.
Going back some steps I noticed that
alert( document.getElementsByName('sel')[0].onclick);
does not output the onclick content, as I expected, but outputs:
function onclick(event) {
alert("Error!");
}
So i guess that the comparisons fails for this reason, I cannot compare a function with a string.
Does anyone has a guess on how to distinguish which function is associated to the onclick attribute?
This works
http://jsfiddle.net/mplungjan/HzvEh/
var button=document.getElementsByName('desel')[0];
// I don't want to change it when it is empty or calls the 'checkAll' function
var click = button.getAttribute("onclick");
if (click.indexOf('error') ) {
document.getElementsByName('sel')[0].onclick=function() {setIt(1)};
document.getElementsByName('desel')[0].onclick=function() {setIt(0)};
}
function setIt(num) { alert(num)}
But why not move the onclick to a script
window.onload=function() {
var button1 = document.getElementsByName('sel')[0];
var button2 = document.getElementsByName('desel')[0];
if (somereason && someotherreason) {
button1.onclick=function() {
sel(1);
}
button2.onclick=function() {
sel(0);
}
}
else if (somereason) {
button1.onclick=function() {
alert("Error");
}
}
else if (someotherreason) {
button1.onclick=function() {
checkAll('stato_nave')
}
}
}
Try casting the onclick attribute to a string. Then you can at least check the index of checkAll and whether it is empty. After that you can bind those input elements to the new onclick functions easily.
var sel = document.getElementsByName('sel')[0];
var desel = document.getElementsByName('desel')[0];
var onclick = sel.getAttribute("onclick").toString();
if (onclick.indexOf("checkAll") == -1 && onclick != "") {
sel.onclick = function() { set(1) };
desel.onclick = function() { set(0) };
}
function set(number)
{
alert("worked! : " + number);
}
working example: http://jsfiddle.net/fAJ6v/1/
working example when there is a checkAll method: http://jsfiddle.net/fAJ6v/3/
So, I have some faux checkboxes (so I could style them) that work with jQuery to act as checked or not checked. There are a number of faux checkboxes in my document, and for each one I have a click function:
var productInterest = [];
productInterest[0] = false;
productInterest[1] = false;
productInterest[2] = false;
// here is one function of the three:
$('#productOne').click(function() {
if (productInterest[0] == false) {
$(this).addClass("checkboxChecked");
productInterest[0] = true;
} else {
$(this).removeClass("checkboxChecked");
productInterest[0] = false;
}
});
The problem seems to be that there is an error in the if statement, because it will check, but not uncheck. In other words it will add the class, but the variable won't change so it still thinks its checked. Anybody have any ideas? Thanks for your help.
UPDATE: So, I need to show you all my code because it works in the way I supplied it (thanks commenters for helping me realize that)... just not in the way its actually being used on my site. so below please find the code in its entirety.
Everything needs to happen in one function, because the UI and data for each checkbox need to be updated at once. So here is the complete function:
$('input[name=silkInterest]').click(function() { // they all have the same name
var silkInterest = [];
silkInterest[0] = false;
silkInterest[1] = false;
silkInterest[2] = false;
if ($(this).is('#silkSilk')) { // function stops working because the .is()
if (silkInterest[0] == false) {
$(this).addClass("checkboxChecked");
silkInterest[0] = true;
} else {
$(this).removeClass("checkboxChecked");
silkInterest[0] = false;
}
alert(silkInterest[0]);
}
if ($(this).is('#silkAlmond')) {
if (silkInterest[1] == false) {
$(this).addClass("checkboxChecked");
silkInterest[1] = true;
} else {
$(this).removeClass("checkboxChecked");
silkInterest[1] = false;
}
}
if ($(this).is('#silkCoconut')) {
if (silkInterest[2] == false) {
$(this).addClass("checkboxChecked");
silkInterest[2] = true;
} else {
$(this).removeClass("checkboxChecked");
silkInterest[2] = false;
}
}
var silkInterestString = silkInterest.toString();
$('input[name=silkInterestAnswer]').val(silkInterestString);
// This last bit puts the code into a hidden field so I can capture it with php.
});
I can't spot the problem in your code, but you can simply use the class you're adding in place of the productInterest array. This lets you condense the code down to a single:
// Condense productOne, productTwo, etc...
$('[id^="product"]').click(function() {
// Condense addClass, removeClass
$(this).toggleClass('checkboxChecked');
});
And to check if one of them is checked:
if ($('#productOne').hasClass('checkboxChecked')) {...}
This'll make sure the UI is always synced to the "data", so if there's other code that's interfering you'll be able to spot it.
Okay, just had a palm to forehead moment. In regards to my revised code- the variables get reset everytime I click. That was the problem. Duh.
I have a requirement to implement an "Unsaved Changes" prompt in an ASP .Net application. If a user modifies controls on a web form, and attempts to navigate away before saving, a prompt should appear warning them that they have unsaved changes, and give them the option to cancel and stay on the current page. The prompt should not display if the user hasn't touched any of the controls.
Ideally I'd like to implement this in JavaScript, but before I go down the path of rolling my own code, are there any existing frameworks or recommended design patterns for achieving this? Ideally I'd like something that can easily be reused across multiple pages with minimal changes.
Using jQuery:
var _isDirty = false;
$("input[type='text']").change(function(){
_isDirty = true;
});
// replicate for other input types and selects
Combine with onunload/onbeforeunload methods as required.
From the comments, the following references all input fields, without duplicating code:
$(':input').change(function () {
Using $(":input") refers to all input, textarea, select, and button elements.
One piece of the puzzle:
/**
* Determines if a form is dirty by comparing the current value of each element
* with its default value.
*
* #param {Form} form the form to be checked.
* #return {Boolean} <code>true</code> if the form is dirty, <code>false</code>
* otherwise.
*/
function formIsDirty(form) {
for (var i = 0; i < form.elements.length; i++) {
var element = form.elements[i];
var type = element.type;
if (type == "checkbox" || type == "radio") {
if (element.checked != element.defaultChecked) {
return true;
}
}
else if (type == "hidden" || type == "password" ||
type == "text" || type == "textarea") {
if (element.value != element.defaultValue) {
return true;
}
}
else if (type == "select-one" || type == "select-multiple") {
for (var j = 0; j < element.options.length; j++) {
if (element.options[j].selected !=
element.options[j].defaultSelected) {
return true;
}
}
}
}
return false;
}
And another:
window.onbeforeunload = function(e) {
e = e || window.event;
if (formIsDirty(document.forms["someForm"])) {
// For IE and Firefox
if (e) {
e.returnValue = "You have unsaved changes.";
}
// For Safari
return "You have unsaved changes.";
}
};
Wrap it all up, and what do you get?
var confirmExitIfModified = (function() {
function formIsDirty(form) {
// ...as above
}
return function(form, message) {
window.onbeforeunload = function(e) {
e = e || window.event;
if (formIsDirty(document.forms[form])) {
// For IE and Firefox
if (e) {
e.returnValue = message;
}
// For Safari
return message;
}
};
};
})();
confirmExitIfModified("someForm", "You have unsaved changes.");
You'll probably also want to change the registration of the beforeunload event handler to use LIBRARY_OF_CHOICE's event registration.
In the .aspx page, you need a Javascript function to tell whether or not the form info is "dirty"
<script language="javascript">
var isDirty = false;
function setDirty() {
isDirty = true;
}
function checkSave() {
var sSave;
if (isDirty == true) {
sSave = window.confirm("You have some changes that have not been saved. Click OK to save now or CANCEL to continue without saving.");
if (sSave == true) {
document.getElementById('__EVENTTARGET').value = 'btnSubmit';
document.getElementById('__EVENTARGUMENT').value = 'Click';
window.document.formName.submit();
} else {
return true;
}
}
}
</script>
<body class="StandardBody" onunload="checkSave()">
and in the codebehind, add the triggers to the input fields as well as resets on the submission/cancel buttons....
btnSubmit.Attributes.Add("onclick", "isDirty = 0;");
btnCancel.Attributes.Add("onclick", "isDirty = 0;");
txtName.Attributes.Add("onchange", "setDirty();");
txtAddress.Attributes.Add("onchange", "setDirty();");
//etc..
The following uses the browser's onbeforeunload function and jquery to capture any onchange event. IT also looks for any submit or reset buttons to reset the flag indicating changes have occurred.
dataChanged = 0; // global variable flags unsaved changes
function bindForChange(){
$('input,checkbox,textarea,radio,select').bind('change',function(event) { dataChanged = 1})
$(':reset,:submit').bind('click',function(event) { dataChanged = 0 })
}
function askConfirm(){
if (dataChanged){
return "You have some unsaved changes. Press OK to continue without saving."
}
}
window.onbeforeunload = askConfirm;
window.onload = bindForChange;
Thanks for the replies everyone. I ended up implementing a solution using JQuery and the Protect-Data plug-in. This allows me to automatically apply monitoring to all controls on a page.
There are a few caveats however, especially when dealing with an ASP .Net application:
When a user chooses the cancel option, the doPostBack function will throw a JavaScript error. I had to manually put a try-catch around the .submit call within doPostBack to suppress it.
On some pages, a user could perform an action that performs a postback to the same page, but isn't a save. This results in any JavaScript logic resetting, so it thinks nothing has changed after the postback when something may have. I had to implement a hidden textbox that gets posted back with the page, and is used to hold a simple boolean value indicating whether the data is dirty. This gets persisted across postbacks.
You may want some postbacks on the page to not trigger the dialog, such as a Save button. In this case, you can use JQuery to add an OnClick function which sets window.onbeforeunload to null.
Hopefully this is helpful for anyone else who has to implement something similar.
General Solution Supporting multiple forms in a given page (Just copy and paste in your project)
$(document).ready(function() {
$('form :input').change(function() {
$(this).closest('form').addClass('form-dirty');
});
$(window).bind('beforeunload', function() {
if($('form:not(.ignore-changes).form-dirty').length > 0) {
return 'You have unsaved changes, are you sure you want to discard them?';
}
});
$('form').bind('submit',function() {
$(this).closest('form').removeClass('form-dirty');
return true;
});
});
Note: This solution is combined from others' solutions to create a general integrated solution.
Features:
Just copy and paste into your app.
Supports Multiple Forms.
You can style or make actions dirty forms, since they've the class "form-dirty".
You can exclude some forms by adding the class 'ignore-changes'.
The following solution works for prototype (tested in FF, IE 6 and Safari). It uses a generic form observer (which fires form:changed when any fields of the form have been modified), which you can use for other stuff as well.
/* use this function to announce changes from your own scripts/event handlers.
* Example: onClick="makeDirty($(this).up('form'));"
*/
function makeDirty(form) {
form.fire("form:changed");
}
function handleChange(form, event) {
makeDirty(form);
}
/* generic form observer, ensure that form:changed is being fired whenever
* a field is being changed in that particular for
*/
function setupFormChangeObserver(form) {
var handler = handleChange.curry(form);
form.getElements().each(function (element) {
element.observe("change", handler);
});
}
/* installs a form protector to a form marked with class 'protectForm' */
function setupProtectForm() {
var form = $$("form.protectForm").first();
/* abort if no form */
if (!form) return;
setupFormChangeObserver(form);
var dirty = false;
form.observe("form:changed", function(event) {
dirty = true;
});
/* submitting the form makes the form clean again */
form.observe("submit", function(event) {
dirty = false;
});
/* unfortunatly a propper event handler doesn't appear to work with IE and Safari */
window.onbeforeunload = function(event) {
if (dirty) {
return "There are unsaved changes, they will be lost if you leave now.";
}
};
}
document.observe("dom:loaded", setupProtectForm);
Here's a javascript / jquery solution that is simple. It accounts for "undos" by the user, it is encapsulated within a function for ease of application, and it doesn't misfire on submit. Just call the function and pass the ID of your form.
This function serializes the form once when the page is loaded, and again before the user leaves the page. If the two form states are different, the prompt is shown.
Try it out: http://jsfiddle.net/skibulk/Ydt7Y/
function formUnloadPrompt(formSelector) {
var formA = $(formSelector).serialize(), formB, formSubmit = false;
// Detect Form Submit
$(formSelector).submit( function(){
formSubmit = true;
});
// Handle Form Unload
window.onbeforeunload = function(){
if (formSubmit) return;
formB = $(formSelector).serialize();
if (formA != formB) return "Your changes have not been saved.";
};
}
$(function(){
formUnloadPrompt('form');
});
I recently contributed to an open source jQuery plugin called dirtyForms.
The plugin is designed to work with dynamically added HTML, supports multiple forms, can support virtually any dialog framework, falls back to the browser beforeunload dialog, has a pluggable helper framework to support getting dirty status from custom editors (a tinyMCE plugin is included), works within iFrames, and the dirty status can be set or reset at will.
https://github.com/snikch/jquery.dirtyforms
Detect form changes with using jQuery is very simple:
var formInitVal = $('#formId').serialize(); // detect form init value after form is displayed
// check for form changes
if ($('#formId').serialize() != formInitVal) {
// show confirmation alert
}
I expanded on Slace's suggestion above, to include most editable elements and also excluding certain elements (with a CSS style called "srSearch" here) from causing the dirty flag to be set.
<script type="text/javascript">
var _isDirty = false;
$(document).ready(function () {
// Set exclude CSS class on radio-button list elements
$('table.srSearch input:radio').addClass("srSearch");
$("input[type='text'],input[type='radio'],select,textarea").not(".srSearch").change(function () {
_isDirty = true;
});
});
$(window).bind('beforeunload', function () {
if (_isDirty) {
return 'You have unsaved changes.';
}
});
var unsaved = false;
$(":input").change(function () {
unsaved = true;
});
function unloadPage() {
if (unsaved) {
alert("You have unsaved changes on this page. Do you want to leave this page and discard your changes or stay on this page?");
}
}
window.onbeforeunload = unloadPage;
This is exactly what the Fleegix.js plugin fleegix.form.diff (http://js.fleegix.org/plugins/form/diff) was created for. Serialize the initial state of the form on load using fleegix.form.toObject (http://js.fleegix.org/ref#fleegix.form.toObject) and save it in a variable, then compare with the current state using fleegix.form.diff on unload. Easy as pie.
A lot of outdated answers so here's something a little more modern.
ES6
let dirty = false
document.querySelectorAll('form').forEach(e => e.onchange = () => dirty = true)
One method, using arrays to hold the variables so changes can be tracked.
Here's a very simple method to detect changes, but the rest isn't as elegant.
Another method which is fairly simple and small, from Farfetched Blog:
<body onLoad="lookForChanges()" onBeforeUnload="return warnOfUnsavedChanges()">
<form>
<select name=a multiple>
<option value=1>1
<option value=2>2
<option value=3>3
</select>
<input name=b value=123>
<input type=submit>
</form>
<script>
var changed = 0;
function recordChange() {
changed = 1;
}
function recordChangeIfChangeKey(myevent) {
if (myevent.which && !myevent.ctrlKey && !myevent.ctrlKey)
recordChange(myevent);
}
function ignoreChange() {
changed = 0;
}
function lookForChanges() {
var origfunc;
for (i = 0; i < document.forms.length; i++) {
for (j = 0; j < document.forms[i].elements.length; j++) {
var formField=document.forms[i].elements[j];
var formFieldType=formField.type.toLowerCase();
if (formFieldType == 'checkbox' || formFieldType == 'radio') {
addHandler(formField, 'click', recordChange);
} else if (formFieldType == 'text' || formFieldType == 'textarea') {
if (formField.attachEvent) {
addHandler(formField, 'keypress', recordChange);
} else {
addHandler(formField, 'keypress', recordChangeIfChangeKey);
}
} else if (formFieldType == 'select-multiple' || formFieldType == 'select-one') {
addHandler(formField, 'change', recordChange);
}
}
addHandler(document.forms[i], 'submit', ignoreChange);
}
}
function warnOfUnsavedChanges() {
if (changed) {
if ("event" in window) //ie
event.returnValue = 'You have unsaved changes on this page, which will be discarded if you leave now. Click "Cancel" in order to save them first.';
else //netscape
return false;
}
}
function addHandler(target, eventName, handler) {
if (target.attachEvent) {
target.attachEvent('on'+eventName, handler);
} else {
target.addEventListener(eventName, handler, false);
}
}
</script>
In IE document.ready will not work properly it will update the values of input.
so we need to bind load event inside the document.ready function that will handle for IE browser also.
below is the code you should put inside the document.ready function.
$(document).ready(function () {
$(window).bind("load", function () {
$("input, select").change(function () {});
});
});
I have found that this one works in Chrome with an exception... The messages being returned do not match those in the script:
dataChanged = 0; // global variable flags unsaved changes
function bindForChange() {
$("input,checkbox,textarea,radio,select").bind("change", function (_event) {
dataChanged = 1;
});
$(":reset,:submit").bind("click", function (_event) {
dataChanged = 0;
});
}
function askConfirm() {
if (dataChanged) {
var message =
"You have some unsaved changes. Press OK to continue without saving.";
return message;
}
}
window.onbeforeunload = askConfirm;
window.onload = bindForChange;
The messages returned seem to be triggered by the specific type of action I'm performing. A RELOAD displays a question "Reload Site?
And a windows close returns a "Leave Site?" message.