0

After refer to page as Getting value of select (dropdown) before change, I am trying to implement below logic with jQuery:

Two element relation: indicator toggle yes/no to control reason editable or not The 1st column is when page load indicator initial value, last column is final choice, column(s) between are redundant option(especially in case user just toggle it but not really want anything on reason), because indicator actually only contain yes/no two values, simplify 4 cases below:

(1) Y - N (indicator on page load as Y, finally change to N) --> reason editable

(2) Y - N - Y (indicator on page load as Y, redundant change as N, finally change to Y) --> reason editable

(3) N - Y (indicator on page load as N, finally change to Y) --> reason editable

(4) N - Y - N (indicator on page load as N, redundant change as Y, finally change to N) --> reason NOT editable

The problem now is as code below, it never hit case (4), I observe indicator previous value retrieved, but it seems NOT keep as initial value when page load, e.g when page load, indicator is 'N', user first change it to 'Y', then change back to 'N', but the pre data value will be 'Y', not what I expect as original page load initial value 'N', I use a pop up dialog to observe this issue.

Could someone help me to figure out how to change this code to implement the logic above which including case (4) ?

(I guess it relate to last statement in script section as jqThis.data("prev", after_change); which update the previous data) ? But how to add logic before that to keep a real initial previous value (on page load value) for use in if-else logic ?

$(window).load(function() {
  var indicator = $(document.getElementById("indicator"));

  // set the pre data, usually needed after you initialize the select element
  indicator.data("prev", indicator.val());

  // Handle initial status of indicator, when page load, if it is 'N' disable
  // reason field, if it is 'Y' open reason field
  if (indicator.data("prev") == 'N') {
    $(document.getElementById("reason")).attr('disabled', 'disabled');
  } else {
    $(document.getElementById("reason")).removeAttr('disabled');
  }

  // Handle change status of indicator, 
  indicator.change(function(data) {
    var jqThis = $(this);

    // get changed data
    var after_change = jqThis.val();

    // get the pre data (Question : I expect the pre data should be original page load value, but 
    // seems it always the latest one before current value ?)
    // e.g when page load, indicator is 'N', user first change it to 'Y', then change back to 'N', but
    // the pre data value will be 'Y', not what I expect as original page load initial value 'N'
    // I use a pop up dialog to observe this issue.
    var before_change = jqThis.data("prev");

    // Debug
    console.log("before:",before_change);

    // do your work here
    if (before_change == 'N' && after_change == 'Y') {
      // Change indicator from No to Yes, please type in reason
      $(document.getElementById("reason")).attr('disabled', 'disabled');
    } else if (before_change == 'Y' && after_change == 'N') {
      // Change indicator from Yes to No, please type in reason
      $(document.getElementById("reason")).attr('disabled', 'disabled');
    } else if (before_change == 'N' && after_change == 'N') {
      // Keep indicator as its initial status No
      $(document.getElementById("reason")).removeAttr('disabled');
    } else if (before_change == 'Y' && after_change == 'Y') {
      // Keep indicator as its initial status Yes, if necessary you can type in new reason
      $(document.getElementById("reason")).attr('disabled', 'disabled');
    }

    // update the pre data
    jqThis.data("prev", after_change);
  });
});
.htmlClass {
  padding: 8px;
  border: 1px solid blue;
  margin-bottom: 8px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<form name="myform">
  <div align="center">
    <select id="indicator">
      <option value="Y">Yes</option>
      <option value="N">No</option>
    </select>
    <textarea id="reason">
    </textarea>
</form>
Community
  • 1
  • 1
Lampard
  • 345
  • 4
  • 14
  • If you have a jQuery question, please create a [mcve] that does not require us to run a java server to test your code. Please post only jQuery+HTML. Also where is your focus handler that saves the initial state? You can also use jqThis[0].defaultValue – mplungjan Dec 10 '16 at 06:46
  • Also `$("#mypage\\:indicator");` – mplungjan Dec 10 '16 at 06:51
  • @mplungjan, hi, i am quite new to jQuery, so didn't get the rule as you say, in my code, i didn't use focus event, just save the initial indicator value(on page load) in `var inidicator.data("prev", indicator.val())`, then retrieve the value by `"prev"`, but looks like in every `change event`, last line will update `"prev"` value, that's my guess I always retrieve the most recent value before current value, not the real initial one. – Lampard Dec 10 '16 at 06:55
  • Yeah, I see it now. But I cannot verify your problem since I cannot run your code. – mplungjan Dec 10 '16 at 07:01
  • @mplungjan, thanks, let me try to convert it in your suggest style, and edit it later, as this one is build on JSF / RichFaces, I may need some time – Lampard Dec 10 '16 at 07:04
  • Just right-click in the rendered page, copy and use the `<>` snippet editor to tidy the html - we just need the select – mplungjan Dec 10 '16 at 07:08
  • Also I do not see any `reason` here – mplungjan Dec 10 '16 at 07:12
  • @mplungjan, and as your suggest, I edit it into a purely jQuery and html format, some syntax changed from xhtml to html, but not influence the question, I can run up this page on my Chrome, please help to have a look, thank you. – Lampard Dec 10 '16 at 07:40
  • So I made a snippet for you. I used jQuery 1.9.1 since that is the highest IE8 compatible version but way better than your 1.4.3. – mplungjan Dec 10 '16 at 08:10

2 Answers2

0

Perhaps if you

  1. use prop
  2. do NOT remove the prop
  3. simplify your logic
  4. use a more recent version of jQuery

$(window).load(function() {
  var $indicator = $("#indicator"); // if you have colons, use #mypage\\:indicator
  var $reason = $("#reason");

  // set the pre data, usually needed after you initialize the select element
  $indicator.data("prev", $indicator.val());

  // Handle initial status of indicator, when page load, if it is 'N' disable
  // reason field, if it is 'Y' open reason field
  $reason.prop('disabled', $indicator.data("prev") == 'N');

  // Handle change status of indicator, 
  $indicator.on("change", function(data) {
    var jqThis = $(this);

    // get changed data
    var after_change = jqThis.val();

    // get the pre data (Question : I expect the pre data should be original page load value, but 
    // seems it always the latest one before current value ?)
    // e.g when page load, indicator is 'N', user first change it to 'Y', then change back to 'N', but
    // the pre data value will be 'Y', not what I expect as original page load initial value 'N'
    // I use a pop up dialog to observe this issue.

    var before_change = jqThis.data("prev");

    // Debug
    console.log("before:", before_change);

    // do your work here
    /* var dis = (before_change == 'N' && after_change == 'Y') ||
              (before_change == 'Y' && after_change == 'N') ||
              (before_change == 'Y' && after_change == 'Y') */
    var dis = !(before_change == 'N' && after_change == 'N'); 
    $reason.prop('disabled', dis);

    // update the pre data
    jqThis.data("prev", after_change);
  });
});
.htmlClass {
  padding: 8px;
  border: 1px solid blue;
  margin-bottom: 8px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<form name="myform">
  <div align="center">
    <select id="indicator">
      <option value="Y">Yes</option>
      <option value="N">No</option>
    </select>
    <textarea id="reason">
    </textarea>
</form>
mplungjan
  • 134,906
  • 25
  • 152
  • 209
  • thank you for your work, and based on your change, I find the issue and edit inline, it caused exactly on last line which update the previous value, if comment it out, we can keep the real initial value when page load, and use it to compare with current value. To observe the issue, we have to start with `N` case, as **N - Y - N** is special, if keep original logic, it will editable finally, but as my goal, it should not editable, so remove last line, keep previous value as `N` and logic is right. – Lampard Dec 10 '16 at 09:12
0

First thanks to mplungjan's work, as I am trying to edit on his version but refused by peer reviewer and suggest with post a new one, I will post one based on his answer which declare and resolve the issue.

$(window).load(function() {
  var $indicator = $("#indicator"); // if you have colons, use #mypage\\:indicator
  var $reason = $("#reason");

  // set the pre data, usually needed after you initialize the select element
  $indicator.data("prev", $indicator.val());

  // Handle initial status of indicator, when page load, if it is 'N' disable
  // reason field, if it is 'Y' open reason field
  $reason.prop('disabled', $indicator.data("prev") == 'N');

  // Handle change status of indicator, 
  $indicator.on("change", function(data) {
    var jqThis = $(this);

    // get changed data
    var after_change = jqThis.val();

    // get the pre data (Question : I expect the pre data should be original page load value, but 
    // seems it always the latest one before current value ?)
    // e.g when page load, indicator is 'N', user first change it to 'Y', then change back to 'N', but
    // the pre data value will be 'Y', not what I expect as original page load initial value 'N'
    // I use a pop up dialog to observe this issue.

    var before_change = jqThis.data("prev");

    // Debug
    console.log("before:", before_change);

    // do your work here
    /* var dis = (before_change == 'N' && after_change == 'Y') ||
              (before_change == 'Y' && after_change == 'N') ||
              (before_change == 'Y' && after_change == 'Y') */
    //var dis = !(before_change == 'N' && after_change == 'N'); 
    //$reason.prop('disabled', dis);

    // Before concise I just keep original logic in question
    // to show the issue
    if (before_change == 'N' && after_change == 'Y') {
      $reason.prop('disabled', false);
    } else if (before_change == 'Y' && after_change == 'N') {
      $reason.prop('disabled', false);
    } else if (before_change == 'N' && after_change == 'N') {
      $reason.prop('disabled', true);
    } else if (before_change == 'Y' && after_change == 'Y') {
      $reason.prop('disabled', false);
    }

    // update the pre data
    // !! IMPORTANT !! --> This is exactly what cause only
    // get most recent value before current changed value,
    // as continuously update the value in data.
    // As I test, the easiest way is to comment out this
    // line, it will never update the indicator's real 
    // initial value when page load, so that's my goal which
    // compare "real initial value" with "current changed value"
    jqThis.data("prev", after_change);
  });
});
.htmlClass {
  padding: 8px;
  border: 1px solid blue;
  margin-bottom: 8px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<form name="myform">
  <div align="center">
    <select id="indicator">
      <option value="Y">Yes</option>
      <!-- To observe the real issue, need to set default case as 'N' -->
      <option value="N" selected="selected">No</option>
    </select>
    <textarea id="reason">
    </textarea>
</form>
Lampard
  • 345
  • 4
  • 14