I trigger an event "modal:show", where I pass the id of a modal object. But when I handle the event the Event.data are always undefined.
How should I access these values?
<img src="/GetPicture?pic=110&thumb=1" class="r img show-modal" data-modal="modalZoom" data-id="110" data-index="1" />
$(".show-modal").click(function (event) {
var idModal = $(this).data("modal");
event.preventDefault();
$("#" + idModal).trigger("modal:show", [{ id: idModal }]);
});
$(".modal").on("modal:show", function (event) {
var $modal = $("#" + event.data.id);
$modalBlack.fadeIn("slow", function () {
$modal.fadeIn("fast", function () {
$modal.trigger("modal:visible", [{ id: event.data.id }]);
});
});
});
The extra data you're trying to pass along with the modal:show event will not be attached to the event object itself; instead it would arrive as a second parameter to the event handler:
$(".show-modal").click(function(event) {
var idModal = $(this).data("modal");
event.preventDefault();
$("#" + idModal).trigger("modal:show", [{
id: idModal
}]);
});
$(".modal").on("modal:show", function(event, foo) {
console.log(foo.id) // <-- not event.data.id or event.id; the data you want isn't attached to the event object at all
// ...
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="show-modal" data-modal="modalZoom" data-id="110" data-index="1" />
<div class="modal" id="modalZoom">test</div>
In this particular case, though, since the ID you're looking for is on the same element on which the event was triggered, it would be much simpler to not pass the data between handlers, but instead just read it from the DOM:
$(".show-modal").click(function(event) {
var idModal = $(this).data("modal");
event.preventDefault();
$("#" + idModal).trigger("modal:show");
});
$(".modal").on("modal:show", function(event) {
console.log($(this).attr("id"))
// ...
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="show-modal" data-modal="modalZoom" data-id="110" data-index="1" />
<div class="modal" id="modalZoom">test</div>
I replaced this:
var $modal = $("#" + event.data.id);
with this:
var $modal = $("#" + event.id);
Related
This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 1 year ago.
I'm receiving an ajax response, and based on this adding some html content to the dom.
Problem: I want to also add a link that should have a onclick function with passing a parameter from the response.
Example:
http://jsfiddle.net/zu1ymrh8/55/
<a class="LoadFromAjax" href="#">Load Ajax</a>
<div class="appendedContainer"></div>
$(function() {
function myfunc(input) {
alert("test: " + input);
}
$(".LoadFromAjax").on("click", function() {
event.preventDefault();
$.ajax({
url: 'https://dog.ceo/api/breeds/list/all',
type : 'get',
complete : function( qXHR, textStatus ) {
var mock = "John"; //some values extracted from rsp
$('.appendedContainer').hide();
$('.appendedContainer').append(`<a href='#' onclick='myfunc(${mock})' class='mylink'>Alert me</a>`);
$('.appendedContainer').fadeIn();
}
});
});
});
Result: ReferenceError: myfunct is not defined. Why?
I suggest setting the click listener on the container element.
See example below
document.querySelector('button').addEventListener('click', load);
const container = document.querySelector('.container');
// delegating the click handler to the container
container.addEventListener('click', handleItemClick);
function load() {
Promise
.resolve(Date.now())
.then(entry => {
const child = document.createElement('a');
child.innerText = entry;
container.append(child);
})
}
function handleItemClick(ev) {
console.log(ev.target.innerText)
}
a {
display: block;
}
<button>Load</button>
<div class="container"></div>
How about something like:
$.ajax({
...,
complete : function( qXHR, textStatus ) {
var mock = "John"; //some values extracted from rsp
// create a link:
var link = $('<a>', {
href : "the-url",
class : "the-class",
});
// append to container:
$('.appendedContainer').append(link);
// set on click function:
link.click(function() {
// do something with mock:
console.log(mock);
});
...
}
});
Basically I want to trigger the "modal:show" event from when .show-modal is clicked, but I get no respons when I trigger the event. I've tried many different implementations, but can't get it right.
$(".modal").on("modal:show", function (event) {
onShowModal(event.id);
});
function onShowModal(modalId) {
let $modal = $("#" + modalId);
$modalBlack.fadeIn("slow", function () {
$modal.fadeIn("fast", function () {
$modal.trigger("modal:showing", { id: modalId });
});
});
}
$(".show-modal").click(function (event) {
let modalId = $(this).data("modal-id");
event.preventDefault();
$(".modal").trigger("modal:show", { id: modalId });
});
To get your code working I had to make a few modifications. Try this:
<div class="modal">Generate my own HTML</div>
<div class="show-modal" data-modal-id="randomId">Make a button</div>
<div class="randomId" >Toggle, toggle.</div>
<script>
$(".modal").on("modal:show", function (event, idObj) {
// The trick here is that the first parameter is the event.
// The second parameter is the object that you send in on the
// triggering call. ($(".modal").trigger...)
onShowModal(idObj);
});
function onShowModal(idObj) {
let $modal = $("#" + idObj.id);
// Don't forget to go into the object and get the Id.
// I don't have modalBlack so my code broke at this point.
$modalBlack.fadeIn("slow", function () {
$modal.fadeIn("fast", function () {
$modal.trigger("modal:showing", { id: modalId });
// modalId is probably going to be idObj.id.
});
});
}
$(".show-modal").click(function (event) {
let modalId = $(this).data("modal-id");
event.preventDefault();
$(".modal").trigger("modal:show", { id: modalId });
// Notice that you are sending this as an object {id:modalId}.
});
</script>
So basically I have two functions on my click() trigger.
var firstFunction = function() {
var id = $(this).attr('id');
alert(id);
};
var secondFunction = function() {
//something here
};
$('#trigger').click(function() {
firstFunction();
secondFunction();
});
On firstFunction() I'm trying to get $(this).attr('id') but it's returning undefined.
I know it has something two do with calling multiple functions because it works when I only call one function
$('#trigger').click(firstFunction);
Sample Fiddle here
As per your existing approach this refers to Window object not the element which invoke the event.
You can use .bind()
The bind() method creates a new function that, when called, has its this keyword set to the provided value,
$('#trigger').click(function() {
firstFunction.bind(this)();
secondFunction.bind(this)();
})
var firstFunction = function() {
var id = $(this).attr('id');
console.log(id);
};
var secondFunction = function() {
//something here
var id = $(this).attr('id');
console.log(id);
};
$('#trigger').click(function() {
firstFunction.bind(this)();
secondFunction.bind(this)();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="trigger">Click Me</button>
Fiddle
It's returning undefined because you aren't applying the same this as the event. You can achieve this by using call or apply instead of calling it directly.
$('#trigger').click(function() {
firstFunction.call(this);
secondFunction.call(this);
});
The this inside the firstFunction will be the window object itself - pass this to the function to fix it - see demo below:
var firstFunction = function(el) {
var id = $(el).attr('id');
alert(id);
};
var secondFunction = function() {
//something here
};
$('#trigger').click(function() {
firstFunction(this);
secondFunction(this);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="trigger">Click Me</button>
Another way is to use Function.prototype.call to bind a this argument to the funciton:
var firstFunction = function() {
var id = $(this).attr('id');
alert(id);
};
var secondFunction = function() {
//something here
};
$('#trigger').click(function() {
firstFunction.call(this);
secondFunction.call(this);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="trigger">Click Me</button>
You can pass the jQuery object element and than only use it in your function:
var firstFunction = function($el) {
var id = $el.attr('id');
console.log(id);
};
var secondFunction = function() {
//something here
};
$('#trigger').click(function() {
firstFunction($(this));
secondFunction();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="trigger">Button</button>
click() handler receives event as parameter. Pass it because this is not available in the scope of firstFunction().
Like this:
var firstFunction = function(target) {
var id = $(target).attr('id');
alert(id);
};
var secondFunction = function() {
//something here
};
$('#trigger').click(function(e) {
firstFunction(e.target);
secondFunction();
});
Nothing to do major, it's quite simple.
If you are calling a function and into that function you need an event to be used, then pass a reference in the function parameter.
I have updated the code in your Fiddle and updated with Mine:
Step 1:
$('#trigger').click(function(event) {
var that = this;
firstFunction(that);
secondFunction(that);
});
Created a variable that assigned this to that and passed into function parameter.
Note that, writing event in the click function is required to define this as a local click reference (Not a window)
Step 2:
Passed that rather than this, to make sure the reference is from click function only not of window.
var firstFunction = function(that) {
var id = $(that).attr('id');
alert(id);
};
Updated Fiddle
When you click on each button, it just calls a modal so you can edit or delete an event. I am having trouble passing in the event from the view.
This is in the controller:
$scope.eventRender = function (event, element, view) {
element.append(calendarEventService.formatWeekEvent(event));
$compile(element)($scope);
};
$scope.uiConfig = {
calendar:{
...,
eventRender: $scope.eventRender
}
};
This is the service the eventRender is calling:
app.service('calendarEventService', function () {
this.formatWeekEvent = function (event) {
return <a whole bunch of html to render the button> +
'<a ng-click="editActivityModal(event, $event)">Edit</a>' +
'<a ng-click="deleteActivityModal(event, $event)">Delete</a>'
};
});
The event itself gets passed into the service, but when the editActivityModal or deleteActivityModal gets called, the event is not being passed and I only get undefined, however, the $event is being passed (this is just to use the preventDefault and stopPropagation stuff)
Found a solution to this as follows:
In the returning html add a css class to bind a click event in the eventRender function:
app.service('calendarEventService', function () {
this.formatWeekEvent = function (event) {
return <a whole bunch of html to render the button> +
'<a class="editEvent">Edit</a>' +
'<a class="deleteEvent">Delete</a>';
};
});
In the eventRender function:
$scope.eventRender = function (event, element, view) {
element.append(calendarEventService.formatWeekEvent(event));
element.find(".editEvent").bind('click', function () {
$scope.editEvent(event);
return false;
});
element.find(".deleteEvent").bind('click', function () {
$scope.deleteEvent(event);
return false;
});
$compile(element)($scope);
};
I'm new to Backbone. I have a collection whose url function depends on the textfield text. How do i get that text from my textfield. No i don't want to use JQuery selectors as accessing outside selectors from your views aint a good practice. My HTML stucture is like:
<div id='outer'>
<input type='text' id='xyz'>
<div id='image123'></div>
<div id='div1'>
<ul>
</ul>
</div>
<div id='div2'></div>
</div>
So i got 2 views, 1 collections & 1 model.
How do i get the input text in the collection without using JQuery selectors from my 'outer' view.
[Post updated with View code]
var outerView = Backbone.View.extend
({
el: '#outer',
initialize: function()
{
},
events:
{
'keyup #xyz' : 'keyfunc'
},
keyfunc: function()
{
// inputtext is a global variable & i don't want it that way
inputtext = $('#xyz').val();
},
render: function()
{
},
});
I couldn't figure what are you doing , but only if you want to send the value to the collection with out making it global and changing the url ,try doing it this way
var outerView = Backbone.View.extend
({
el: '#outer',
initialize: function()
{
},
events:
{
'keyup #xyz' : 'keyfunc'
},
keyfunc: function()
{
// not global now
var inputtext = $('#xyz').val();
var myclooction = new MainCollection({
text : inputtext
});
},
render: function()
{
},
});
in the collection
var MainCollection = Backbone.extend.collection({
url : function(){
return "someurl/"+this.text;
},
// receive the value here
initialize:function(options){
this.text = options.text;
}
});
Backbone passes information about the element that triggered the event, and there you can find that value like so:
keyfunc: function(e)
{
inputtext = $(e.currentTarget).val();
this.model.trigger('textChanged', {id: this.myID, data: inputtext});
}
and your model can listen that event like this in its initialize-function.
this.listenTo(this, 'textChanged', this.textChangedHandler);
And the model can then decide what to do with that event. For example to send it to that another view by another event.
textChangeHandler: function (e) {
this.trigger('someTextChanged', e);
}
And your views or collections can listen that event in their initialize-function:
this.listenTo(this.model, 'someTextChanged', this.textChangedHandler);
And the handler would be something like:
textChangeHandler: function (e) {
if (e.id !== this.myID) {
//do stuff
}
}