5

I have a simple class that has a few methods(for now). I can instantiate it and call the init function, but I cant call another method from the onchange attribute.

here is the class:

var ScheduleViewer = (function() {
var options = {
  container: 'trip_stops',
  schedule: {}
};

function ScheduleViewer (){};

ScheduleViewer.prototype.init = function(params) {
  $.extend(options, params);
  // setTimeout(function() {
  //   ScheduleViewer.addListener(options);
  // }, 3000);
  this.addListener(options);
}

ScheduleViewer.prototype.getSchedule = function(trip_id) {
  var _id = trip_id;
  console.log(_id);
}

ScheduleViewer.prototype.addListener = function(options) {
  console.log("adding listener");
   var _id = options.select_id;
   console.log($('#train_select').length);// zero assuming timing issue
   $('#'+_id).on('change', function() {
     alert("changed");
   })
}
return ScheduleViewer;
})();

the call

<div id="trip_stops" class="trip_options">
        <% if (trips.length > 0) {  %>
            <%
                var params = {
                schedule: schedule
              };
              var scheduler = new ScheduleViewer();
              scheduler.init(params);
            %>
            <select id="train_select">
                <option value="0" selected disabled>Select a train</option>
                <% $.each(trips, function(index, val) { %>
                    <option value="<%= val.trip_id %>">
                        <%= val.train_num %> Train
                    </option>
                <% }); %>
            </select>
        <% } else { %>
            No trips scheduled.
        <% } %>
    </div>

Note that Im using jqote for templating.

I get the log from the init call, but then fails in the onchange with Uncaught ReferenceError: scheduler is not defined. Im not sure what Im doing wrong. Any pointers?

Thanks

EDIT: I made an attempt to add a listener that gets called at initialization. Im assuming that because of timing issues the listener is not getting bind. Now this is where my inexperience comes in play I tried to setTimeout but the function call is not happening as is.

8
  • What's the stuff between <% %>? Server-side JScript? Commented Aug 1, 2013 at 17:21
  • @bfavaretto I think it's like ASP.NET or something Commented Aug 1, 2013 at 17:29
  • jqote = javascript templating. Commented Aug 1, 2013 at 17:31
  • So I believe what you declare inside the template tags is preprocessed, and not available in the global scope to an inline onchange attribute. Commented Aug 1, 2013 at 17:40
  • Why does every ScheduleViewer instance have the same options? And notice that schedule in your params object is undefined. Commented Aug 1, 2013 at 18:53

5 Answers 5

2

I don't know why this may not work, but you shouldn't really use inline styles/functions anyway.

Why don't you try and get the element in your script the apply the onchange function to it.

var scheduler = new ScheduleViewer();
    select = document.getElementById('train_select');

scheduler.init(params);

select.onchange = function() {
   scheduler.getSchedule(this.value)
};
Sign up to request clarification or add additional context in comments.

1 Comment

Ill try to add a listener. Thanks!
1

Try binding the event in javascript and remove the inline event.

var scheduler = new ScheduleViewer();
scheduler.init(params);

$(document).on('change', '#select', function() {
   scheduler.getSchedule(this.value)
});

Comments

0

I have never used jQote before, however could it be because of the way jQote handles variable declarations? Try instanciating your scheduler object outside the templating code.

<script>
var scheduler = new ScheduleViewer(),
    params = { schedule: schedule };

scheduler.init(params);
</script>

<!-- template code... -->

Also please note that the way you have written your code, all ScheduleViewer instances will share the same options object. I am not sure what you will be doing with this options object, but I guess that's not the desired behaviour.

Finally, like already stated by others, adding event listeners inline is a bad practice and you should register your even handlers programmatically using JavaScript. Either with the native addEventListener function or with helper functions of your favorite library.

1 Comment

@Connor, It appears to be his client-side templating library. aefxx.com/jquery-plugins/jqote
0

I'm not familiar with jqote, but it looks like a scoping problem. If you must use the inline onchange, put the object reference in the window object and access it from there.

window['scheduler'] = new ScheduleViewer();
window['scheduler'].init(params);

And

<select id="train_select" onchange="window['scheduler'].getSchedule(this.value)">

3 Comments

These are all the same, so which one do you prefer? scheduler = new ScheduleViewer(); | OR | window.scheduler = new ScheduleViewer(); | OR | window['scheduler'] = new ScheduleViewer();
They're the same if the jqote section is not changing the scope of scheduler declaration. If the declaration were in a script tag I would not be proposing this.
Still dot notation is better, ie window.scheduler
0

So to solve the issue I ended up adding the class to the window object. I had issues with the listeners as the code that loads the template was not fast enough and the binding was not happening.

The class looks like:

window.ScheduleViewer = (function() {
var options = {
  container: 'trip_stops',
  schedule: {}
};

this.init = function(params) {
  $.extend(options, params); 
}

this.getSchedule = function(trip_id) {
  var _id = trip_id;
  //Do some cool stuff with GTFS data
}
//More functions

return this;
})();

The templated html:

<div id="trip_stops" class="trip_options">
        <% if (trips.length > 0) {  %>
            <%
                var params = {
                schedule: schedule
              };
              ScheduleViewer.init(params);
            %>
            <select id="train_select" onchange="ScheduleViewer.getSchedule(this.value)">
                <option value="0" selected disabled>Select a train</option>
                <% $.each(trips, function(index, val) { %>
                    <option value="<%= val.trip_id %>">
                        <%= val.train_num %> Train
                    </option>
                <% }); %>
            </select>
        <% } else { %>
            No trips scheduled.
        <% } %>
    </div>

Thank you for all the responses.

Comments

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.