Monday, October 24, 2011

Run document.ready code in ajax content loaded to jqModal window

Working on a project using the jqModal plugin for jQuery, I came across the need to run some document.ready code on the content that was loaded into the modal viewport via ajax to attach some click events. The parent page had a series of about 50 links that each had to load dynamic content into the same modal window when called. Took a bit of buggering around but finally arrived at the following solution. The setupTabs method is what ultimately applies the click (mouseup for IE7+8) event within the modal window. All of this takes place in the document.ready event of the parent page that contains the trigger links. Several ideas in this code block were discovered using various google searches to work around compatibility bugs between browsers. Why can't companies just upgrade?? Still on IE7... crickey.

//set up modal window for map at night
var mapAtNight = $('#mapAtNight');
if (mapAtNight.length) {
  mapAtNight.attr('aria-hidden', true);
  mapAtNight.jqm({ onShow: modalOpenMapAtNight, onHide: clearMapAtNight });
  mapAtNight.jqmAddClose('.close');
  mapAtNight.jqmAddTrigger('.triggerModalMapAtNight');
}

//open modal window, get data via ajax call and setup overlay
var modalOpenMapAtNight = function (hash) {
  //get content for lightbox from remote page
  getContentMapAtNight(hash.w, hash.t.href)
  //display the modal window
  hash.w.show().attr('aria-hidden', false);

  //attach esc key to close modal
  jQuery(document).keydown(function (e) {
    if (e.which === 27) {
      if (hash.w.is(":visible")) {
        hash.w.jqmHide().attr('aria-hidden', true);
        jQuery('#grid').find('a:eq(0)').focus();
      }
    }
  });
  jQuery('html, body').scrollTop(0);
  jQuery('.jqmOverlay').css({ zIndex: 2 });
  jQuery('.jqmWindow').css({ zIndex: 3 });
  jQuery('#top').css({ position: 'relative', zIndex: 1 });
};

//ajax call for remote content into lightbox  
function getContentMapAtNight(lightbox, url) {
  var containers = [];
  lightbox.find('.ajaxContent').each(function () {
    containers.push(jQuery(this).attr('id'));
  });
  jQuery.get(url, function (data) {
    for (i in containers) {
      jQuery(data).find('#' + containers[i].substr(5)).each(function () {
        var $data = jQuery(this);
        lightbox.find('#' + containers[i]).append($data);
        setupTabs($data);
      });
    }
  });
}

//close modal window and clear contents ready for next load
var clearMapAtNight = function (hash) {
  var containers = [];
  hash.w.find('.ajaxContent').each(function () {
    containers.push(jQuery(this).attr('id'));
  });
  for (i in containers) {
    hash.w.find('#' + containers[i]).empty();
  }
  hash.w.fadeOut('100', function () { hash.o.remove(); });
};

function setupTabs(data) {
  var tabs = data.find('#pageTabs li');
  var contentBlocks = data.find('#mapData div');
  contentBlocks.hide();
  $(contentBlocks + ':first-child').show();

  //ie7 and ie8 remove click event when content is "moved" from one element to another, use mouseup instead
  // can't use href attribute in link as IE7 will try to follow, use name instead
  if (jQuery.browser.version < 9.0 && jQuery.browser.msie) {
    $(tabs).bind('mouseup', function () {
      $(tabs).removeClass("selected"); //Remove any "active" class
      $(this).addClass("selected"); //Add "active" class to selected tab
      contentBlocks.hide(); //Hide all tab content
      var activeTab = '.' + $(this).find("a").attr("name"); //Find the name attribute value to identify the active tab + content
      //ie7 & ie8 utilize same rendering engine and the .show() jquery method does not respond properly, need to manually set display & visibility properties
      $(activeTab).css('display', 'block');
      $(activeTab).css('visibility', 'visible');
      return false;
    });
  } else {
    $(tabs).bind('click', function () {
      $(tabs).removeClass("selected"); //Remove any "active" class
      $(this).addClass("selected"); //Add "active" class to selected tab
      contentBlocks.hide(); //Hide all tab content
      var activeTab = '#' + $(this).find("a").attr("name"); //Find the name attribute value to identify the active tab + content
      $(activeTab).show(); //Fade in the active ID content
      return false;
    });
  }
}

Splitting SQL results into 2 or more groups/tables

Came across a need recently to split a result set into two output tables to achieve a certain layout requirement. SQL 2008 (2005 actually, but why?) makes life so much easier than creating a temp table or taxing joins. The code sample uses NTILE(n) and Over() ranking function to pull roughly equal result sets. Change the value passed to  NTILE() for any number of result sets. I used this output to populate two strongly typed data sets.

------------------------------------
-- Table 0 - Items for group 1
-------------------------------------
SELECT [ItemID] = AutoID, Column2, Column3, Column4 FROM (
SELECT NTILE(2) OVER(ORDER BY AutoID) as GroupID, * FROM dbo.[SourceDataTable] [WHERE CLAUSE]
) [ArbitraryTableName]
WHERE [ArbitraryTableName].GroupID = 1
 
------------------------------------
-- Table 1 - Items for group 2
-------------------------------------
SELECT [ItemID] = AutoID, Column2, Column3, Column4 FROM (
SELECT NTILE(2) OVER(ORDER BY AutoID) as GroupID, * FROM dbo.[SourceDataTable] [WHERE CLAUSE]
) [ArbitraryTableName]
WHERE [ArbitraryTableName].GroupID = 2