Showing posts with label Javascript. Show all posts
Showing posts with label Javascript. Show all posts

Tuesday, April 19, 2011

ClientIDMode = “Predictable” broke my dropdown list auto partial postback

In my previous post, I try to upgrade my recent .NET web apps to use recent .NET for capabilities by doing this

<pages controlRenderingCompatibilityVersion="4.0">






But unfortunately, I find couple of my control inside UPDATE PANEL – does not do Partial Postback anymore. (It is doing FULL postback now)

This only happen to a control outside button which I have set as autoPostback = true.





After looking around and test which part that I need to put it back, I found clientIDMode.

I need to set clientIDMode=“AutoID” because the default value is “Predictable”.





<pages controlRenderingCompatibilityVersion="4.0" clientIDMode="Predictable">






The weird things is I try to compare the id and html which generated by both “predictable and “AutoID”. And the result is the SAME but the different is one of them can do partial postback and one of them not.





<!-- Generated when I set "clientIDMode='Predictable'" -->
<select class="ddlPostback" id="ContentPlaceHolderDefault_MainContainerPlaceHolder_ucProductDetail_rptVariationChoiceGroup_ddlChoiceGroup_0" onchange="javascript:setTimeout('__doPostBack(\'ctl00$ctl00$ctl00$ContentPlaceHolderDefault$MainContainerPlaceHolder$ucProductDetail$rptVariationChoiceGroup$ctl00$ddlChoiceGroup\',\'\')', 0)" name="ctl00$ctl00$ctl00$ContentPlaceHolderDefault$MainContainerPlaceHolder$ucProductDetail$rptVariationChoiceGroup$ctl00$ddlChoiceGroup">
<option value="">Please select</option>
<option value="2" selected="selected">Green</option>
<option value="3">Yellow</option>
<option value="4">Blue</option>
<option value="5">Brown</option>
</select>


<!-- Generated when I set "clientIDMode='AutoID'" -->
<select class="ddlPostback" id="ContentPlaceHolderDefault_MainContainerPlaceHolder_ucProductDetail_rptVariationChoiceGroup_ddlChoiceGroup_0" onchange="javascript:setTimeout('__doPostBack(\'ctl00$ctl00$ctl00$ContentPlaceHolderDefault$MainContainerPlaceHolder$ucProductDetail$rptVariationChoiceGroup$ctl00$ddlChoiceGroup\',\'\')', 0)" name="ctl00$ctl00$ctl00$ContentPlaceHolderDefault$MainContainerPlaceHolder$ucProductDetail$rptVariationChoiceGroup$ctl00$ddlChoiceGroup">
<option value="">Please select</option>
<option value="2" selected="selected">Green</option>
<option value="3">Yellow</option>
<option value="4">Blue</option>
<option value="5">Brown</option>
</select>



Friday, April 08, 2011

Firefox Update panel after 2 mins idle time

Recently, I fight with firefox bug which aborting my partial postback from update panel after 2 mins idle time.

Here was my step to investigate this problem

  • check other browsers (IE, IE6, Chrome) – and the result, only firefox does this weird behaviour
  • create simple update panel and tested on FF. – unfortunately this work perfectly
    and then I wonder why my actual code does not work.
  • Apply more content on Update Panel – It is not work again (oh my be it’s I need to make my content on update panel smaller)
  • After trying to make my update panel content smaller, it still not work.
  • Then I use my previous simple update panel to test if it is content outside update panel is matter. – (Yes, it is the content outside update panel is matter)
  • Confuse how I solve this, we still need to use update panel for particular reason because of the due date, etc. so we can’t change anything (we have to keep the update panel but has to work in FF)

After looking around the solutions, luckily I found on the other section of my project work perfectly after 2 mins idle in FF.

I try to investigate why that section work but not this. Finally I figure out that the different is that part is calling ajax call on other page before call partial postback.

Then here is my simple solutions to fix this.

  • Register Begin Request
    Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(microsoftAJAX_BeginRequest);
  • check the browser if it is mozilla and the time difference is 2 mins then request to other server page (ASPX page) first synchonously before continue the process.

    Here is the code, hopefully it will help your problem as well.
    //check availability for partial postback for FF fixed. FF will abort the partial postback call after 2 mins unless it call ajax to other page first
    var checkConnectionForPartialPostback = function ()
    {
    $.ajax({
    url: "/usercontrols/testconnection.aspx",
    async: false
    });
    };

    //check availability for partial postback for FF fixed. FF will abort the partial postback call after 2 mins unless it call ajax to other page first
    var checkAvailabilityForPartialPostback = function ()
    {
    //firefox fix for time diff
    if ($.browser.mozilla && GetTimeDiff(new Date(), lastLoadTime).getMinutes() >= 2)
    {
    //refresh this page
    checkConnectionForPartialPostback();
    }
    else
    {
    lastLoadTime = new Date();
    }
    };







Wednesday, April 06, 2011

Basic Geolocation example

Here is some basic geolocation example and display it to google maps.

<!DOCTYPE html>
<html>

<head>
<script src="js/jquery-1.4.2.min.js"></script>
<script src="js/yqlgeo.js"></script>
<script>
jQuery(window).ready(function(){
jQuery("#btnInit").click(initiate_geolocation);
})

function initiate_geolocation() {
if (navigator.geolocation)
{
navigator.geolocation.getCurrentPosition(handle_geolocation_query, handle_errors);
}
else
{
yqlgeo.get('visitor', normalize_yql_response);
}
}

function handle_errors(error)
{
switch(error.code)
{
case error.PERMISSION_DENIED: alert("user did not share geolocation data");
break;

case error.POSITION_UNAVAILABLE: alert("could not detect current position");
break;

case error.TIMEOUT: alert("retrieving position timedout");
break;

default: alert("unknown error");
break;
}
}

function normalize_yql_response(response)
{
if (response.error)
{
var error = { code : 0 };
handle_error(error);
return;
}

var position = {
coords :
{
latitude: response.place.centroid.latitude,
longitude: response.place.centroid.longitude
},
address :
{
city: response.place.locality2.content,
region: response.place.admin1.content,
country: response.place.country.content
}
};

handle_geolocation_query(position);
}

function handle_geolocation_query(position){
alert('Lat: ' + position.coords.latitude + ' ' +
'Lon: ' + position.coords.latitude);
}
</script>

</head>
<body>
<div>
<button id="btnInit" >Find my location</button>
</div>

</body>
</html>function handle_geolocation_query(position)
{
var image_url = "http://maps.google.com/maps/api/staticmap?sensor=false&center=" + position.coords.latitude + "," +
position.coords.longitude + "&zoom=14&size=300x400&markers=color:blue|label:S|" +
position.coords.latitude + ',' + position.coords.longitude;

jQuery("#map").remove();
jQuery(document.body).append(
jQuery(document.createElement("img")).attr("src", image_url).attr('id','map')
);
}



JQuery Intellisense in VS 2010

 

If you want  jquery intellisense in your visual studio like this the you can get the vsdoc file generator which hosted by damo

http://damianedwards.com/vsdoc/

image

Tuesday, March 29, 2011

Refresh Javascript

Here are my favourite links to refresh or introduce Javascript to new comers.

http://www.jslint.com/lint.html

http://vimeo.com/18511621

http://developer.yahoo.com/yui/theater/ by Douglas Crockford

 

Javascript is a wild language which need to be tamed.
Here are some js pattern which I think best pattern to tackle down the scoping and closure issue which called (Module Pattern)

http://stackoverflow.com/questions/3722820/examples-of-practical-javascript-object-oriented-design-patterns

Recently I build a framework called SiteUI which follows this pattern and give you protection and flexibility.

SiteUI.BaseUI = function (options)
{
//default options
var defaultsOpt = {
//set it to false otherwise, when you disable from the ajax, it when postback it will enable all your control
//but if you have other reason you can do so.
disableAllButtonOnSubmit: false,
ajaxProcessMessage: "Processing..."
};

var options = $.extend(defaultsOpt, options);


//optional value - to disable all button on submit or not
var disableAllButtonOnSubmit = options.disableAllButtonOnSubmit;
var setDisableAllButtonOnSubmit = function (value)
{
disableAllButtonOnSubmit = value;
}

var ajaxProcessMessage = options.ajaxProcessMessage;
var setAjaxProcessMessage = function (value)
{
ajaxProcessMessage = value;
}

//Shopping Cart Control
var shoppingCartControl = null;

var ddlPostbackSelector = '.ddlPostback';
var txtPostbackSelector = '.txtPostback';
var btnPostbackSelector = '.btnPostback';
var chkPostbackSelector = '.chkPostback';

var loadingSelector = '.postbackLoading';
var loaderHtml = "<img src='/images/ajax-loader.gif' class='postbackLoading' style='width:15px;height:15px;position:absolute; z-index:9999;' />";



var isHideLoadingBeforePostbackTemporary = false;
//this to indication a form validator after call back - (CommonFormValidator.js option)
var formValidator_CallBack = function (source, isValid)
{
//alert('formValidator_CallBack : ' + isValid);
if (!isValid)
{
//not valid - hide loading temporary - because this will be called first before click happen
isHideLoadingBeforePostbackTemporary = true;
}
};

//Show loading
var showLoadingBeforePostback = function (source, addLoadingToParent)
{
//alert('showLoadingBeforePostback isHideLoadingBeforePostbackTemporary: ' + isHideLoadingBeforePostbackTemporary);
if (!isHideLoadingBeforePostbackTemporary)
{
//add loader html after
if (addLoadingToParent)
{
$(source).parent().after(loaderHtml);
showPageLoader(); //show page loader
}
else
{
$(source).after(loaderHtml);
showPageLoader(); //show page loader
}
}
else
{
//set it to false again
isHideLoadingBeforePostbackTemporary = false;
}
};

//Clear Loading Function
var clearLoading = function ()
{
$(loadingSelector).remove();
hidePageLoader();
};

//show Page loader - this using jquery.loader this will disable all the button automatically
var showPageLoader = function ()
{
$.loader({
className: "loaderBox",
content: ''
});

};

//hide page loader
var hidePageLoader = function ()
{
$.loader('close');
};

//Show Hide Loading On Content
var showHideLoadingOnContent = function (contentSelector, isShow)
{
if (isShow)
{
$(contentSelector).before(loaderHtml); //add loader after it fades

//show loading
showPageLoader(); //show page loader to hide
$(contentSelector).animate({ opacity: 0 }, 150);
//$(contentSelector).effect('fade',null,500);

}
else
{
//hide loading - remove all loading selector
$(loadingSelector).remove(); //remove loader first
hidePageLoader(); // hide page loader
//just in case if in the beginning it hides this
$(contentSelector).animate({ opacity: 1 }, 150);
//$(contentSelector).effect('fade',null,500);
}
};

//redirect content
var redirectContent = function (url, contentSelector)
{
if (contentSelector)
{ //only if they pass content selector we can redirect with show and hide loading
showHideLoadingOnContent(contentSelector, true);
}

window.location = url;
};

//update content
var updateContent = function (responseText, contentSelector, updateContent_Callback)
{

$(contentSelector).html(responseText);


if (updateContent_Callback)
updateContent_Callback(responseText);

//hide loading on content
showHideLoadingOnContent(contentSelector, false);
};

//Used to track last Request Ajax URL
var lastRequestAjaxUrl = "";
//load content
var loadContent = function (ajaxUrl, relatedData, contentSelector, updateContent_Callback)
{
showHideLoadingOnContent(contentSelector, true);

lastRequestAjaxUrl = ajaxUrl;
$.ajax({
type: "POST",
url: ajaxUrl,
data: relatedData,
complete: function (data, stat)
{
//only process last request ajax url
if (this.url == lastRequestAjaxUrl)
{
//$.log("Update this " + this.url + " VS " + lastRequestAjaxUrl);
if (stat == "success")
{
var isError = true;
updateContent(data.responseText, contentSelector, updateContent_Callback);
}
else
{
updateContent("<p>Error Loading Data : " + stat + ' : ' + data.responseText + "</p>", contentSelector, updateContent_Callback);
}
}
else
{
//$.log("Dispose this ajax " + this.url + " VS " + lastRequestAjaxUrl);
}
}
});
};


// *************** MICROSOFT AJAX INIT - HANDLE ALL AJAX CALL*******************
var initMicrosoftAjaxRequest = function ()
{
/// <reference name="MicrosoftAjax.js"/>
if (typeof (Sys) != 'undefined' && typeof (Sys.WebForms) != 'undefined')
{
Sys.Application.add_init(microsoftAJAX_App_Init);
}
};

var microsoftAJAX_App_Init = function ()
{
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(microsoftAJAX_BeginRequest);
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(microsoftAJAX_EndRequest);
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(microsoftAJAX_pageLoaded);
};

var postbackTriggerElement;
var microsoftAJAX_BeginRequest = function (sender, args)
{
if (disableAllButtonOnSubmit)
{
//disable all button
disableAllSubmitButtons(true);
}
postbackTriggerElement = args.get_postBackElement()
var ctrl = $(postbackTriggerElement);

//remove all validation error
removeAllValidationError();

if (ctrl.is("input:checkbox") || ctrl.is("input:radio"))
{
ctrl.hide(); //hide this check box
if (!ctrl.hasClass("noLoaderOnPostback"))
{
showLoadingBeforePostback(ctrl, true); //show loading on this control
}
}
else if (ctrl.is("input:submit"))
{ //you can change it to other
if (ctrl.hasClass("waitLabelOnPostback"))
{
if (ajaxProcessMessage != "")
{
ctrl.val(ajaxProcessMessage);
}
}

if (ctrl.hasClass("disableOnPostback"))
{
ctrl.attr('disabled', true); //disable but later on postback it will enable or disable based on the behaviour
}


if (!ctrl.hasClass("noLoaderOnPostback"))
{
showLoadingBeforePostback(ctrl);
}
}
else
{ //other items show loading
//show loading on this control
if (!ctrl.hasClass("noLoaderOnPostback"))
{
showLoadingBeforePostback(ctrl);
}
}
};

var microsoftAJAX_pageLoaded = function (sender, args)
{
if (!postbackTriggerElement)
{
return;
}

//get updated panels and referesh
var updatedPanels = args.get_panelsUpdated();
for (i = 0; i < updatedPanels.length; i++)
{
//apply filter textbox
setFilterTextbox(updatedPanels[i].id);
//set rating
setRating(updatedPanels[i].id);
//set date picker
setDatePicker(updatedPanels[i].id);
//set text area counter
setTextAreaCounter(updatedPanels[i].id);

//Call Microsoft AJAX_EndRequest_AdditionalFunciton() if available
if (typeof (microsoftAJAX_PageLoaded_AdditionalFunction) == 'function')
{
microsoftAJAX_PageLoaded_AdditionalFunction(updatedPanels[i].id);
}
}
};


//end request
var microsoftAJAX_EndRequest = function (sender, args)
{
if (args.get_error() != undefined)
{
var errorMessage = args.get_error().message;
args.set_errorHandled(true);
alert("Error in ajax call : " + errorMessage);
clearLoading(); //clear loading
return;
}


if (disableAllButtonOnSubmit)
{
//enable all button
disableAllSubmitButtons(false);
}




//Call Microsoft AJAX_EndRequest_AdditionalFunciton() if available
if (typeof (microsoftAJAX_EndRequest_AdditionalFunction) == 'function')
{
microsoftAJAX_EndRequest_AdditionalFunction();
}


//empty the postback element
postbackTriggerElement = null;

hidePageLoader(); //hide page loader
};


//this can be override by calling set ajax page loaded
var microsoftAJAX_PageLoaded_AdditionalFunction = function (updatedPanelId)
{
//baseUI. microsoft AJAX Page Loaded Additional funxtion
//you can write default function here
};

//this can be override by calling set ajax end request
var microsoftAJAX_EndRequest_AdditionalFunction = function ()
{
//baseUI. microsoft AJAX End Request Additional funxtion
//you can write default function here
};

//override ajax end request
var overrideMicrosoftAJAX_EndRequest_AdditionalFunction = function (func)
{
microsoftAJAX_EndRequest_AdditionalFunction = func;
};

//override ajax page loaded
var overrideMicrosoftAJAX_PageLoaded_AdditionalFunction = function (func)
{
microsoftAJAX_PageLoaded_AdditionalFunction = func;
};
//-----------------------------------------------



//use for postback
var setupPostbackControlEvents = function ()
{
//show loading before postback
$(ddlPostbackSelector).live("change", function (e)
{
//e.preventDefault();//cannot prevent default, it won't go to onclick
showLoadingBeforePostback(this);
});

//filter search keyword
$(txtPostbackSelector).live("change", function (e)
{
//e.preventDefault();//cannot prevent default, it won't go to onclick
showLoadingBeforePostback(this);
});

$(btnPostbackSelector).live("click", function (e)
{
//e.preventDefault(); //cannot prevent default, it won't go to onclick
showLoadingBeforePostback(this);

if ($(this).hasClass("clearValidation"))
{
//check if it has class clear validation
removeAllValidationError();
}

});


$(chkPostbackSelector + " input").live("change", function (e)
{
//e.preventDefault(); //cannot prevent default, it won't go to onclick
showLoadingBeforePostback(this, true);
removeAllValidationError(); //it will clear validation - usually this will change the view
});
};


//setup Dropdown Item
var setupDropdownItem = function ()
{

//find drop down item trigger
$('.dropdownItemTrigger').each(function ()
{
// Make the drop down cart appear/disappear.
var boxSelector = $(this).attr('rel');

// Set natural height and other properties of hidable object.
$(boxSelector).data('naturalHeight', $(boxSelector).height());
$(boxSelector).addClass('hidden');
$(boxSelector).css(
{
display: 'none',
bottom: 'auto'
});

// Create back reference.
$(boxSelector).data('trigger', $(this));
});

$('.dropdownItemTrigger').live("click", function (e)
{
e.preventDefault();

var $trigger = $(this);

// Don't do anything if the drop down item is already animating.
if ($trigger.hasClass('disabled')) return false;

// Find direction.
var direction = $trigger.hasClass('maximise') ? 1 : -1;

// Find effect type.
var classes = $trigger.attr('class'); //.match(/effect-/);
var effect = $trigger.attr('class').match(/\beffect-[a-z]{1,}/);
//alert(effect);

// Make the drop down cart appear/disappear.
var boxSelector = $trigger.attr('rel');



if (boxSelector == shoppingCartControl.shoppingCartControlSelector)
{
shoppingCartControl.checkToReload();
}

$(boxSelector).trigger('dropdowntoggle', [direction, effect]);
});

$('.dropdownItem').live('dropdowntoggle', function (e, direction, fxtype)
{
var $dropdownItem = $(this);
var $trigger = $dropdownItem.data('trigger');


// Ensure direction.
if (isNaN(direction)) direction = $dropdownItem.hasClass('shown') ? -1 : 1;

// Disable trigger.
$trigger.addClass('disabled');

// Set states. / cursor
$trigger.toggleClass('maximise', direction == -1);
$trigger.toggleClass('minimise', direction == 1);

$dropdownItem.toggleClass('hidden', direction == -1);
$dropdownItem.toggleClass('shown', direction == 1);

// Effect
//var currPosition = $dropdownItem.css('top').replace(/([a-z]+)/, '') * 1
var currPosition; // = direction == 1 ? $dropdownItem.height() * -1 : 0;
var displacement; // = $dropdownItem.height(); //$dropdownItem.data('naturalHeight');
var newPosition; // = currPosition + displacement * direction;

//alert(fxtype);
// Toggle drop down item + Effect
if (fxtype == 'effect-slide')
{
// Calculate new values.
currPosition = direction == 1 ? ($dropdownItem.height() * -1) : 0 - 50;
displacement = $dropdownItem.height(); //$dropdownItem.data('naturalHeight');
newPosition = currPosition + displacement * direction;

// Execute
$dropdownItem.css(
{
display: 'block',
top: currPosition
}).animate(
{
top: newPosition
}, 400, function ()
{
$trigger.toggleClass('active', direction == 1);

$trigger.removeClass('disabled');
});
}
else
{
// if (fxtype=='effect-fade') {
// Calculate new values.
var currOpacity = direction == 1 ? 0 : 1;
var newOpacity = direction == 1 ? 1 : 0;


//Execute
$dropdownItem.css(
{
display: 'block',
top: 0,
opacity: currOpacity
}).animate(
{
opacity: newOpacity
}, 400, function ()
{
$trigger.toggleClass('active', direction == 1);
if (direction == -1)
{
//hide the display
$dropdownItem.css({display: 'none'});
}
$trigger.removeClass('disabled');
});
}

});
};

/*this doesn't work for shopping cart in IE 6*/
var setupDropdownItemUsingJqueryUI = function ()
{
//Bind Drop down item - just require this button
$('.dropdownItemTriggerBlind').live("click", function (e)
{
e.preventDefault();

var $trigger = $(this);
// Make the drop down cart appear/disappear.
var boxSelector = $trigger.attr('rel');

//check if it is shopping cart control
if (boxSelector == shoppingCartControl.shoppingCartControlSelector)
{
shoppingCartControl.checkToReload();
}


//using jquery.ui toggle( effect, [options], [speed], [callback] )
$(boxSelector).toggle('blind', null, 300);

});

}


/*Setup Events - This will be call unsynchronously*/
var setupEvents = function ()
{ //setup postback control events
setupPostbackControlEvents();
//setup drop down
setupDropdownItem();



//for login trigger
$(".txtTriggerLogin").live("change", function (e)
{
$(".btnLogin").click();
});

$(".txtTriggerLogin").live("keypress", function (e)
{
//$.log('run from DISABLE DEFAULT BUtton');
return runFunctionOnEnter(e,
function ()
{
$(".btnLogin").click();
}
);
});


// Removes SEO text in navItems
$(".clearText").html("");
$(".clearText").removeClass("clearText");

// Clears input fields on Focus
// Title must match the value to clear.
$(".clearField").live("blur", function ()
{
if ($(this).val() == "")
{
$(this).val($(this).attr("title"));
};
});

$(".clearField").live("focus", function ()
{

if ($(this).val() == $(this).attr("title"))
{
$(this).val("");
};
});


//bind shopping cart
//cart = new SiteUI.ShoppingCart();
//cart.updateCartHover();
};

/*Constructor*/
var bindDefaultBehaviour = function ()
{
//init ajax request behaviour
initMicrosoftAjaxRequest();
//disable default button
disableDefaultButton();

//set droppy menu
$('#dropdownNavigation').droppy();

shoppingCartControl = new SiteUI.ShoppingCartControl();

//run this async
setTimeout(function ()
{
setupEvents();


//apply filter textbox
setFilterTextbox();

setRating();
setDatePicker();
setTextAreaCounter();

}, 0);
};

var init = function ()
{

}

//return public method
return {
bindDefaultBehaviour: bindDefaultBehaviour,
formValidator_CallBack: formValidator_CallBack,
redirectContent: redirectContent,
setupPostbackControlEvents: setupPostbackControlEvents,

loadContent: loadContent,
updateContent: updateContent,

clearLoading: clearLoading,
showLoadingBeforePostback: showLoadingBeforePostback,
showHideLoadingOnContent: showHideLoadingOnContent,

showPageLoader: showPageLoader,
hidePageLoader: hidePageLoader,

setAjaxProcessMessage: setAjaxProcessMessage,
setDisableAllButtonOnSubmit: setDisableAllButtonOnSubmit,
overrideMicrosoftAJAX_EndRequest_AdditionalFunction: overrideMicrosoftAJAX_EndRequest_AdditionalFunction,
overrideMicrosoftAJAX_PageLoaded_AdditionalFunction: overrideMicrosoftAJAX_PageLoaded_AdditionalFunction
};
}