I render a list Post to template after select it from window scroll event and i need to get model and event in this Post.
I want to get view Post for using model or event from route when window scroll event? have a way to do it?
sub view:
Post = Backbone.View.extend({
tagName: "div",
className: "post",
initialize: function () {
this.post = this.model;
this.render();
},
render: function () {
$(this.el).html(this.template(this.post));
return this;
}
});
view:
ListPost = Backbone.View.extend({
tagName: "div",
className: "listpost",
initialize: function(models, options){
this.listpost = options.listpost;
this.render();
},
render: function () {
_.each(this.listpost, function (post) {
$(this.el).append(new Post({model: post}).el);
}, this);
return this;
}});
route:
var AppRouter = Backbone.Router.extend({
initialize: function () {
$('body').html(new ListPost([], {listpost: posts}).el);
window.onscroll = this.scroll;
},
scroll : function() {
var element = $('.post');
var find_out = false;
for(var i = 0; i< element.length; i++) {
if(find_out) break;
var post = element[i];
if(post.getBoundingClientRect) {
var rect = post.getBoundingClientRect();
x = rect.bottom;
y = rect.top;
if(x > 0) {
if(x > 480/3) {
//result is post
// how i can select this post to sub view Post
find_out = true;
}
}
}
}
}});
Move the scroll functionality to the ListPost so you can have an array of views in your scope.
Example:
ListPost = Backbone.View.extend({
tagName: "div",
className: "listpost",
initialize: function(models, options){
this.listpost = options.listpost;
// Add scroll event here ($.proxy makes sure the event can see this.element).
$(document).scrool( $.proxy(this.scroll, this) );
this.render();
// Create an array to hold a reference to all Post views.
this.element = [];
},
render: function () {
_.each(this.listpost, function (post) {
// Create the post views and add them to the array.
var postView = new Post({model: post});
this.element.push( postView );
$(this.el).append(postView.el);
}, this);
return this;
},
scroll: function() {
var find_out = false;
// Make sure you use this with element.
for(var i = 0; i< this.element.length; i++) {
if(find_out) break;
// Post is now a Backbone view.
var post = this.element[i];
// Make sure you use post.el to access the views DOM element.
if(post.el.getBoundingClientRect) {
var rect = post.el.getBoundingClientRect();
x = rect.bottom;
y = rect.top;
if(x > 0) {
if(x > 480/3) {
//result is post
// how i can select this post to sub view Post
find_out = true;
// Do what you want with the backbone view.
post.render();
console.log(post.model);
}
}
}
}
}
});
Related
I am trying to filter a collection based on an attribute called status. Once filtered I want to re-render the view to reflect the filtered results. So far I have come up with this function in my collection.
var ProjectCollection = Backbone.Collection.extend({
url: '/projects',
model: app.Project,
status: function( status ) {
return this.filter(function(project){
return project.get('status') == status;
});
},
});
In my view I the run the following,
filterStatus: function(e) {
e.preventDefault();
var elm = $(e.currentTarget),
status = elm.data('statusid');
this.collection.reset( this.collection.status( status ) );
}
The render function is below along with it's functions that also get called,
render: function() {
this.$el.empty();
console.log("ProjectDashboardView render");
if(this.collection.length < 1) {
var noProjects = new app.noProjectsDashboard;
} else {
this.addAll();
}
$(".month-column").height($(".project-holder").height() + 50);
},
addAll: function() {
console.log("allAdd");
this.collection.each(function(model){
this.addOne(model)
}, this);
},
addOne: function(model) {
var view = new app.ProjectTimelineEntry({
model: model
});
this.$el.append( view.render() );
var number_of_days_in_calendar = 0;
$('.month-column').each(function(){
number_of_days_in_calendar = number_of_days_in_calendar + parseInt($(this).data('days'));
});
var day_width = 1/(number_of_days_in_calendar) * 100;
//Is the start after the end of Feb?
var start_date = new Date(model.get('start_date'));
var march_date = new Date("03/01/2014");
var current_month = start_date.getMonth() + 1;
var march_month = march_date.getMonth() + 1;
console.log(current_month, march_month);
if(current_month <= march_month) {
var start_date_offset = model.get('num_days_from_year_start') * day_width;
var duration_of_project = model.get('run_number_days') * day_width;
//view.$('.duration-bar').css("background-color", model.get('color'));
view.$el.find('.duration-bar').css({
width : duration_of_project + "%",
"margin-left" : start_date_offset + "%"
}, 500);
} else {
var start_date_offset = (model.get('num_days_from_year_start') + 2) * day_width;
var duration_of_project = model.get('run_number_days') * day_width;
//view.$('.duration-bar').css("background-color", model.get('color'));
view.$el.find('.duration-bar').css({
width : duration_of_project + "%",
"margin-left" : start_date_offset + "%"
}, 500);
}
// if(Date.parse(start_date) < new Date("01/03")) {
// console.log("before march");
// }
},
Now this filters the collection, however what happens is that when I try and filter the collection again, it filters the collection that I have just reset too, how can I filter the collection, run the views render() function once a filter is complete, but not keep resetting the collection?
As hindmost mentionned, you should add a visible field to app.Project model.
Then in ProjectView attach a listener to this field:
this.listenTo(this.model, "change:visible", this.onVisibleChange)
and the method definition:
onVisibleChange: function(){
$(this.el).css('display', (this.get('visible')) ? 'block': 'none')
}
In your filter method you run over the collection and change the visible field of each model accordingly to if it should or should not being rendered.
var ProjectCollection = Backbone.Collection.extend({
url: '/projects',
model: app.Project,
status: function( status ) {
return this.each(function(project){
project.set('visible', project.get('status') == status)
});
},
});
You have to add extra attribute to collection's model (app.Project) which will store the flag indicating if a project has to be displayed or not.
var app.Project = Backbone.Model.extend({
defaults: {
...
status: '',
display: true
}
};
Then you have to add the code to model View's render which will show/hide View's element depending on value of display attribute:
var ProjectView = Backbone.View.extend({
...
render: function() {
...
if (this.model.get('display'))
this.$el.show();
else
this.$el.hide();
...
return this;
},
...
};
And, finally you have to modify ProjectCollection's status method to set display attribute on each model:
var ProjectCollection = Backbone.Collection.extend({
url: '/projects',
model: app.Project,
status: function( status ) {
this.each(function(project){
project.set('display', project.get('status') == status);
});
},
...
});
I am using marionitte framework and i am trying to fire a trigger from one layout view to any other view but its function on the other view is invoked multiple times even though the trigger is fired only once.
Does anyone has got encountered the same issue and has resolved it please let me know the resolution so that i can use in my code.
w.src.SourceTabView = Backbone.Marionette.Layout.extend({
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template: "#src-template-source-tab-view",
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
regions: {
"change results" : "#src-template-change-results-region",
"change pagination" : "#src-template-change-pagination-region",
"document layout" : "#src-template-document-layout-region",
"workflow detail" : "#src-template-workflow-detail-region",
"job log" : "#src-template-job-log-region",
"source job" : "#src-template-job-region"
},
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
changeInfo: null,
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
mostRecentChange: null,
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
screenCapture: null,
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
regionSelector: null,
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tab: "details",
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
controls: {
institution: new w.EntitySelector(null,[]),
contentSetGroup: new w.EntitySelector(null,["cs"]),
pageTypes: new w.EntitySelector(null,["page_type"]),
prevTypes: new w.EntitySelector(null,["previous_type"])
},
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
initialize: function(){
this.listenTo( this.model , 'sync' , this.render );
var instTypes = [] ;
for( var instTypeEntityId in w.INST_TYPES ){
instTypes.push(instTypeEntityId);
}
this.controls.institution = new w.EntitySelector(null,instTypes);
this.controls.institution.minValueLength = 1;
this.controls.contentSetGroup.maxValueLength = 1;
this.controls.contentSetGroup.minValueLength = 1;
this.controls.prevTypes.minValueLength = 1;
this.controls.prevTypes.maxValueLength = 1;
this.fetchMostRecentChange();
this.regionSelector = null;
this.changeInfo = new w.src.ChangeInfo(this.model);
this.changeInfo.vent.on("change-selected", this.render);
this.changeInfo.vent.on("change-refreshed", this.render);
this.changeInfo.vent.on("workflow-selected", this.render);
this.changeInfo.vent.on("workflow-refreshed", this.render);
this.changeInfo.vent.on("jobLog-view", this.render);
this.changeInfo.vent.on("workflow-created", w.refreshWorkflows);
this.changeInfo.vent.on('save-source', this.fromJobRun, this);
},
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
fetchMostRecentChange: function(){
var self = this;
$.ajax({
url: "/source/" + self.model.id + "/most-recent-change",
dataType: "json",
success: function(mostRecentChange){
if( mostRecentChange ){
$.ajax({
url: "/document?change=" + mostRecentChange.id + "&rendering=screen-capture",
dataType: "json",
success: function(response){
self.mostRecentChange = mostRecentChange;
if( response.results.length > 0 ){
self.screenCapture = response.results[0];
}
self.render.call(self);
}
});
}
}
});
},
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
serializeData: function(){
var verificationDate = this.model.get('verificationDate');
// Converting timestamp into readable format
if(!verificationDate) {
verificationDate = '';
} else {
verificationDate = moment(verificationDate).format('MM/DD/YYYY');
}
return {
model: this.model,
tab: this.tab,
minimumChangeInterval: this.humanizeDate(this.model.get("minimumChangeIntervalMs")),
verificationDate: verificationDate
}
},
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
onRender: function(){
var tabRegion = localStorage.getItem("tabRegion"),
rememberTabs = localStorage.getItem("rememberTabs");
if( tabRegion && rememberTabs === "true"){
this.tab = tabRegion;
} else if( this.tab == null ) {
this.tab = "details";
}
localStorage.setItem("tabRegion", this.tab);
// content set group
var contentSetIds = [];
for( var contentSetId in w.CS ){
if( this.model.get("entityIds").indexOf(contentSetId) >= 0 ){
contentSetIds.push(contentSetId);
}
}
this.controls.contentSetGroup.values = contentSetIds;
this.controls.contentSetGroup.bind(this.$("#src-tab-details-group"));
// page types
var pageTypeIds = [];
for( var pageTypeId in w.PAGE_TYPES ){
if( this.model.get("entityIds").indexOf(pageTypeId) >= 0 ){
pageTypeIds.push(pageTypeId);
}
}
this.controls.pageTypes.values = pageTypeIds;
this.controls.pageTypes.bind(this.$("#src-tab-details-page"));
// prev types
var prevTypeIds=[];
for(var prevTypeId in w.PREV_TYPES){
if(this.model.get("entityIds").indexOf(prevTypeId)>=0){
prevTypeIds.push(prevTypeId);
}
}
this.controls.prevTypes.values = prevTypeIds;
this.controls.prevTypes.bind(this.$("#src-tab-details-previousType"));
// changes
var changePaginationView = new w.PaginationView({collection:this.changeInfo.changes});
changePaginationView.autoHide = true;
this["change results"].show(new w.src.ChangeCollectionView({collection:this.changeInfo.changes, changeInfo:this.changeInfo}));
this["change pagination"].show(changePaginationView);
// institution
var institutionIds = [];
_.each(this.model.get("entityIds"),function(entityId){
if( !w.INST_TYPES[entityId] && !w.PAGE_TYPES[entityId] && !w.CS[entityId] && !w.PREV_TYPES[entityId]){
institutionIds.push(entityId);
}
});
this.controls.institution.values = institutionIds;
this.controls.institution.bind(this.$("#src-tab-details-institution"));
// job
this["source job"].show(new w.src.SourceJobView({changeInfo:this.changeInfo}));
// documents
if( this.changeInfo.selectedChange ){
var documentLayoutView = new w.src.DocumentLayoutView({collection:this.changeInfo.documents, changeInfo:this.changeInfo});
this["document layout"].show(documentLayoutView);
var documentPaginationView = new w.PaginationView({collection:this.changeInfo.documents});
documentPaginationView.autoHide = true;
documentLayoutView["document results"].show(new w.src.DocumentCollectionView({collection:this.changeInfo.documents, changeInfo:this.changeInfo}));
documentLayoutView["document pagination"].show(documentPaginationView);
} else {
this["document layout"].close();
}
//view job logs
if(this.changeInfo.viewDetails) {
var self = this;
var jobId = this.changeInfo.selectedChange.get('jobId');
var selectedJobModel = new w.Job({id: jobId});
selectedJobModel.fetch({ success: function(model) {
self["job log"].show(new w.src.JobLogView({logger: model.get('logger')}));
}});
}
// workflow detail
this["workflow detail"].show(new w.src.WorkflowDetailView({changeInfo:this.changeInfo}));
// other setup
this.onUrlType();
this.setTab();
if(!this.model.isNew()) {
this.validate();
}
if(this.model.get("includedRegions").length) {
this.$(".delete-all-selected-region").removeClass("disabled");
}
// Adding datepicker
this.$("#verificationDate").datepicker({
todayHighlight: true,
autoclose: true
});
},
fromJobRun: function() {
var self = this;
this.onUseMyAccountClick();
this.populateDateToModel();
// save the model
this.model.save().success(function() {
self.onSuccess();
self.changeInfo.vent.trigger("job-selected");
}).error(function(response) {
self.onError(response)
});
},
});
sourceJobView.js
w.src.SourceJobView = Backbone.Marionette.Layout.extend({
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template: "#src-template-source-job-view",
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
initialize: function(){
this.options.changeInfo.vent.on("job-selected", this.runJob );
},
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
onRender : function(){
// decide whether to show the job details link
if( w.IS_ADMIN ){
this.$(".jobDetailsMessage").show();
} else {
this.$(".jobDetailsMessage").hide();
}
} ,
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
serializeData: function(){
return this.options.changeInfo;
},
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
runJob: function() {
console.log('here');
},
onRunJobClick: function() {
this.options.changeInfo.vent.trigger("save-source");
}
});
According to the code here
Onrunjobclick in sourceJobview triggered is fired to sourceTabview which is listened by fromrunJob which on success fires a trigger back to sourceJobview which is listened by runJob which is invoked multiple times
The most common cause of this issue is zombie views - they have been removed from the DOM, but their event handlers remain bound.
You should use listenTo instead of on to bind events. This allows Marionette's View.close method to clean up old event handlers when views are closed.
It's a simple fix:
initialize: function(){
this.listenTo(options.changeInfo.vent, "job-selected", this.runJob);
},
I'm new to BackboneJs. And I really don't know what hell I'm doing wrong, but the events from my subview doesn't fire. I've been stuck with this problem now a long time, and I've used the google and stackoverflow to find a solution to my problem but I'm still confused. Could someone help\guide me?
var ExerciseList = Backbone.Collection.extend();
var ExerciseView = Backbone.View.extend({
events : {
'click' : "clickFun"
},
clickFun : function(e) {
alert("yamaha");
},
render : function() {
var exerciseList = new ExerciseList();
exerciseList.url = '/api/exercise_bank/' + this.id + '/';
var that = this;
var element = this.$el;
exerciseList.fetch({
success : function() {
var template = _.template($('#exercise-bank-template-exercises').html(), {exercises : exerciseList.models});
$(element).html(template);
}
});
return this;
},
});
// Collection
var MuscleGroupList = Backbone.Collection.extend({
url : '/api/exercise_bank/'
});
// View
var MuscleGroupView = Backbone.View.extend({
el : '#exercise-bank-component',
initialize : function() {
this.exerciseList = new ExerciseList();
this.exerciseView = new ExerciseView();
},
render : function() {
var muscleGroupList = new MuscleGroupList();
that = this;
console.log('MuscleGroup.render');
muscleGroupList.fetch({
success : function(muscleGroupList) {
template = _.template($('#exercise-bank-template-musclegroups').html(), {
musclegroups : muscleGroupList.models
});
that.$el.html(template);
_.each(muscleGroupList.models, function(musclegroup) {
var element = "#eb-exercises-" + musclegroup.get('id');
that.exerciseList.id = musclegroup.get('id');
that.exerciseView.id = musclegroup.get('id');
that.exerciseView.setElement(element).render();
return that;
});
}
});
return this;
},
});
muscleGroupView = new MuscleGroupView();
exerciseView = new ExerciseView();
muscleGroupView.render();
Backbone.history.start();
Questions:
1) Is your view getting rendered on the Dom.
2) Is this element really present inside the dom var element = "#eb-exercises-" + musclegroup.get('id');
3) Why do need the setElement here
that.exerciseView.setElement(element).render();
Solved it!
I just moved:
initialize : function() {
this.exerciseList = new ExerciseList();
this.exerciseView = new ExerciseView();
},
down to:
_.each(muscleGroupList.models, function(musclegroup) {
var element = "#eb-exercises-" + musclegroup.get('id');
var exerciseList = new ExerciseList();
var exerciseView = new ExerciseView();
exerciseList.id = musclegroup.get('id');
exerciseView.setElement(element).render();
return that;
});
and now it works as I want it to do! :)
I have a backbone chat web app , i have a javascript array which holds names and other stuff, what i want is to look in this array if this.name() exists and if so read the element before the name wich is a image url and use that in option_h3 in the code below.
hope im clear enough.
thanks i.a.
var PeopleView = Backbone.View.extend({
className: 'peopleView',
initialize: function() {
this.people = Hula.user.get("people");
this.people.on('add', this.addPerson, this);
this.people.on('remove', this.render, this);
$(".nav_item").removeClass("nav_item_s");
$("#people_nav").addClass("nav_item_s");
},
render: function(){
this.$el.empty();
var header = $('<div id="people_header">');
var title = $('<div class="t34 title">');
title.html("Friends");
header.append(title);
this.$el.append(header);
var addOption = $('<div id="people_add_option">');
var addInput = '<div id="addp"><div id="people_add_input_h"><form id="add_person_input_form" ><input id="add_person_input" name="s" type="text" value="Enter Hularing ID..." ></input></form></div></div>';
addOption.html(addInput);
this.$el.append(addOption);
var list = $('<div id="people_list" >');
this.$el.append(list);
this.people.each(this.addPerson, this);
return this;
},
addPerson: function(person){
var view = new PeopleViewPerson({model: person});
this.$("#people_list").prepend(view.render().$el);
},
events: {
'keypress #add_person_input': 'addNewPerson',
},
addNewPerson: function(e){
var ID = $('#add_person_input').val();
if(ID !=="Enter Hularing ID..."){
if(e.which == 13) {
if(validate(ID)){
Hula.subscribe(ID);
this.$('#add_person_input').val("")
$("#add_person_input_form")[0].reset();
$('#add_person_input').blur().focus();
e.preventDefault();
}
}
}
}
});
var PeopleViewPerson = Backbone.View.extend({
className: 'friend_holder',
initialize: function() {
$(this.el).attr('id', jid_to_id(this.model.get("jid")));
this.model.on('all', this.render, this);
this.model.get('conversation').get('messages').on('add', this.onNewMessage, this);
},
render: function() {
var img = $('<div class="friend_img_h">');
if(this.pic() == null){
img.html('<img src="farax/img/default.png" />');
} else {
var img_src = 'data:'+this.picType()+';base64,'+this.pic();
img.html('<img src="'+img_src+'" />')
}
var info_h = $('<div class="friend_info_h">');
var person_name = $('<div class="friend_name">');
person_name.html(this.name());
var line2 = $('<div class="friend_line2">');
var status = this.status();
line2.html(status);
var option_h = $('<div class="friend_option_h">');
option_h.html('<div class="msg_person_icon" ></div>');
// CONTACT INFO DIV.
var option_h1 = $('<div class="friend_option_h1">');
// CONTACT INFO IMAGE IN CSS FILE.
option_h1.html('<div class="msg_person_icon1"></div>');
// CONTACT FACEBOOK TIJDLIJN.
var option_h2 = $('<div class="friend_option_h2">');
// CONTACT FACEBOOK TIJDLIJN IMAGE IN CSS FILE.
option_h2.html('<div class="msg_person_icon2"></div>');
var option_h3 = $('<div class="friend_option_h3">');
option_h3.html('<div class="msg_person_icon3"></div>');
for(var t = 0; t < javaScript_array.length; t++) {
// this one stays the same
var naam = this.name();
var res = javaScript_array[t];
// ignore this it is done to get the name from the database the same as in the collection
var naam1 = naam.replace(" ","0");
// see if it exists
if(naam1 === res){
option_h3.append('<div class="msg_person_icon3"><img src="'+ javaScript_array[t-1] +'" width="35" height="35"/></div>');
} else {
option_h3.html('<div class="msg_person_icon3"></div>');
}
}
if(this.ask()== "subscribe"){
line2.prepend('<span class="pending_out">Request pending.</span>');
}
if(this.pending()){
line2.prepend('<span class="pending_in">Pending authorisation!</span>');
}
info_h.append(person_name).append(line2);
this.$el.html(img);
this.$el.append(info_h);
this.$el.append(option_h);
this.$el.append(option_h1);
this.$el.append(option_h2);
this.$el.append(option_h3);
return this;
},
jid: function() { return this.model.get('jid');},
name: function() { return this.model.get('name'); },
status: function() { return this.model.get('status'); },
pic: function() { return this.model.get('picture').pic; },
picType: function() { return this.model.get('picture').picType; },
ask: function() { return this.model.get('ask'); },
subscription: function() { return this.model.get('subscription'); },
pending: function() { return this.model.get('pending'); },
online: function() { return this.model.get('online'); },
events: {
'click .friend_img_h': 'loadPerson',
'click .friend_info_h': 'loadPerson',
'click .msg_person_icon': 'messagePerson'
},
loadPerson: function(){
Hula.screen.person.render(this.model);
},
messagePerson: function(){
Hula.screen.conversation.render(this.model);
},
onAll: function(person){
},
onNewMessage: function(message){
$('#people_list #'+jid_to_id(this.jid())+' .friend_line2').html(message.get("message"));
},
OnStatusChange: function(change){
$("#people_list #"+id_to_jid(this.ji())).html(this.status().toString());
}
});
it only works on the last element in the array while there are three elements.
I'm looking at your code and to be completely honest, it makes absolutely no sense to me.
I can see that you have option1 option2 and option3 which I assume are the 3 elements you are referring to only, in your array at the bottom, you only ever seem to change option 3.
I have a plugin with the following structure:
(function($){
function pluginName(el, options) {
var _this = this;
_this.defaults = {
someOptions: '',
onSlideStart: function() {},
onSlideEnd: function() {},
};
_this.opts = $.extend({}, _this.defaults, options);
$(el).on("slideStart", function() {
_this.opts.onSlideStart.call();
});
$(el).on("slideEnd", function() {
_this.opts.onSlideEnd.call();
});
}
pluginName.prototype = {
someFunctions: function() {
}
};
$.fn.pluginName = function(options) {
if(this.length) {
this.each(function() {
var rev = new pluginName(this, options);
rev.init();
$(this).data('pluginName', rev);
});
}
};
})(jQuery);
If I call it the following way, everything is okay:
$('.element').pluginName({
someOptions: 'full',
onSlideStart: function() {
console.log('slideStart!');
},
onSlideEnd: function() {
console.log('slideEnd!');
},
});
But I want to dynamic load the custom event handler like this:
(function($){
function pluginName(el, options) {
var _this = this;
_this.defaults = {
someOptions: '',
onSlideStart: function() {},
onSlideEnd: function() {},
};
_this.opts = $.extend({}, _this.defaults, options);
for (var optionName in _this.opts) {
var
optionValue = _this.opts[optionName],
optionType = typeof(optionValue)
;
if(optionType == 'function') {
optionNames = optionName.split('on');
eventName = global.lowerFirstLetter(optionNames[1]);
$(el).on(eventName, function() {
eval('_this.opts.' + optionName + '.call();');
});
}
}
}
...
})(jQuery);
But this does not work. When I call the plugin with the "dynamic" part, it always call the slideEnd-function. So am I doing it wrong or is it just impossible with my plugin-pattern to call the custom event-handler dynamically?
Why use eval ? It's usually bad to use eval.
if(optionType == 'function') {
optionNames = optionName.split('on');
eventName = global.lowerFirstLetter(optionNames[1]);
$(el).on(eventName, _this.opts[optionName]);
}
Try it and let me know.