I know that in jquerymobile application, if we use pagebeforeshow page event, all the events inside that execute multiple times. I find the solution i.e: to unbind the event when hiding the page and bind the event when show the page. But what about the code, which is not inside any function or which has to execute every time the page is visited without any event (like click, tap, bind, focus etc.).
Code:
$(document).on( 'pagebeforeshow', '#profile', function(event){
//call to fetch user data
//first part
var invocationData6 = {
adapter : 'registerUser',
procedure : 'fetchUserProfileData',
parameters : [profileId]
};
WL.Client.invokeProcedure(invocationData6, {
onSuccess : fetchSuccess,
onFailure : fetchFailure,
});
function fetchSuccess(result){
$.mobile.utils.hideWaitBox();
var invocationResult = result.invocationResult;
var array1 = invocationResult.array;
}
function fetchFailure(result){
$.mobile.utils.hideWaitBox();
WL.Logger.error('Fetch Unsuccessful');
}
//second part
$(document).undelegate('#updBtn1', 'click').delegate('#updBtn1', 'click', function() {
var newAge = $("#updAge").val();
var newPhone = $("#updPhone").val();
var newSmoker = $("#flip-9").val();
$.mobile.utils.showWaitBox("e", "Wait! Updating your Info...");
var invocationData7 = {
adapter : 'registerUser',
procedure : 'updateRegisterData',
parameters : [profileId, newAge, newPhone, newSmoker]
};
WL.Client.invokeProcedure(invocationData7, {
onSuccess : update1Success,
onFailure : update1Failure,
});
function update1Success(result){
$.mobile.utils.hideWaitBox();
}
function update1Failure(result){
$.mobile.utils.hideWaitBox();
}
});
});
As you can see in the code that the first part is not enclosed inside anything so that it cannot be bind or unbind to prevent it from executing multiple times in pagebeforeshow page event. But the second part can easily be prevented from this problem by using delegate and undelegate events.
So, how to prevent the first part from executing multiple times. I cannot enclose it as it has to be executed when the page is changed using $.mobile.changePage.
Related
In 1.4.2, I have this:
$(document).on('pagecontainershow', PageShown);
function PageShown(myEvent, myUI ) {
log(this)
log(myEvent)
log(myUI)
};
I can't determine which page was just shown.
If I add more specificity to the selector, the event doesn't fire.
Update
As of jQuery Mobile 1.4.2 you can access previous .prevPage and next page .toPage.
$(document).on("pagecontainerhide", function (e, ui) {
var activePage = ui.toPage,
previousPage = ui.prevPage;
});
Both are jQuery objects so $() isn't needed.
To determine which page is currently active, you have two options:
Listen to pagecontainerhide and check ui.nextPage object emitted by that event
$(document).on("pagecontainerhide", function (e, ui) {
var activePage = $(ui.nextPage);
});
On pagecontainershow, use the below function which will return active page.
var activePage = $.mobile.pageContainer.pagecontainer("getActivePage");
Read more about page events.
Are there any events fired by an element to check whether a css3 transition has started or end?
W3C CSS Transitions Draft
The completion of a CSS Transition generates a corresponding DOM Event. An event is fired for each property that undergoes a transition. This allows a content developer to perform actions that synchronize with the completion of a transition.
Webkit
To determine when a transition completes, set a JavaScript event listener function for the DOM event that is sent at the end of a transition. The event is an instance of WebKitTransitionEvent, and its type is webkitTransitionEnd.
box.addEventListener( 'webkitTransitionEnd',
function( event ) { alert( "Finished transition!" ); }, false );
Mozilla
There is a single event that is fired when transitions complete. In Firefox, the event is transitionend, in Opera, oTransitionEnd, and in WebKit it is webkitTransitionEnd.
Opera
There is one type of transition event
available. The oTransitionEnd event
occurs at the completion of the
transition.
Internet Explorer
The transitionend event occurs at the completion of the transition. If the transition is removed before completion, the event will not fire.
Stack Overflow: How do I normalize CSS3 Transition functions across browsers?
Update
All modern browsers now support the unprefixed event:
element.addEventListener('transitionend', callback, false);
https://caniuse.com/#feat=css-transitions
I was using the approach given by Pete, however I have now started using the following
$(".myClass").one('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd',
function() {
//do something
});
Alternatively if you use bootstrap then you can simply do
$(".myClass").one($.support.transition.end,
function() {
//do something
});
This is becuase they include the following in bootstrap.js
+function ($) {
'use strict';
// CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
// ============================================================
function transitionEnd() {
var el = document.createElement('bootstrap')
var transEndEventNames = {
'WebkitTransition' : 'webkitTransitionEnd',
'MozTransition' : 'transitionend',
'OTransition' : 'oTransitionEnd otransitionend',
'transition' : 'transitionend'
}
for (var name in transEndEventNames) {
if (el.style[name] !== undefined) {
return { end: transEndEventNames[name] }
}
}
return false // explicit for ie8 ( ._.)
}
$(function () {
$.support.transition = transitionEnd()
})
}(jQuery);
Note they also include an emulateTransitionEnd function which may be needed to ensure a callback always occurs.
// http://blog.alexmaccaw.com/css-transitions
$.fn.emulateTransitionEnd = function (duration) {
var called = false, $el = this
$(this).one($.support.transition.end, function () { called = true })
var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
setTimeout(callback, duration)
return this
}
Be aware that sometimes this event doesn’t fire, usually in the case
when properties don’t change or a paint isn’t triggered. To ensure we
always get a callback, let’s set a timeout that’ll trigger the event
manually.
http://blog.alexmaccaw.com/css-transitions
All modern browsers now support the unprefixed event:
element.addEventListener('transitionend', callback, false);
Works in the latest versions of Chrome, Firefox and Safari. Even IE10+.
In Opera 12 when you bind using the plain JavaScript, 'oTransitionEnd' will work:
document.addEventListener("oTransitionEnd", function(){
alert("Transition Ended");
});
however if you bind through jQuery, you need to use 'otransitionend'
$(document).bind("otransitionend", function(){
alert("Transition Ended");
});
In case you are using Modernizr or bootstrap-transition.js you can simply do a change:
var transEndEventNames = {
'WebkitTransition' : 'webkitTransitionEnd',
'MozTransition' : 'transitionend',
'OTransition' : 'oTransitionEnd otransitionend',
'msTransition' : 'MSTransitionEnd',
'transition' : 'transitionend'
},
transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
You can find some info here as well http://www.ianlunn.co.uk/blog/articles/opera-12-otransitionend-bugs-and-workarounds/
Just for fun, don't do this!
$.fn.transitiondone = function () {
return this.each(function () {
var $this = $(this);
setTimeout(function () {
$this.trigger('transitiondone');
}, (parseFloat($this.css('transitionDelay')) + parseFloat($this.css('transitionDuration'))) * 1000);
});
};
$('div').on('mousedown', function (e) {
$(this).addClass('bounce').transitiondone();
});
$('div').on('transitiondone', function () {
$(this).removeClass('bounce');
});
If you simply want to detect only a single transition end, without using any JS framework here's a little convenient utility function:
function once = function(object,event,callback){
var handle={};
var eventNames=event.split(" ");
var cbWrapper=function(){
eventNames.forEach(function(e){
object.removeEventListener(e,cbWrapper, false );
});
callback.apply(this,arguments);
};
eventNames.forEach(function(e){
object.addEventListener(e,cbWrapper,false);
});
handle.cancel=function(){
eventNames.forEach(function(e){
object.removeEventListener(e,cbWrapper, false );
});
};
return handle;
};
Usage:
var handler = once(document.querySelector('#myElement'), 'transitionend', function(){
//do something
});
then if you wish to cancel at some point you can still do it with
handler.cancel();
It's good for other event usages as well :)
Hi guys i have posted a similar post before, but that is for another, now i face a strange and odd issue with my Jquery code. Here i was calling a controller method using Jquery but it is calling twice , so that may cause two entries in my db. Here is what i have written in my JQuery
<script type="text/javascript">
$('#btnSubmit').click(function () {
var instructorUrl = '#Url.Action("ApplyToBecomeInstructor", "InstructorApplication")';
var currentUser = '#Model.CurrentUserId';
var user = [];
var educationList = [];
var experience = $('#Experience').val();
var isWilling = $('#WillingToTravel').is(":checked");
$('#editorRows .editorRow').each(function () {
var education = {
UniversityOrCollege: $(this).find('.university').val(),
AreaOfStudy: $(this).find('.area').val(),
Degree: $(this).find('.degree').val(),
YearReceived: $(this).find('.year').val()
}
educationList.push(education);
});
var applicationFromView = {
EducationalBackgrounds: educationList,
CurrentUserId: currentUser,
Experience: experience,
WillingToTravel: isWilling
}
$.ajax({
type: 'POST',
url: instructorUrl,
dataType: 'JSON',
async: false,
data: JSON.stringify(applicationFromView),
contentType: 'application/json; charset=utf-8',
success: function (data) {
return false;
},
error: function (data) {
alert(xhr.status);
alert(thrownError);
alert(xhr.responseText);
return false;
}
});
});
</script>
and my controller action looks like this
[HttpPost]
public ActionResult ApplyToBecomeInstructor(InstructorApplicationViewModel applicationFromView)
{
Student thisStudent = this.db.Students.Where(o => o.StudentID == applicationFromView.CurrentUserId).FirstOrDefault();
List<PaulSchool.Models.EducationalBackground> educationList = new List<EducationalBackground>();
foreach (var educate in applicationFromView.EducationalBackgrounds)
{
var education = new Models.EducationalBackground
{
YearReceived = educate.YearReceived,
Degree = educate.Degree,
AreaOfStudy = educate.AreaOfStudy,
UniversityOrCollege = educate.UniversityOrCollege
};
educationList.Add(education);
}
var instructorApplication = new InstructorApplication
{
BasicInfoGatheredFromProfile = thisStudent,
Experience = applicationFromView.Experience,
EducationalBackground = new List<Models.EducationalBackground>(),
WillingToTravel = applicationFromView.WillingToTravel
};
instructorApplication.EducationalBackground.AddRange(educationList);
this.db.InstructorApplication.Add(instructorApplication);
this.db.SaveChanges();
return this.Redirect("Index");
}
Error message showing is JSON Parsing error.. but it is confusing to me.
I really wondered why this is happening, can anybody please take a look and help me?
This is what your code does:
$('#btnSubmit').click(function () { // attach a click handler for the button.
...
...
// Look for elements inside the button...
UniversityOrCollege: $(this).find('.university').val(),
Change from click to submit:
$('#formId').submit(function (e) {
...
// Now "this" is the form - not the button.
// Look for elements inside the <form>
UniversityOrCollege: $(this).find('.university').val(),
// Prevent the default form submition
return false // Or: e.preventDefault();
Another tip: use jQuery serialize function.
$('#btnSubmit').click() will fire every time the button is pressed. Often users double click buttons even though it only needs a single click or if you don't give any indication that something is happening they get impatient and click it again. You need some way to determine if the request has been made. There's ways to do this client and server side. The easiest client side way is to disable the button to prevent multiple clicks:
$('#btnSubmit').click(function () {
// Disable the button so it can't be clicked twice accidentally
$('#btnSubmit').attr('disabled', 'disabled');
//...
$.ajax({
//...
complete: function() {
// Make sure we re-enable the button on success or failure so it can be used again
$('#btnSubmit').removeAttr('disabled');
}
});
});
In this JsFiddle : http://jsfiddle.net/maxl/mCXND/
(copied and modified from http://jsfiddle.net/ud3323/XMgwV/)
I try to create an Ember DatePicker based on JQuery's.
The first problem I run into is this line :
var ui = jQuery.ui[this.get('uiType')](options, this.get('element'));
jQuery.ui[this.get('uiType')] doesn't return a function, so I suppose that the solution
that I started with works for some jQueryUI widgets, but not all.
I would like a solution that will work for all JQuery-UI widgets,
and in particular JQueryUI's Datepicker.
Thanks
If you look at the jqueryui code, you see that some of them are invoked as a function, others not. You can solve it using this:
var ui;
if (typeof jQuery.ui[this.get('uiType')] === 'function') {
ui = jQuery.ui[this.get('uiType')](options, this.get('element'));
} else {
ui = this.$()[this.get('uiType')](options);
}
working example: http://jsfiddle.net/PzsrT/7/
One more thing about jQuery UI's datepicker widget as a EmberJS Mixin.
If you want to supply a callback function to handle the beforeShowDay event, you will raise this error:
Uncaught TypeError: Cannot read property '0' of undefined
even if your callback function (in your ember view) return an array, like it's specified in the jqueryui doc
beforeShowDay: function(date){
some code...
return [true, ''];
};
This happens because nothing is returned after the callback.call in the _gatherEvents function
_gatherEvents: function(options) {
var uiEvents = this.get('uiEvents') || [], self = this;
uiEvents.forEach(function(event) {
var callback = self[event];
if (callback) {
// You can register a handler for a jQuery UI event by passing
// it in along with the creation options. Update the options hash
// to include any event callbacks.
options[event] = function(event, ui) { callback.call(self, event, ui); };
}
});
}
I fix this by adding a return statement before the callback.call.
_gatherEvents: function(options) {
var uiEvents = this.get('uiEvents') || [], self = this;
uiEvents.forEach(function(event) {
var callback = self[event];
if (callback) {
// You can register a handler for a jQuery UI event by passing
// it in along with the creation options. Update the options hash
// to include any event callbacks.
options[event] = function(event, ui) { return callback.call(self, event, ui); };
}
});
}
working example http://jsfiddle.net/thibault/qf3Yu/
I would like to have a custom handler for the save button.
How can I override the default command?
The current top answer messed up the toolbar grouping for me (put the save button at the end), and the other answer did not work in ckeditor v4.
Here's how to do it in ckeditor 4:
html:
<textarea id="CKEditor1"></textarea>
javascript:
<script>
// Need to wait for the ckeditor instance to finish initialization
// because CKEDITOR.instances.editor.commands is an empty object
// if you try to use it immediately after CKEDITOR.replace('editor');
CKEDITOR.on('instanceReady', function (ev) {
// Create a new command with the desired exec function
var editor = ev.editor;
var overridecmd = new CKEDITOR.command(editor, {
exec: function(editor){
// Replace this with your desired save button code
alert(editor.document.getBody().getHtml());
}
});
// Replace the old save's exec function with the new one
ev.editor.commands.save.exec = overridecmd.exec;
});
CKEDITOR.replace('CKEditor1');
</script>
CKEDITOR.plugins.registered['save']=
{
init : function( editor )
{
var command = editor.addCommand( 'save',
{
modes : { wysiwyg:1, source:1 },
exec : function( editor ) {
//YOUR CODE
}
}
);
editor.ui.addButton( 'Save',{label : 'YOUR LABEL',command : 'save'});
}
}
If you want to override the save command for just one instance, you can try the following code:
var editor = $('#myTextarea').ckeditorGet(); // Retrieving CKeditor instance with jQuery
editor.getCommand('save').exec = function(editor) {
// Do whatever you need to
...
return true;
};
This should work for any CKEditor command.
function configureEditor(id) {
var editor = CKEDITOR.replace(id);
editor.on("instanceReady", function () {
// overwrite the default save function
editor.addCommand("save", {
modes: { wysiwyg: 1, source: 1 },
exec: function () {
// get the editor content
var theData = editor.getData();
alert("insert your code here");
}
});
editor.ui.addButton('Save', { label: 'My Save', command: 'save', enabled: 'true' });
var saveButton = $('#cke_' + id).find('.cke_button__save');
saveButton.removeClass('cke_button_disabled');
});
}
In CKEditor 4, the save plugin is meant to be cancelable. If unsure, one can always have a look at the source. You can cancel the event and apply your own logic in a handler, like in this example:
//assuming editor is a CKEDITOR.editor instance
editor.on('save', function (event) {
event.cancel();
//your custom command logic
//(you can access the editor instance through event.editor)
});
I would advise against creating a new command and replacing the default with it, as it is an unnecessary workaround.