I have developed some sort of Jcrop initialization for a website, I managed to make my own namespace. Question I have is regarding this keyword. Every time I had to access my base object “aps” in any callback function I must wrap this in a variable (I have chosen word that). Is there any better way to do it? For example can I use call or apply methods? This is just a namespace so I could use simple aps.methodName but for sake of this example, please don’t mind it. Here is my source code:
var aps;
$(function(){
aps = function(){
// private
// variables
var bgColor = '#f5f5f5';
var threshold = 370;
var threshold_width = 800;
return {
tmpl : $('#jcrop-template').html(),
upl_cont : {},
form : {},
logo_img : new Image(),
jcrop_api : null,
scaled_logo_url : '',
image_filename : '',
original_image_filename : '',
mime : '',
trueSize : '',
jcrop_init : function (oiFrameRes){
$('#logo_upload_form').find('img').hide();
this.scaled_logo_url = oiFrameRes.image_url;
this.logo_url = oiFrameRes.original_image_url;
this.original_image_filename = oiFrameRes.original_image_filename;
this.image_filename = oiFrameRes.image_filename;
this.mime = oiFrameRes.mime;
this.upl_cont = $('#facebox div#upload-container-d');
this.logo_img = new Image();
this.logo_img.that = this;
this.logo_img.name = 'logo';
this.logo_img.onload = function(){
this.true_width=this.width;
this.true_height=this.height;
this.that.resize_image();
this.that.resize_facebox();
this.that.display_image();
}
this.logo_img.src = this.logo_url;
},
resize_image : function(){
this.trueSize = '';
if(typeof (this.oSettings.trueSize)!=='undefined') delete(this.oSettings.trueSize);
if (this.logo_img.width > threshold){
if (this.logo_img.width > threshold_width){
this.trueSize = [ this.logo_img.width, this.logo_img.height ];
this.logo_img.height = this.logo_img.height / (this.logo_img.width / threshold_width);
this.logo_img.width = threshold_width;
}
}
},
resize_facebox : function(){
var width = (this.logo_img.width > threshold) ? this.logo_img.width : threshold ;
$('#facebox').css({
left : $(window).width() / 2 - width / 2
}).
find('div.change-size').css({'width': width+30});
},
display_image : function (){
if (this.jcrop_api === null) {
$logo_img = $(this.logo_img).css({'display':'block','margin-left':'auto','margin-right':'auto'})
if (this.upl_cont.find('#logo-container-d>img').length > 0){
if (this.upl_cont.find('#logo-container-d>img').attr('src').length > 0){
this.upl_cont.find('#logo-container-d').empty().append($logo_img);
}
}
else {
this.upl_cont.append(this.tmpl).find('#logo-container-d').append($logo_img);
}
var that = this;
if (typeof (this.upl_cont.find('#jcrop-menu1 a').data('events')) === 'undefined'){
this.upl_cont.find('#jcrop-menu1 a').click(function(){
if (this.href.indexOf('#crop')>-1){
$(this).closest('div').hide();
that.upl_cont.find('#jcrop-menu2').show();
that.setup_crop();
}
if (this.href.indexOf('#close')>-1){
manageIframeResponse();
}
location.hash = '';
return false;
});
}
}
else {
this.reset();
}
},
reset : function(){
$('#jcrop-menu2',this.upl_cont).find('a').unbind('click').end().hide();
$('#jcrop-coords-f',this.upl_cont).find('input[type="text"]').each(function(){this.value="";}).end().hide();
$('#jcrop-menu1',this.upl_cont).find('a').unbind('click').end().show();
this.jcrop_api.destroy();
this.jcrop_api=null;
this.display_image();
},
send_form : function (){
var sPost = $(this.form).find('input[name="image_filename"]').val(this.image_filename).end()
.find('input[name="original_image_filename"]').val(this.original_image_filename).end()
.find('input[name="mime"]').val(this.mime).end()
.find('input[name="user_url"]').val($('#logo_upload_base_url').val()).end()
.find('input[name="user_key"]').val($('#logo_upload_user_key').val()).end()
.serialize();
$.ajax({
url:'iframe_upload.php',
type:'POST',
data: sPost,
success : function(response){
manageIframeResponse();
},
dataType : 'json'
});
},
setup_crop : function (){
var that = this;
if (this.jcrop_api === null) {
this.form = this.upl_cont.find('form#jcrop-coords-f').get(0);
this.upl_cont.find('#jcrop-menu2>a').click(function(){ that.send_form();return false; });
this.updateForm = function (){
var c = arguments[0];
that.form.x1.value=c.x;
that.form.x2.value=c.x2;
that.form.y1.value=c.y;
that.form.y2.value=c.y2;
that.form.h.value=c.h;
that.form.w.value=c.w;
}
this.oSettings.onSelect = this.updateForm;
if (typeof (this.trueSize) !== 'string' && $.isArray(this.trueSize)){
$.extend(this.oSettings,{'trueSize':this.trueSize});
}
$('#facebox #logo-container-d>img').Jcrop( this.oSettings, function(){
that.jcrop_api = this;
var _x1 = (that.logo_img.true_width*0.1).toFixed();
var _y1 = (that.logo_img.true_height*0.1).toFixed();
var _x2 = (that.logo_img.true_width*0.9).toFixed();
var _y2 = (that.logo_img.true_height*0.9).toFixed();
that.jcrop_api.setSelect([0,0,that.logo_img.true_width,that.logo_img.true_height]);
that.jcrop_api.animateTo([_x1,_y1,_x2,_y2]);
});
}
},
updateForm : function (){},
oSettings : {
onSelect:'',
onChange:'',
keySupport: false,
bgColor:bgColor,
aspectRatio:1,
minSize:[0,0]
}
}
}();
$(document).bind('afterClose.facebox', function() {
if (aps.jcrop_api !=null) {
aps.jcrop_api.destroy();
aps.jcrop_api=null;
}
});
});
Anytime a function is invoked using function invocation*, the
thisvalue is set to the global variable (orundefinedin strict mode)—even if you call the function from a method. Douglas Crockford has actually described this as a flaw in the language.Saving the
thisvalue into a variable that the function will have access to is the standard way of dealing with this.If you really want to control what
thisis in your callback, you could useapplyorcall. Both take as the first argument what you wantthisto be set to. The difference is thatapplyexpects all the function’s arguments to be passed as an array, whilecallexpects you to list them out individually.So if, in your ajax callback, you wanted to call
manageIframeResponse, pass it the ajax call’s response (I know your example didn’t pass the response, I’m just illustrating how you would do it), and have itsthisvalue be the same as the current object, you could do:Or, since your parameters aren’t already in array form, you could more simply use
call*
There are different ways to invoke a function.
Function invocation means you’re just calling a function that happens to be in your current scope:
Method invocation means that you’re calling a function that’s attached to an object
Here’s an example of where this can trip you up if you’re nor careful.