0

I have a process designed to change concatenate separate address fields entered by a user into a single hidden field to be used by Google Maps to drop a pin on the location.

The Event Listeners responsible for the concatenation are functioning properly, but when I try to chain a listener to the hidden field to execute the pin placement, the function isn't executed.

Here is the code I am using:

$(document).ready(function initMap() {

    ...

    function join_address() {
        var address = document.getElementById('id_form5-address1').value;
        var city = document.getElementById('id_form5-city').value;
        var state = document.getElementById('id_form5-state').value;
        var zip = document.getElementById('id_form5-zip').value;
        document.getElementById('id_jointAddress').value = address+", "+city+", "+state+", "+zip;
        }

    document.getElementById("id_form5-city").addEventListener("change", join_address);
    document.getElementById("id_form5-state").addEventListener("change", join_address);
    document.getElementById("id_form5-zip").addEventListener("change", join_address);

    function codeAddress() {
        console.log("function engaged")
        var address = document.getElementById("id_jointAddress").value;
        geocoder.geocode( { 'address': address}, function(results, status) {
          if (status == google.maps.GeocoderStatus.OK) {
            map.setCenter(results[0].geometry.location);
            var marker = new google.maps.Marker({
                map: map,
                position: results[0].geometry.location
            });
          } else {
            alert("Geocode was not successful for the following reason: " + status);
          }
        });
      }

    document.getElementById("id_jointAddress").addEventListener("change", codeAddress);

    ...

}

"Function engaged" never even prints to console, so I am assuming that it is the listener that is constructed wrong, or is in the wrong place. Can anyone assist?

Edit: Here is the html object in question:

<input type="hidden" name="jointAddress" id="id_jointAddress">

If I unhide the element, and type in the field directly it triggers the listener. I think the "change" listener does not respond to changes made through Javascript. Does anyone know of a solution that will work for me?

8
  • what type of object is #id_jointAddress? Commented Nov 3, 2015 at 21:55
  • Did it return you html object document.getElementById("id_jointAddress")? Commented Nov 3, 2015 at 21:56
  • Mind providing an example? It seems to work fine. Commented Nov 3, 2015 at 21:57
  • 1
    it looks like you're wrapping everything in the function initMap() is that ever called? Commented Nov 3, 2015 at 21:58
  • I added the html object that I am using. The other event listeners are functioning, I'm not sure why this final one is not working. Commented Nov 3, 2015 at 22:00

2 Answers 2

1

The problem is that setting value programatically doesn't fire the change event. You can fire a synthetic event on your own. See http://jsfiddle.net/mendesjuan/uct8bL9d/2/

If you use the fireEvent function I linked to, you can just add the following line in your code

var joint = document.getElementById('id_jointAddress');   
joint.value = address + ", " + city + ", " + state + ", " + zip;
fireEvent(joint, 'change');

Here's a reduction of the problem:

document.querySelector('input').addEventListener('change', function() {
    document.getElementById('output').innerHTML +='changed <br />'; 
});

document.querySelector('button').addEventListener('click', function() {
    var input =  document.querySelector('input');
    input.value = new Date();
    fireEvent(input, 'change')
});

/**
 * Fire an event handler to the specified node. Event handlers can detect that the event was fired programatically
 * by testing for a 'synthetic=true' property on the event object
 * @param {HTMLNode} node The node to fire the event handler on.
 * @param {String} eventName The name of the event without the "on" (e.g., "focus")
 */
function fireEvent(node, eventName) {
    // Make sure we use the ownerDocument from the provided node to avoid cross-window problems
    var doc;
    if (node.ownerDocument) {
        doc = node.ownerDocument;
    } else if (node.nodeType == 9){
        // the node may be the document itself, nodeType 9 = DOCUMENT_NODE
        doc = node;
    } else {
        throw new Error("Invalid node passed to fireEvent: " + node.id);
    }

     if (node.dispatchEvent) {
        // Gecko-style approach (now the standard) takes more work
        var eventClass = "";

        // Different events have different event classes.
        // If this switch statement can't map an eventName to an eventClass,
        // the event firing is going to fail.
        switch (eventName) {
            case "click": // Dispatching of 'click' appears to not work correctly in Safari. Use 'mousedown' or 'mouseup' instead.
            case "mousedown":
            case "mouseup":
                eventClass = "MouseEvents";
                break;

            case "focus":
            case "change":
            case "blur":
            case "select":
                eventClass = "HTMLEvents";
                break;

            default:
                throw "fireEvent: Couldn't find an event class for event '" + eventName + "'.";
                break;
        }
        var event = doc.createEvent(eventClass);

        var bubbles = eventName == "change" ? false : true;
        event.initEvent(eventName, bubbles, true); // All events created as bubbling and cancelable.

        event.synthetic = true; // allow detection of synthetic events
        // The second parameter says go ahead with the default action
        node.dispatchEvent(event, true);
    } else  if (node.fireEvent) {
        // IE-old school style
        var event = doc.createEventObject();
        event.synthetic = true; // allow detection of synthetic events
        node.fireEvent("on" + eventName, event);
    }
};
<input />
<button>Set programatically</button>

<div id="output"> </div>

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! This helped a lot
0

The problem is that setting value programatically doesn't fire the change handlers. If you use jQuery and call val(), then it will fire a synthetic change event. Try updating your JavaScript to utilize jQuery.

$(function(){
    function initMap() {
        ...
    }

    function join_address() {
        var address = $('#id_form5-address1').val();
        var city = $('#id_form5-city').val();
        var state = $('#id_form5-state').val();
        var zip = $('#id_form5-zip').val();
        $('#id_jointAddress').val(address+", "+city+", "+state+", "+zip);
    }

    $("#id_form5-city").on("change", join_address);
    $("#id_form5-state").on("change", join_address);
    $("#id_form5-zip").on("change", join_address);

    function codeAddress() {
        console.log("function engaged")
        var address = $("#id_jointAddress").val();
        geocoder.geocode( { 'address': address}, function(results, status) {
          if (status == google.maps.GeocoderStatus.OK) {
            map.setCenter(results[0].geometry.location);
            var marker = new google.maps.Marker({
                map: map,
                position: results[0].geometry.location
            });
          } else {
            alert("Geocode was not successful for the following reason: " + status);
          }
        });
      }

    $("#id_jointAddress").on("change", codeAddress);
});

3 Comments

Thanks, I tried making these changes, but it broke it further. I'm not really used to jQuery. If I can't find an easy javascript solution, I will try harder to implement this change.
let me know if you have any interest in implementing jQuery, I can help you through the errors you're getting
I tried this again and got the page working, but it seems to be stuck in the same spot. The join_address function executes successfully, but the codeAddress function is never called.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.