Plugin opens only after two clicks - javascript

I have a custom made tooltip plugin which should be opened by another plugin. But the plugin opens only after the second click and I can't figure out what the problem is.
The whole thing can be tested under. You have to click on the second input Field.
https://codepen.io/magic77/pen/XWMeqrM
$.fn.packstationFinder = function (options) {
var settings = $.extend({
event: 'click.packstationFinder'
}, options);
this.bind(settings.event, function (e) {
if ($postalCode.val() === '') {
$('#packstation-number').tooltip();
return;
}
});
return this;
};
$('[rel~=packstationFinder]').packstationFinder();

I've checked the code in Codepen. The problem here is because in packstationFinder() you call the tooltip() function for the element. But as you can see inside the tooltip() you just bind the click event on the element and not trigger it. So by current code with a first click on the element (#packstation-number) you just bind the click event and really trigger the tooltip only by the second click. You can see that it work as it should by moving out the calling of tooltip() function from packstationFinder() and call it directly as in the code below:
$.fn.packstationFinder = function (options) {
var settings = $.extend({
event: 'click.packstationFinder'
}, options);
return this;
};
$('[rel~=packstationFinder]').packstationFinder();
$('#packstation-number').tooltip();

Related

Angular $scope variable not being shown on Bootstrap modal init

I am using FullCalendar with angular and it has worked well so far. However when I click on an event, I present a modal with information about an event.
eventClick : function(event) {
$scope.clickedEvent = $filter('filter')($scope.events, {eventID: event.id})[0];
console.log($scope.clickedEvent);
GetEvent($scope, $scope.clickedEvent, $filter);
// opening the event modal
$("#eventModal").modal("show");
},
And this works for the most part but for display my event I have lines like
<td class="col-md-6"><label class="horizontal-table-title">{{clickedEvent.eventStatusID}}</label></td>
And these are not filled. In my initial call I am doing a console.log() and this shows my clickedEvent $scope variable and shows that it is filled with the event information.
My GetEvent() function looks like
function GetEvent($scope, event, $filter) {
// Init date and time pickers
InitPickers($scope);
$scope.submitInfo = angular.copy(event)
// Converting the event date to a moment.js object for better display
// Also need to seperate the date and time as it comes in as one string but edited as two
var eventDate = moment($scope.clickedEvent.eventStartDateAndTime).format('MMMM Do YYYY');
var eventTime = moment($scope.clickedEvent.eventStartDateAndTime).format('hh:mm a');
// Modal event info body
$("#claim-id").text($scope.clickedEvent.attachedClaim.claimId);
$("#event-date").text(eventDate);
$("#event-time").text(eventTime);
// Modal event edit body
$("#datepicker").attr("value", eventDate);
$("#timepicker").attr("value", eventTime);
$("#event-edit-status").val($scope.clickedEvent.eventStatusID);
$("#event-edit-description").val($scope.clickedEvent.eventDescription);
$("#event-edit-resource").text($scope.clickedEvent.eventResourceName);
$("#event-edit-resource-address").text($scope.clickedEvent.eventResourceAddress);
}
I also have an function called EventRefresh with is bound to a checkbox that changes the view of the modal from displaying events to being able to edit events.
<label>Change View Type:
<input type="checkbox" ng-model="checkboxModel" ng-click="eventRefresh()">
</label>
Which calls GetEvents()
scope.eventRefresh = function() {
GetEvent($scope, $scope.clickedEvent, $filter)
}
And once this is checked all the information in {{clickedEvent}} is displayed. Only on the initial opening of the modal that nothing shows.
As charlieftl pointed out in his comment above I needed to use
$scope.$apply()
So I wrapped my GetEvent() function with it. My code went from
eventClick : function(event) {
$scope.clickedEvent = $filter('filter')($scope.events, {eventID: event.id})[0];
console.log($scope.clickedEvent);
GetEvent($scope, $scope.clickedEvent, $filter);
// opening the event modal
$("#eventModal").modal("show");
},
To:
eventClick : function(event) {
$scope.clickedEvent = $filter('filter')($scope.events, {eventID: event.id})[0];
console.log($scope.clickedEvent);
$scope.$apply(function() {
GetEvent($scope, $scope.clickedEvent, $filter);
// opening the event modal
$("#eventModal").modal("show");
});
},
Thanks charlieftl!

Prevent duplcate ajaxLoad event calls added with a click event

I am using MVC Razor - The overall goal is to create a "print view" pop-up page.
The print view button is on the parent page, when clicked, an ajax event is fired which will populate an empty div with the contents that are to be included in the print preview:
//from the view
#Ajax.ActionLink("prntPreview", "Display", new { ID = Model.Detail.ID }, new AjaxOptions { UpdateTargetId = "modal" }, new { #class = "btnPreview" })
then, using JavasScript/jQuery I clone the contents of that newly populated div and create a new window with the contents:
//in the scripts file
$('.btnPreview').on('click', function () {
$(document).ajaxStop(function () {
var pageData = $('#modal').html();
setTimeout( //add a slight delay
function () {
PopupPrint(pageData);
}, 300);
});
});
function PopupPrint(data) {
var mywindow = window.open('', '', 'height=500,width=800,resizable,scrollbars');
mywindow.document.write(data);
mywindow.focus();
//do some other stuff here
}
This is where I run into difficulty. The first time I click, everything is working as expected - however, if you do not navigate away from the parent page and try to use the print preview button a second time, the popup will be created twice, then three times etc. with each additional click.
I think that the problem is because each time the .btnPreview is clicked, a new $(document).ajaxStop event is being created, causing the event to fire multiple times.
I have tried to create the ajaxStop as a named function which is declared outside the scope of the click event and then clear it but this produces the same result:
var evnt = "";
$('.btnPreview').on('click', function () {
evnt =
$(document).ajaxStop(function () {
var pageData = $('#modal').html();
setTimeout( //add a slight delay
function () {
PopupPrint(pageData);
evnt = "";
}, 300);
});
});
I also have other ajaxStop events initialised so don't want to completely unbind the ajaxStop event. Is it possible to get the name or something from each ajax event so that I can clear just that event or similar?
You can prevent adding additional triggers by checking with a variable outside of scope like this:
(function() {
var alreadyAdded = false;
$('.btnPreview').on('click', function() {
if (!alreadyAdded) {
$('.eventTrigger').click(function() {
console.log('printing!');
});
alreadyAdded = true;
}
});
})();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="btnPreview">Add Event</button>
<button class="eventTrigger">Trigger</button>
Please note that the variable and function are encapsulated in a self-executing anonymous function and do not pollute global space.
The output of the sample can be seen in the developer console. If you remove the if-check then every click on the "Add Event" button produces an additional print statement on the "Trigger" button each time it is clicked (which is your problem). With the if, there will ever only be one event on the trigger button.
There were 2 issues which I needed to address.
The answer is to unbind the ajax event after it has checked that the request had completed and to unbind and reattach the button click trigger.
This is how I did it:
//in the scripts file
$('.btnPreview').off('click').on('click', function () {
$(document).ajaxComplete(function (e) {
var pageData = $('#modal').html();
setTimeout( //add a slight delay
function () {
PopupPrint(pageData);
}, 300);
$(this).off(e);
});
});
I unbound the click event by adding .off('click') before the .on. this is what stopped it popping up multiple times.
The other issue was that anytime any ajax event completed (triggered by something else) that would also create the popup - to get around that, I added $(this).unbind(e); to the end of the code block which removed the ajaxComplete binding which was being triggered each time any ajax event completed.

How to trigger ready event on JQuery chosen plugin?

I am trying to bind an liszt:ready event of my list, to be invoked once that the list has been initialized by chosen.
I follow the steps that here are describing without any success.
This is my code:
var initPreferredCollaboratorChosen = function () {
$("#preferredCollaboratorChosenId").chosen({width: "95%"}).trigger("chosen:ready");
};
var initListener = function () {
$("preferredCollaboratorChosenId").on("chosen:ready", function(){
alert("Hey, I am ready!");
});
initPreferredCollaboratorChosen()
};
I try with "liszt:ready" instead "chosen:ready" as well.
Can anyone that has work with this plugin tell me how make it?.
Regards.

JQuery.one() event that fires immediately

I'm making a jquery plugin in which you can set the event for something to happen.
$.fn.makeSomething = function(options) {
var defaults = {
activationEvent: "mouseover"
};
options = $.extend(defaults, options);
this.each(function() {
var elem = $(this);
elem.one(options.activationEvent, function(){
// some code to be called at the event (in which I use elem)
// but by default should be called immediately on load
});
});
return this;
}
I would like the default to be that it just happens without any needed interaction. Is this possible?
A little more info:
I have several divs in which some extra content should be loaded. By default I want the content to be loaded when the page loads. However, on some pages I don't want all the content to be loaded with the page, but I want each piece to be loaded only when you hover your mouse over its div.
Thanks!
If you separate the function definition from the binding:
$.fn.makeSomething = function(options) {
// ...
function doSomething() {
// ...
}
$(this).one(options.activationEvent, doSomething);
};
You can test the activationEvent for a default value that isn't an event, such as null, providing the that same function to .each():
$.fn.makeSomething = function(options) {
var defaults = {
activationEvent: null
};
options = $.extend(defaults, options);
function doSomething() {
var $elem = $(this);
// ...
}
if (!options.activationEvent)
this.each(doSomething);
else
this.one(options.activationEvent, doSomething);
};
// act immediately
$('...').makeSomething();
// act on mouseover
$('...').makeSomething({ activationEvent: 'mouseover' });
Both .one() and .each() will invoke doSomething() with this referring to the DOM Element. (Note: the arguments provided to doSomething() will, however, be different.)

Redefining a jQuery dialog button

In our application we use a general function to create jQuery dialogs which contain module-specific content. The custom dialog consists of 3 buttons (Cancel, Save, Apply). Apply does the same as Save but also closes the dialog.
Many modules are still using a custom post instead of an ajax-post. For this reason I'm looking to overwrite/redefine the buttons which are on a specific dialog.
So far I've got the buttons, but I'm unable to do something with them. Is it possible to get the buttons from a dialog (yes, I know) but apply a different function to them?
My code so far:
function OverrideDialogButtonCallbacks(sDialogInstance) {
oButtons = $( '#dialog' ).dialog( 'option', 'buttons' );
console.log(oButtons); // logs the buttons correctly
if(sDialogInstance == 'TestInstance') {
oButtons.Save = function() {
alert('A new callback has been assigned.');
// code for ajax-post will come here.
}
}
}
$('#dialog').dialog({
'buttons' : {
'Save' : {
id:"btn-save", // provide the id, if you want to apply a callback based on id selector
click: function() {
//
},
},
}
});
Did you try this? to override button's callback based on the need.
No need to re-assign at all. Try this.
function OverrideDialogButtonCallbacks(dialogSelector) {
var button = $(dialogSelector + " ~ .ui-dialog-buttonpane")
.find("button:contains('Save')");
button.unbind("click").on("click", function() {
alert("save overriden!");
});
}
Call it like OverrideDialogButtonCallbacks("#dialog");
Working fiddle: http://jsfiddle.net/codovations/yzfVT/
You can get the buttons using $(..).dialog('option', 'buttons'). This returns an array of objects that you can then rewire by searching through them and adjusting the click event:
// Rewire the callback for the first button
var buttons = $('#dialog').dialog('option', 'buttons');
buttons[0].click = function() { alert('Click rewired!'); };
See this fiddle for an example: http://jsfiddle.net/z4TTH/2/
If necessary, you can check the text of the button using button[i].text.
UPDATE:
The buttons option can be one of two forms, one is an array as described above, the other is an object where each property is the name of the button. To rewire the click event in this instance it's necessary to update the buttons option in the dialog:
// Rewire the callback for the OK button
var buttons = $('#dialog').dialog('option', 'buttons');
buttons.Ok = function() { alert('Click rewired!'); };
$('#dialog').dialog('option', 'buttons', buttons);
See this fiddle: http://jsfiddle.net/z4TTH/3/
Can you try binding your new function code with Click event of Save?
if(sDialogInstance == 'TestInstance') {
$('#'+savebtn_id).click(function() {
alert('A new callback has been assigned.');
// code for ajax-post will come here.
});
}

Categories