XDomainRequest sometimes randomly aborts - javascript

XDomainRequest most of them time works ok but sometimes aborts in ie9 specially. has anyone experienced this before?
In case you want to see this is the xdr implementation im using:
(function( jQuery ) {
if ( window.XDomainRequest ) {
jQuery.ajaxTransport(function( s ) {
if ( s.crossDomain && s.async ) {
if ( s.timeout ) {
s.xdrTimeout = s.timeout;
delete s.timeout;
}
var xdr;
return {
send: function( _, complete ) {
function callback( status, statusText, responses, responseHeaders ) {
xdr.onload = xdr.onerror = xdr.ontimeout = jQuery.noop;
xdr = undefined;
complete( status, statusText, responses, responseHeaders );
}
xdr = new window.XDomainRequest();
xdr.onload = function() {
callback( 200, "OK", { text: xdr.responseText }, "Content-Type: " + xdr.contentType );
};
xdr.onerror = function() {
callback( 404, "Not Found" );
};
xdr.onprogress = function() {};
if ( s.xdrTimeout ) {
xdr.ontimeout = function() {
callback( 0, "timeout" );
};
xdr.timeout = s.xdrTimeout;
}
xdr.open( s.type, s.url, true );
xdr.send( ( s.hasContent && s.data ) || null );
},
abort: function() {
if ( xdr ) {
xdr.onerror = jQuery.noop();
xdr.abort();
}
}
};
}
});
}
})( jQuery );

I had this issue a while back and I found that if you wrap your send method inside a setTimeout it solves the issue.
setTimeout(function(){
xdr.send( ( s.hasContent && s.data ) || null );
}, 0);

Related

FullCalendar can't figure out correct moment.js format

I'm trying to setup a schedule system in full calendar. With my current code when you click on a day in the calendar it brings up a modal that displays the day and the time you clicked on. This modal then allows you to add events to the calendar based on that day and time.
What I want is to for the app to only pass the day on click and pass the time through the modal.
If i format the date to ("HH:mm:ss YYYY-MM-DD" ) I can pass in the correct date and all is well. The only thing is I do not want the YYYY-MM-DD portion showing up in my modal. If i trim it to just ("HH:mm:ss" ) It updates the calendar but updates that specific time for every day in the calendar indefinitely.
How can i only show the time in the modal box while still passing the year, month and day to the calendar?
My code is
let isPast = ( date ) => {
let today = moment().format();
return moment( today ).isAfter( date );
};
Template.events.onCreated( () => {
let template = Template.instance();
template.subscribe( 'events' );
});
Template.events.onRendered( () => {
$( '#events-calendar' ).fullCalendar({
header: {
center: 'month,agendaWeek'
},
events( start, end, timezone, callback ) {
let data = Events.find().fetch().map( ( event ) => {
event.editable = !isPast( event.start );
return event;
});
if ( data ) {
callback( data );
}
},
eventRender( event, element ) {
element.find( '.fc-content' ).html(
`<h4>${ event.title }</h4>
<p class="guest-count">${ event.guests } Guests</p>
<p class="type-${ event.type }">#${ event.type }</p>
`
);
},
eventDrop( event, delta, revert ) {
let date = event.start.format();
if ( !isPast( date ) ) {
let update = {
_id: event._id,
start: date,
end: date
};
Meteor.call( 'editEvent', update, ( error ) => {
if ( error ) {
Bert.alert( error.reason, 'danger' );
}
});
} else {
revert();
Bert.alert( 'Sorry, you can\'t move items to the past!', 'danger' );
}
},
dayClick( date ) {
Session.set( 'eventModal', { type: 'add', date: date.format("HH:mm:ss YYYY-MM-DD" ) } );
$( '#add-edit-event-modal' ).modal( 'show' );
},
eventClick( event ) {
Session.set( 'eventModal', { type: 'edit', event: event._id } );
$( '#add-edit-event-modal' ).modal( 'show' );
}
});
Tracker.autorun( () => {
Events.find().fetch();
$( '#events-calendar' ).fullCalendar( 'refetchEvents' );
});
});
And
let closeModal = () => {
$( '#add-edit-event-modal' ).modal( 'hide' );
$( '.modal-backdrop' ).fadeOut();
};
Template.addEditEventModal.helpers({
modalType( type ) {
let eventModal = Session.get( 'eventModal' );
if ( eventModal ) {
return eventModal.type === type;
}
},
modalLabel() {
let eventModal = Session.get( 'eventModal' );
if ( eventModal ) {
return {
button: eventModal.type === 'edit' ? 'Edit' : 'Add',
label: eventModal.type === 'edit' ? 'Edit' : 'Add an'
};
}
},
selected( v1, v2 ) {
return v1 === v2;
},
event() {
let eventModal = Session.get( 'eventModal' );
if ( eventModal ) {
return eventModal.type === 'edit' ? Events.findOne( eventModal.event ) : {
start: eventModal.date,
end: eventModal.date
};
}
}
});
Template.addEditEventModal.events({
'submit form' ( event, template ) {
event.preventDefault();
let eventModal = Session.get( 'eventModal' ),
submitType = eventModal.type === 'edit' ? 'editEvent' : 'addEvent',
eventItem = {
title: template.find( '[name="title"]' ).value,
start: template.find( '[name="start"]' ).value,
end: template.find( '[name="end"]' ).value,
type: template.find( '[name="type"] option:selected' ).value,
guests: parseInt( template.find( '[name="guests"]' ).value, 10 )
};
if ( submitType === 'editEvent' ) {
eventItem._id = eventModal.event;
}
Meteor.call( submitType, eventItem, ( error ) => {
if ( error ) {
Bert.alert( error.reason, 'danger' );
} else {
Bert.alert( `Event ${ eventModal.type }ed!`, 'success' );
closeModal();
}
});
},
'click .delete-event' ( event, template ) {
let eventModal = Session.get( 'eventModal' );
if ( confirm( 'Are you sure? This is permanent.' ) ) {
Meteor.call( 'removeEvent', eventModal.event, ( error ) => {
if ( error ) {
Bert.alert( error.reason, 'danger' );
} else {
Bert.alert( 'Event deleted!', 'success' );
closeModal();
}
});
}
}
});
Image of app
I separate out the date and time into two moments like this:
this.dayClick = function(when) {
this.event.selectedTime = when;
this.event.selectedDate = when.clone();
And then use a datepicker for one, and a timepicker for the other. When saving to the database I need to mash them together for a date/time

CKEditor append child error

With the project I am on, I have been asked to move from CKEditor 3 to 4. Everything works fine except for a custom plugin someone wrote.
Argument 1 of Node.appendChild is not an object.
The code is all over the place, and a bit of a mess. Here is the plugin, which I think is causing the error.
/*
Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or http://ckeditor.com/license
*/
/**
* #fileOverview The "limereplacementfields" plugin.
*
*/
(function()
{
var limereplacementfieldsReplaceRegex = /(\{[A-Z]+[^\{\}]+[A-Z0-9]+\})/g;
CKEDITOR.plugins.add( 'limereplacementfields',
{
requires : [ 'dialog' ],
lang : [ 'en' ],
init : function( editor )
{
var lang = editor.lang.limereplacementfields;
editor.addCommand( 'createlimereplacementfields', new CKEDITOR.dialogCommand( 'createlimereplacementfields' ) );
editor.addCommand( 'editlimereplacementfields', new CKEDITOR.dialogCommand( 'editlimereplacementfields' ) );
editor.ui.addButton( 'Createlimereplacementfields',
{
label : lang.title,
command :'createlimereplacementfields',
icon : this.path + 'limereplacementfields.gif'
});
if ( editor.addMenuItems )
{
editor.addMenuGroup( 'limereplacementfields', 20 );
editor.addMenuItems(
{
editlimereplacementfields :
{
label : lang.title,
command : 'editlimereplacementfields',
group : 'limereplacementfields',
order : 1,
icon : this.path + 'limereplacementfields.gif'
}
} );
if ( editor.contextMenu )
{
editor.contextMenu.addListener( function( element, selection )
{
if ( !element || !element.data( 'cke-limereplacementfields' ) )
return null;
return { editlimereplacementfields : CKEDITOR.TRISTATE_OFF };
} );
}
}
editor.on( 'doubleclick', function( evt )
{
if ( CKEDITOR.plugins.limereplacementfields.getSelectedPlaceHoder( editor ) )
evt.data.dialog = 'editlimereplacementfields';
});
editor.on( 'contentDom', function()
{
editor.document.getBody().on( 'resizestart', function( evt )
{
if ( editor.getSelection().getSelectedElement().data( 'cke-limereplacementfields' ) )
evt.data.preventDefault();
});
});
CKEDITOR.dialog.add( 'createlimereplacementfields', this.path + 'dialogs/limereplacementfields.js' );
CKEDITOR.dialog.add( 'editlimereplacementfields', this.path + 'dialogs/limereplacementfields.js' );
},
afterInit : function( editor )
{
var dataProcessor = editor.dataProcessor,
dataFilter = dataProcessor && dataProcessor.dataFilter,
htmlFilter = dataProcessor && dataProcessor.htmlFilter;
if ( dataFilter )
{
dataFilter.addRules(
{
text : function( text )
{
return text.replace( limereplacementfieldsReplaceRegex, function( match )
{
return CKEDITOR.plugins.limereplacementfields.createlimereplacementfields( editor, null, match, 1 );
});
}
});
}
if ( htmlFilter )
{
htmlFilter.addRules(
{
elements :
{
'span' : function( element )
{
if ( element.attributes && element.attributes[ 'data-cke-limereplacementfields' ] )
delete element.name;
}
}
});
}
},
onLoad: function(editor) {
CKEDITOR.addCss(
'.cke_limereplacementfields' +
'{' +
'background-color: #ffff00;' +
( CKEDITOR.env.gecko ? 'cursor: default;' : '' ) +
'}'
);
}
});
})();
CKEDITOR.plugins.setLang('limereplacementfields','en', {
limereplacementfields: {
title:sReplacementFieldTitle,
button:sReplacementFieldButton
}
}
);
CKEDITOR.plugins.limereplacementfields =
{
createlimereplacementfields : function( editor, oldElement, text, isGet )
{
var element = new CKEDITOR.dom.element( 'span', editor.document );
element.setAttributes(
{
contentEditable : 'false',
'data-cke-limereplacementfields' : 1,
'class' : 'cke_limereplacementfields'
}
);
text && element.setText( text );
if ( isGet )
return element.getOuterHtml();
if ( oldElement )
{
if ( CKEDITOR.env.ie )
{
element.insertAfter( oldElement );
// Some time is required for IE before the element is removed.
setTimeout( function()
{
oldElement.remove();
element.focus();
}, 10 );
}
else
element.replace( oldElement );
}
else
editor.insertElement( element );
return null;
},
getSelectedPlaceHoder : function( editor )
{
var range = editor.getSelection().getRanges()[0];
range.shrink( CKEDITOR.SHRINK_TEXT );
var node = range.startContainer;
while( node && !( node.type == CKEDITOR.NODE_ELEMENT && node.data( 'cke-limereplacementfields' ) ) )
node = node.getParent();
return node;
}
};
Turns out it was another file altogether, which I had to rewrite.

Ajax response how to access

I got this response from ajax
{
"laborCostIndex":0.0,
"laborDailyWage":0.0,
"laborHourlyWage":0.0,
"laborMonthlyWage":0.0,
"laborLeave":0.0,
"laborBonus":0.0,
"laborSSS":0.0,
"laborPagIbig":0.0,
"laborPhilHealth":0.0,
"laborEMP":0.0,
"laborTotalMonthlyRate":110.0,
"laborTotalDailyRate":4.230769230769231,
"laborTotalHourlyRate":0.5288461538461539
}
I'm trying to access the element inside through this:
response.laborCostIndex and response['laborCostIndex'] but seems doesn't work for me.
The ajax is from the xeditable here is the code:
UPDATE: posted the whole ajax
$('.laborCostIndex').editable({
pk: '1',
name: 'laborCostIndex',
url: '../BTool/edit_laborCostIndex.do',
validate: function( value ) {
if($.trim( value ) == '') {
return 'This field is required';
} else if( isNaN( value ) ) {
return 'Only accepts numbers';
}
},
params: function(params) {
var basicDailyWage = $(this).closest('td').next('td').find('a').text();
var pagIbig = $(this).closest('tr').find(':nth-child(11)').find('a').text();
var emp = $(this).closest('tr').find(':nth-child(13)').find('a').text();
var datas = new Array(basicDailyWage, pagIbig, emp);
params.pk = datas;
return params;
},
success: function(response, newValue) {
console.log( response );
console.log( response.laborCostIndex );
console.log( response['laborCostIndex'] );
}
});
Both results to undefined, I don't know why.
Try this in your success function
var obj = JSON.parse(response);
console.log( obj.laborCostIndex);

Using aspect.around, but checking for methods calling each other

I would like to run some specific code around put() and add() for Dojo stores.
The problem I am having is that for JSON REST stores, in JsonRest.js add() is just a function that calls put():
add: function(object, options){
options = options || {};
options.overwrite = false;
return this.put(object, options);
},
So, if I use aspect.around() with add(), my code ends up being executed twice IF I apply my code to stores created with a store that implements add() as a stub to put().
Please note that I realise that most stores will do that. I just want my solution to be guaranteed to work with any store, whether there is method nesting or not.
Dojo's own Observable.js has the same problem. This is how they deal with it:
function whenFinished(method, action){
var original = store[method];
if(original){
store[method] = function(value){
if(inMethod){
// if one method calls another (like add() calling put()) we don't want two events
return original.apply(this, arguments);
}
inMethod = true;
try{
var results = original.apply(this, arguments);
Deferred.when(results, function(results){
action((typeof results == "object" && results) || value);
});
return results;
}finally{
inMethod = false;
}
};
}
}
// monitor for updates by listening to these methods
whenFinished("put", function(object){
store.notify(object, store.getIdentity(object));
});
whenFinished("add", function(object){
store.notify(object);
});
whenFinished("remove", function(id){
store.notify(undefined, id);
});
My question is: is there a simple, "short" way to change my existing code so that it checks if it's within a method, and avoid running the code twice?
I gave it a go, but I ended up with clanky, hacky code. I am sure I am missing something...
Here is my existing code:
topic.subscribe( 'hotplate/hotDojoStores/newStore', function( storeName, store ){
aspect.around( store, 'put', function( put ){
return function( object, options ){
return when( put.call( store, object, options ) ).then( function( r ) {
var eventName;
var identity = store.idProperty;
eventName = object[ identity ] ? 'storeRecordUpdate' : 'storeRecordCreate';
topic.publish( eventName, null, { type: eventName, storeName: storeName, objectId: r[ identity ], object: object }, false );
} );
}
});
aspect.around( store, 'add', function( add ){
return function( object, options ){
return when( add.call( store, object, options ) ).then( function( r ) {
var identity = store.idProperty;
topic.publish('storeRecordCreate', null, { storeName: storeName, storeTarget: storeTarget, objectId: r[identity], object: object }, false } );
});
}
});
});
This is my attempt...
What I don't really "get" about my attempt is whether it's 100% safe or not.
If store.add() is called twice in a row, is is ever possible that inMethod is set to true by the first call, and that the second add() call then finds it already set to true because the first one hasn't managed to set it to false yet?
This would only really be possible if nextTick() is called in between the two calls I assume?
Or am I just completely confused by it all? (Which is very possible...)
topic.subscribe( 'hotplate/hotDojoStores/newStore', function( storeName, store ){
var inMethod;
aspect.around( store, 'put', function( put ){
return function( object, options ){
if( inMethod ){
return when( put.call( store, object, options ) );
} else {
inMethod = true;
try {
return when( put.call( store, object, options ) ).then( function( r ) {
var eventName;
var identity = store.idProperty;
eventName = object[ identity ] ? 'storeRecordUpdate' : 'storeRecordCreate';
topic.publish( eventName, null, { type: eventName, storeName: storeName, objectId: r[ identity ], object: object }, false );
});
} finally {
inMethod = false;
}
}
}
});
aspect.around( store, 'add', function( add ){
return function( object, options ){
if( inMethod ){
return when( add.call( store, object, options ) );
} else {
inMethod = true;
try {
return when( add.call( store, object, options ) ).then( function( r ) {
var identity = store.idProperty;
topic.publish('storeRecordCreate', null, { type: 'storeRecordCreate', storeName: storeName, objectId: r[identity], object: object }, false );
});
} finally {
inMethod = false;
}
}
}
});
aspect.around( store, 'remove', function( remove ){
return function( objectId, options ){
return when( remove.call( store, objectId, options ) ).then( function( r ) {
topic.publish('storeRecordRemove', null, { type: 'storeRecordRemove', storeName: storeName, objectId: objectId }, false );
});
};
});
});

Qunit unit test error , on jQuery ajax

I have written unit test for ajax suing Qunit, but getting error like
Error: assertion outside test context, was .success#http://test.loc/assets/test/widget-add-or-edit-test.js:227
b.Callbacks/c#http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js:3
b.Callbacks/p.fireWith#http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js:3
k#http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js:5 .send/r#http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js:5
Source:
http://code.jquery.com/qunit/qunit-1.11.0.js:899
my test code is
test( "Widget.updateAxisTypeAjax x", function() {
stop();
Widget.updateAxisTypeAjax( {
axis : 'x' ,
x_id : 179,
y_id : 175
} ,{
success : function( response ){
ok( true, "updateAxisTypeAjax Success PASS!");
equal( typeof response ,
"object" ,
"updateAxisTypeAjax response is json valid object !"
);
equal( typeof response == "object" &&
( "average" in response ) &&
("is_datetime" in response) ,
true ,
"updateAxisTypeAjax average check PASS !"
);
} ,
complete : function(){
ok(true, "updateAxisTypeAjax completed PASS!");
start();
}
});
});
and Widget.updateAxisTypeAjax is
Widget.updateAxisTypeAjax = function( data_obj, callbacks ){
data_obj = jQuery.extend( data_obj ,{
action : 'update_axis'
});
Widget.ajax( 5 )
.data( data_obj )
.callbacks( callbacks )
.fire();
}
and Widget.ajax is :
var Widget = Widget || {} ;
function _WidgetAjax( type ){
var loader = $('#series_loader');
this.ajaxUrl = '/dashboard/charts/ajax/' + ( type || 1 ) ;
this.ajaxSettings = {
url: this.ajaxUrl ,
type:"GET",
data :{} ,
complete : function(){ // always
loader.hide();
}
};
// show ajax loading
loader.show();
this.data = function( data ){
jQuery.extend( this.ajaxSettings, { data: data } );
return this;
}
this.callbacks = function( callbacks ){
jQuery.extend( this.ajaxSettings, callbacks || {} );
return this;
}
this.success = function( func ){
if ( jQuery.isFunction( func ) ){
jQuery.extend( this.ajaxSettings, { success: func } );
}
return this;
};
this.fire = function(){
return $.ajax( this.ajaxSettings );
};
};
Widget.ajax = function( type ){
return new _WidgetAjax( type );
};
Please help me fix this unit test error !
You're testing an asynchronous function, so you need to use the async features in QUnit.
Instead of test you should be using asyncTest
Here is the documentation.
Note that you have to tell QUnit how many assertions to expect when doing async tests.
asyncTest( "Widget.updateAxisTypeAjax x", 4, function() {
stop();
Widget.updateAxisTypeAjax( {
axis : 'x' ,
x_id : 179,
y_id : 175
} ,{
success : function( response ){
ok( true, "updateAxisTypeAjax Success PASS!");
equal( typeof response ,
"object" ,
"updateAxisTypeAjax response is json valid object !"
);
equal( typeof response == "object" &&
( "average" in response ) &&
("is_datetime" in response) ,
true ,
"updateAxisTypeAjax average check PASS !"
);
} ,
complete : function(){
ok(true, "updateAxisTypeAjax completed PASS!");
start();
}
});
});
Should probably work. This shouldn't be too hard to fix!

Categories