Revision: 1485
Author:
net.a...@gmail.com
Date: Mon Apr 4 09:08:43 2011
Log: - Added javascript functions to enable display of gantry
forms/results
via ajax.
- Added needed jquery dependencies.
- Updated Gantry.pm to allow returning of errors in json format
to support ajax frontends.
- Incorporated functionality of AjaxCRUD plugin into CRUD plugin to allow
CRUD to support ajax forms.
- Added TO_JSON method to View.pm and Form.pm to allow to_json method of
the JSON library to convert their data stuctures into json format.
- Updated TablePerms.pm to allow links containing request parameters to
be output correctly. Also updated it to process rel option.
http://code.google.com/p/gantry/source/detail?r=1485
Added:
/trunk/root/js/ajaxForm.js
/trunk/root/js/ajaxResults.js
/trunk/root/js/jquery-1.4.3.min.js
/trunk/root/js/jquery.address.min.js
/trunk/root/js/jquery.blockUI.js
/trunk/root/js/jquery.form.js
/trunk/root/js/jquery.sprintf.js
/trunk/root/js/jquery.url.min.js
Modified:
/trunk/Changes
/trunk/MANIFEST
/trunk/lib/Gantry/Plugins/CRUD.pm
/trunk/lib/Gantry/Stash/View/Form.pm
/trunk/lib/Gantry/Stash/View.pm
/trunk/lib/Gantry/Utils/TablePerms.pm
/trunk/lib/Gantry.pm
/trunk/t/auth/04_run.t
=======================================
--- /dev/null
+++ /trunk/root/js/ajaxForm.js Mon Apr 4 09:08:43 2011
@@ -0,0 +1,743 @@
+/**
+ *
+ * Gantry: ajaxForm.js
+ *
+ * Contains functions to display / render gantry forms using ajax.
+ *
+ * Author John Weigel [John.Weigel at knology dot com]
+ * Copyright (C) 2011 Knology
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <
http://www.gnu.org/licenses/>.
+ *
+ */
+
+var $j = jQuery.noConflict();
+var blocking = false;
+var gantryAjaxFormBuiCss;
+var gantryAjaxErrorFormBuiCss;
+var gantryAjaxFormOptions = {};
+
+$j(document).ready(function() {
+ var offset = $j("#results").offset();
+ var top = 140;
+ var left = 150;
+
+ // Set css defaults for bui popup form.
+ gantryAjaxFormBuiCss = {
+ top: top,
+ left: offset.left + left,
+ width: '425px',
+ border: '1px solid #000',
+ backgroundColor: '#ccc',
+ '-webkit-border-radius': '10px',
+ '-moz-border-radius': '10px',
+ opacity: '1',
+ color: '#000'
+ };
+
+ // Set css defaults for bui popup error form.
+ gantryAjaxErrorFormBuiCss = {
+ width: '300px',
+ border: 'none',
+ padding: '15px',
+ backgroundColor: '#000',
+ '-webkit-border-radius': '10px',
+ '-moz-border-radius': '10px',
+ opacity: '.8',
+ color: '#fff'
+ };
+
+ /**
+ *
+ * function: $j.address.change(fn)
+ *
+ * parameters: event
+ *
+ * description: Method that gets called when navigation changes occur.
+ * event object contains the following:
+ * value - url including query string.
+ * path - url minus the query string.
+ * pathNames - comma separated list of each part of the path.
+ * parameterNames - comma separated list of parameter names.
+ * parameters - object containing parameter values.
+ * queryString - url query string.
+ *
+ */
+ $j.address.change(function(event) {
+ if (event.value == '/') {
+ if (blocking == true) {
+ $j.unblockUI();
+ }
+ }
+ else {
+ gantryAjaxDisplayForm(event.path, event.parameters.gftype,
event.parameters.eftype);
+ }
+ });
+});
+
+/**
+*
+* function: gantryAjaxRenderForm(formType, json)
+*
+* parameters: formType, json
+*
+* description: Given the type of form (currently bui or inline) and a json
+* representation of a gantry form, it will render the form
+* to the page. bui type forms use the blockUI jquery plugin
+* to create a blocking popup form. Inline forms will replace
+* the content on the page with output of the form.
+*/
+function gantryAjaxRenderForm (formType, json) {
+ var fieldsets = [];
+ var cfsgroup = {};
+ var jform = $j(
+ $j.sprintf(
+ '<form action="%s" method="post" class="form-box">' +
+ '<div class="form-box">' +
+ '</div>' +
+ '</form>',
+ json.form.action
+ )
+ );
+ var ajaxFormOptions = {
+ 'dataType' : 'json',
+ 'success' : function (result_json, status_text) {
+ // Response contains a form...
+ if (result_json.form != null) {
+ // Set form action to original form action if none was specified.
+ if (result_json.form.action == null) {
+ result_json.form.action = json.form.action;
+ }
+
+ gantryAjaxRenderForm(formType, result_json);
+ }
+ // Response contains results.
+ else if (result_json.headings != null) {
+ gantryAjaxRenderResults(result_json);
+ $j.address.value('/');
+ }
+ else {
+ $j.address.value('/');
+ }
+ },
+ };
+
+ // Add any specified callbacks to the options.
+ for (var cb in gantryAjaxFormOptions) {
+ alert(cb);
+ ajaxFormOptions[cb] = gantryAjaxFormOptions[cb];
+ }
+
+ // Handle form error summary.
+ if (json.form.results != null && json.form.show_error_summary == 1) {
+ if (json.form.results.msgs.group_by_field == 1) {
+ var invalid = false;
+ var missing = false;
+
+ // Check for invalid.
+ for (var i in json.form.results.invalid) {
+ invalid = true;
+ }
+
+ // Check for missing.
+ for (var i in json.form.results.missing) {
+ missing = true;
+ }
+
+ // If there are any invalid or missing fields...
+ if (invalid || missing) {
+ var jep = $j('<p class="missing" style="color: red"></p>');
+
+ for (var i = 0; i < json.form.fields.length; i++) {
+ var field = json.form.fields[i];
+
+ if (json.form.results.invalid[
field.name] ||
json.form.results.missing[
field.name]) {
+ jep.append(
+ $j.sprintf(
+ '<b>%s:</b> %s<br />',
+ field.label,
+ json.form.results.msgs[
field.name]
+ )
+ );
+ }
+ }
+
+ jform.prepend(jep);
+ }
+ }
+ }
+
+ // Init cfsgroup.
+ cfsgroup.legend = 'gantry-default';
+ cfsgroup.fields = [];
+
+ // Output any message contained in the form.
+ if (json.form.message != null) {
+ jform.find('div').append(
+ $j.sprintf(
+ '<div class="msg">%s</div>',
+ json.form.message
+ )
+ );
+ }
+
+ if (json.form.fields != null) {
+ // Foreach over the fields and add them to the fieldset.
+ for (var i = 0; i < json.form.fields.length; i++) {
+ var field = json.form.fields[i];
+
+ if (field.fieldset != null && field.fieldset != cfsgroup.legend) {
+ if (cfsgroup.fields.length > 0) {
+ fieldsets.push(cfsgroup);
+ }
+
+ cfsgroup = {};
+ cfsgroup.fields = [];
+ cfsgroup.legend = field.fieldset;
+ cfsgroup.fields.push(field);
+ }
+ else {
+ cfsgroup.fields.push(field);
+ }
+ }
+
+ // Add last fieldset.
+ fieldsets.push(cfsgroup);
+
+ // Loop over the fieldsets created above.
+ for (var i = 0; i < fieldsets.length; i++) {
+ var fieldset = fieldsets[i];
+ var jfs = $j(
+ $j.sprintf(
+ '<fieldset class="%s"></fieldset>',
+ fieldset.legend.replace(/ /g, '').replace("'", '').toLowerCase()
+ )
+ );
+
+ // Loop over the fields in the fieldset.
+ for (var f = 0; f < fieldset.fields.length; f++) {
+ var field = fieldset.fields[f];
+ var jlabel = $j(
+ $j.sprintf(
+ '<label id="%s_label">%s%s</label>',
+
field.name,
+ field.label,
+ (field.optional != 1 ? ' *' : '')
+ )
+ );
+
+ // Determine label class based on if the field is optional or not.
+ if (field.optional != 1) {
+ jlabel.addClass('required');
+ }
+
+ // Set 'for' attribute for all types except display and html.
+ if (field.type != 'display' && field.type != 'html') {
+ jlabel.attr('for',
field.name);
+ }
+
+ // Add the label to the fieldset unless the field type is hidden.
+ if (field.type != 'hidden') {
+ jfs.append(jlabel);
+ }
+
+ // Handle file type fields.
+ if (field.type == 'file') {
+ // Add the file input to the fieldset.
+ jfs.append(
+ $j.sprintf(
+ '<input type="file" name="%s" />',
+
field.name
+ )
+ );
+ }
+ // Handle display type fields.
+ else if (field.type == 'display') {
+ var fieldDisplay;
+
+ // Get the display value from either the row or the default value.
+ if (json.form.row != null && json.form.row[
field.name] != null) {
+ fieldDisplay = json.form.row[
field.name];
+ }
+ else {
+ fieldDisplay = field.default_value;
+ }
+
+ // Add the display div to the fieldset.
+ jfs.append(
+ $j.sprintf(
+ '<div class="display">%s</div>',
+ fieldDisplay
+ )
+ );
+ }
+ // Handle textarea type fields.
+ else if (field.type == 'textarea') {
+ var val = '';
+ var jtextarea;
+
+ // Determine val.
+ if (
field.name in json.params) {
+ val = json.params[
field.name];
+ }
+ else if (json.form.row != null) {
+ val = json.form.row[
field.name];
+ }
+ else {
+ val = field.default_value;
+ }
+
+ // Create textarea.
+ jtextarea = $j(
+ $j.sprintf(
+ '<%s name="%s" id="%s">%s</%s>',
+ field.type,
+
field.name,
+
field.name,
+ val,
+ field.type
+ )
+ );
+
+ // Determine field class if any.
+ if (field['class'] != null) {
+ jtextarea.addClass(field['class']);
+ }
+
+ // Determine field rows if any.
+ if (field['rows'] != null) {
+ jtextarea.attr('rows', field['rows']);
+ }
+
+ // Determine field cols if any.
+ if (field['cols'] != null) {
+ jtextarea.attr('cols', field['cols']);
+ }
+
+ // Determine if disabled.
+ if (field['disabled'] == 1) {
+ jtextarea.attr('disabled', 'disabled');
+ }
+
+ // Add textarea field.
+ jfs.append(jtextarea);
+ }
+ // Handle select and multiple select type fields.
+ else if (field.type == 'select' || field.type == 'multiple_select') {
+ var selected = {};
+ var jselect = $j(
+ $j.sprintf(
+ '<select name="%s" id="%s"></select>',
+
field.name,
+
field.name
+ )
+ );
+
+ // Determine if any options are selected.
+ if (json.params[
field.name] != null) {
+ if (json.params[
field.name] instanceof Array) {
+ for (var p = 0; p < json.params[
field.name].length; p++) {
+ selected[json.params[
field.name][p]] = true;
+ }
+ }
+ else {
+ selected[json.params[
field.name]] = true;
+ }
+ }
+ else if (json.form.row != null && json.form.row[
field.name] != null) {
+ selected[json.form.row[
field.name]] = true;
+ }
+ else {
+ selected[field.default_value] = true;
+ }
+
+ // Determine field class if any.
+ if (field['class'] != null) {
+ jselect.addClass(field['class']);
+ }
+
+ // Determine field size if any.
+ if (field['display_size'] != null) {
+ jselect.attr('size', field['display_size']);
+ }
+
+ // Determine if disabled.
+ if (field['disabled'] == 1) {
+ jselect.attr('disabled', 'disabled');
+ }
+
+ // Determine on change if any.
+ if (field['onchange'] != null) {
+ jselect.attr('onchange', field['onchange']);
+ }
+
+ // Determine if this is a multi select.
+ if (field['type'] == 'multiple_select') {
+ jselect.attr('multiple', 'multiple');
+ }
+
+ // Add options to the select list.
+ for (var opt = 0; opt < field.options.length; opt++) {
+ var option = field.options[opt];
+ var joption = $j(
+ $j.sprintf(
+ '<option value="%s">%s</option>',
+ option.value,
+ option.label
+ )
+ );
+
+ // Determine if current option should be selected.
+ if (selected[option.value]) {
+ joption.attr('selected', 'selected');
+ }
+
+ // Add option to select element.
+ jselect.append(joption);
+ }
+
+ // Add select to fieldset.
+ jfs.append(jselect);
+ }
+ else if (field.type == 'html') {
+ jfs.append(field.html);
+ }
+ // Handle all other type fields.
+ else {
+ var val;
+ var jinput;
+
+ // Determine val.
+ if (
field.name in json.params) {
+ val = json.params[
field.name];
+ }
+ else if (json.form.row != null) {
+ val = json.form.row[
field.name];
+ }
+ else if (field.default_value != null) {
+ val = field.default_value;
+ }
+
+ // Create input.
+ jinput = $j(
+ $j.sprintf(
+ '<input type="%s" name="%s" id="%s" />',
+ field.type,
+
field.name,
+
field.name
+ )
+ );
+
+ // Determine field class if any.
+ if (field['class'] != null) {
+ jinput.addClass(field['class']);
+ }
+
+ // Determine field size if any.
+ if (field['display_size'] != null) {
+ jinput.attr('size', field['display_size']);
+ }
+
+ // Determine field value if any.
+ if (val != null) {
+ jinput.attr('value', val);
+ }
+
+ // Determine if disabled.
+ if (field['disabled'] == 1) {
+ jinput.attr('disabled', 'disabled');
+ }
+
+ // Add input field.
+ jfs.append(jinput);
+ }
+
+ if (field.type != 'hidden') {
+ // Add field hint.
+ jfs.append(
+ $j.sprintf(
+ '<span id="%s_hint" class="hint">%s</span>',
+
field.name,
+ (field.hint != null ? field.hint : '')
+ )
+ );
+
+ // If we have results...
+ if (json.form.results != null) {
+ // Display invalid span if necessary.
+ if (json.form.results.invalid[
field.name] != null) {
+ jfs.append(' <span class="invalid">invalid</span>');
+ }
+
+ // Display missing span if necessary.
+ if (json.form.results.missing[
field.name] != null) {
+ jfs.append(' <span class="missing">required</span>');
+ }
+ }
+
+ jfs.append(
+ $j.sprintf(
+ '<br id="%s_br" style="clear: both" />',
+
field.name
+ )
+ );
+ }
+ }
+
+ // Add the legend unless its the gantry default legend.
+ if (fieldset.legend != 'gantry-default') {
+ jfs.prepend(
+ $j.sprintf(
+ '<legend>%s</legend>',
+ fieldset.legend
+ )
+ );
+ }
+
+ // Add the fieldset to the form.
+ jform.find('div').append(jfs);
+ }
+ }
+
+ // Output actions box if we have a submit or cancel action.
+ if (json.form.no_submit != 1 || json.form.no_cancel != 1) {
+ var jactionsDiv = $j(
+ $j.sprintf(
+ '<div class="form-box actions"></div>'
+ )
+ )
+
+ // Add additional form class if necessary.
+ if (json.form['class'] != null) {
+ jactionsDiv.addClass(json.form['class']);
+ }
+
+
+ // Add submit button.
+ if (json.form.no_submit != 1) {
+ jactionsDiv.append(
+ $j.sprintf(
+ '<input type="submit" name="submit_button" id="submit_button"
value="%s" />',
+ (json.form.submit_button_label ?
json.form.submit_button_label : 'Submit')
+ )
+ );
+ }
+
+ // Add submit and add another button.
+ if (json.form.submit_and_add_another == 1) {
+ var value = (
+ json.form.submit_and_add_another_label
+ ? json.form.submit_and_add_another_label
+ : 'Submit & Add Another'
+ );
+
+ jactionsDiv.append(
+ $j.sprintf(
+ '<input type="submit" name="submit_add_another" ' +
+ 'id="submit_add_another" value="%s" />',
+ (
+ json.form.submit_and_add_another_label
+ ? json.form.submit_and_add_another_label
+ : 'Submit & Add Another'
+ )
+ )
+ );
+ }
+
+ // Add cancel button.
+ if (json.form.no_cancel != 1) {
+ var value = (
+ json.form.cancel_button_label
+ ? json.form.cancel_button_label
+ : 'Cancel'
+ );
+
+ jactionsDiv.append(
+ $j.sprintf(
+ '<input type="submit" name="cancel" id="cancel" value="%s" />',
+ (
+ json.form.cancel_button_label
+ ? json.form.cancel_button_label
+ : 'Cancel'
+ )
+ )
+ );
+ }
+
+ // Add actions_div to form.
+ jform.append(jactionsDiv);
+ }
+
+ // Output form header unless its not wanted.
+ if (json.form.nohead != 1) {
+ jform.find('div:first').prepend(
+ $j.sprintf(
+ '<h4 class="heading">%s</h4>',
+ json.title
+ )
+ );
+ }
+
+ // Add ajax to form.
+ jform.ajaxForm(ajaxFormOptions);
+
+ // Handle inline forms.
+ if (formType == 'inline') {
+ $j('#content').html('');
+ $j('#content').prepend(jform);
+ }
+ // Handle blockUI popup forms.
+ else if (formType == 'bui') {
+ var offset = $j("#results").offset();
+ var top = 140;
+ var left = 150;
+ var buiPopup = $j(
+ $j.sprintf(
+ '<div class="bui-popup">' +
+ '<div class="bui-header">' +
+ '<div class="heading">%s</div>' +
+ '<div class="bui-close"></div>' +
+ '<div style="clear: both;"></div>' +
+ '</div>' +
+ '<div class="bui-body"></div>' +
+ '<div class="bui-footer"></div>' +
+ '</div>',
+ json.title
+ )
+ );
+
+ // Add form to body.
+ buiPopup.find('.bui-body').prepend(jform);
+
+ // Add click handler to close button to go back.
+ buiPopup.find('.bui-close').click( function() {
+ history.go(-1);
+ return false;
+ });
+
+ // Add click handler to cancel button to go back.
+ buiPopup.find('.form-box.actions>input[id=cancel]').click(
function() {
+ history.go(-1);
+ return false;
+ });
+
+ // Call blockUi to display message.
+ $j.blockUI( {
+ message: buiPopup,
+ css: gantryAjaxFormBuiCss
+ });
+
+ blocking = true;
+ }
+}
+
+/**
+*
+* function: gantryAjaxDisplayForm(ajaxLocation, formType, errorType)
+*
+* parameters: ajaxLocation, formType, errorType
+*
+* description: This function queries the specfied ajaxLocation for a json
+* representation of a gantry form. If no error occurs retrieving
+* the form then it will call gantryAjaxRenderForm to handle
+* the actual rendering of the form. Their are two supported form
+* types. bui will use the blockUI jquery plugin to create a popup
+* form. inline will output the form to the content section of the page.
+* If errorType is set to bui, then any errors that occur while
retrieving
+* the form will be displayed using a popup windows created created using
+* the jquery blockUI plugin. If not specified, it will create an alert
+* window to display errors.
+*
+*/
+function gantryAjaxDisplayForm (ajaxLocation, formType, errorType) {
+ // Put error handler in place for json requests returning non 200
responses.
+ $j.ajaxSetup({"error": function(XMLHttpRequest,textStatus, errorThrown) {
+ var json = eval('(' + XMLHttpRequest.responseText + ')');
+
+ if (errorType = 'bui') {
+ var jerror = $j(
+ $j.sprintf(
+ '<div id="error">' +
+ '<div>An error has occured:</div>' +
+ '<div id="error_msg">%s</div>' +
+ '<div id="error_continue">Continue</div>' +
+ '</div>',
+ json.error
+ )
+ );
+
+ // Add click handler for continue button.
+ jerror.find('#error_continue').click( function() {
+ history.go(-1);
+ $j.unblockUI();
+ return false;
+ });
+
+ // Create a modal dialog to present the error.
+ $j.blockUI( {
+ message: jerror,
+ css: gantryAjaxErrorFormBuiCss
+ });
+ }
+ else {
+ alert(json.error);
+ }
+ }});
+
+ // Make get json request.
+ $j.getJSON(
+ ajaxLocation,
+ function (json) {
+ if (json.error) {
+ if (errorType = 'bui') {
+ var jerror = $j(
+ $j.sprintf(
+ '<div id="error">' +
+ '<div>An error has occured:</div>' +
+ '<div id="error_msg">%s</div>' +
+ '<div id="error_continue">Continue</div>' +
+ '</div>',
+ json.error
+ )
+ );
+
+ // Add click handler for continue button.
+ jerror.find('#error_continue').click( function() {
+ history.go(-1);
+ $j.unblockUI();
+ return false;
+ });
+
+ // Create a modal dialog to present the error.
+ $j.blockUI( {
+ message: jerror,
+ css: gantryAjaxErrorFormBuiCss
+ });
+ }
+ else {
+ alert(json.error);
+ }
+ }
+ else {
+ // Set form action to ajaxLocation if none was specified.
+ if (json.form.action == null) {
+ json.form.action = ajaxLocation;
+ }
+
+ // Render the form.
+ gantryAjaxRenderForm(formType, json);
+ }
+ }
+ );
+}
=======================================
--- /dev/null
+++ /trunk/root/js/ajaxResults.js Mon Apr 4 09:08:43 2011
@@ -0,0 +1,373 @@
+/**
+ *
+ * Gantry: ajaxResults.js
+ *
+ * Contains functions to display / render gantry results using ajax.
+ *
+ * Author John Weigel [John.Weigel at knology dot com]
+ * Copyright (C) 2011 Knology
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <
http://www.gnu.org/licenses/>.
+ *
+ */
+
+var $j = jQuery.noConflict();
+
+/**
+*
+* function: buildOptions(jobj, options)
+*
+* parameters: jobj, options
+*
+* description: This function will build the jquery options object for
gantry
+* result tables. This includes both pre header, header, and row
+* options.
+*/
+function buildOptions (jobj, options) {
+ // Loop over all the header options.
+ for (var i = 0; i < options.length; i++) {
+ var option = options[i];
+
+ // Output left bracket on first iteration.
+ if (i == 0) {
+ jobj.append('[ ');
+ }
+
+ // If a link was specfied for the option...
+ if (option.link != null || option.rel != null) {
+ var anchor = $j(
+ $j.sprintf(
+ '<a>%s</a>',
+ option.text
+ )
+ );
+
+ // Add href to anchor.
+ if (option.link != null) {
+ anchor.attr('href', option.link);
+ }
+
+ // Add rel attribute to anchor.
+ if (option.rel) {
+ anchor.attr('rel', option.rel);
+ }
+
+ // Add anchor to jquery object.
+ jobj.append(anchor);
+ }
+ // Add the option text without any link.
+ else {
+ jobj.append(option.text);
+ }
+
+ // Add a separator if its not the last option.
+ if (i != options.length - 1) {
+ jobj.append(' | ');
+ }
+ // Add closing bracket after last option.
+ else {
+ jobj.append(' ]');
+ }
+ }
+}
+
+/**
+*
+* function: gantryAjaxRenderResults(json)
+*
+* parameters: json
+*
+* description: Given a json representation of a gantry result table,
+* this method will render the results to the content section
+* of the page.
+*/
+function gantryAjaxRenderResults (json) {
+ var $j = jQuery.noConflict();
+ var resultsBox = $j(
+ $j.sprintf(
+ '<div class="box">' +
+ '<table id="%s" class="%s">' +
+ '<thead>' +
+ '</thead>' +
+ '<tbody>' +
+ '</tbody>' +
+ '</table>' +
+ '</div>',
+ (
json.id ?
json.id : 'results'),
+ 'results ' + ( json['class'] != null ? json['class'] : '' )
+ )
+ );
+ var colspan = ( json.headings != null ? json.headings.length : 0 );
+ var altBG = 1;
+ var hdrRow;
+
+ // Add 1 to colspan if there are options.
+ if (json.no_options != 1) {
+ colspan += 1;
+ }
+
+ // If pre headings are not disabled...
+ if (json.no_pre_headings != 1) {
+ var preheadingRow = $j('<tr class="pre-hdr-row"></tr>');
+ var hidePreHeadings = ( json.params != null &&
json.params.hide_preheadings == 1 ? 'true' : 'false' );
+ var phocolspan = colspan;
+
+ // Check if there are table preheadings to output.
+ if (json.pre_headings != null && json.pre_headings.length > 0 && !
hidePreHeadings) {
+ var preHeadingClass = '';
+
+ for (var i = 0; i < json.pre_headings.length; i++) {
+ var preHeading = json.pre_headings[i];
+ var colspanAttr = '';
+ var preHeadingText;
+ var td;
+
+ // Pre heading is an object.
+ if (typeof preHeading == 'object') {
+ if (preHeading.colspan != null && preHeading.colspan > 0) {
+ colspanAttr = 'colspan="' + preHeading.colspan + '"';
+ phocolspan -= preHeading.colspan;
+ }
+
+ preHeadingText = preHeading.text;
+ preHeadingClass = preHeading['class'];
+ }
+ // Pre heading is just text.
+ else {
+ preHeadingText = preHeading;
+ }
+
+ // Create pre heading jquery td object with the correct
+ // class, colspan, and text.
+ td = $j(
+ $j.sprintf(
+ '<td class="%s" %s>' +
+ '%s' +
+ '</td>',
+ 'hdr ' + preHeading['class'],
+ colspanAttr,
+ preHeadingText
+ )
+ );
+
+ preHeadingRow.append(td);
+ }
+
+ // Add options if there are any.
+ if (json.pre_header_options.length > 0) {
+ var tdOpt = $j('<td class="rhdr"></td>');
+
+ // Add additional class if it exists.
+ if (json.pre_header_options['class']) {
+ tdOpt.addClass(json.pre_header_options['class']);
+ }
+
+ // Build the options.
+ buildOptions(tdOpt, json.pre_header_options);
+
+ // Add options cell to header row.
+ preHeadingRow.append(tdOpt);
+ }
+ }
+ // Add empty preheading row.
+ else {
+ preheadingRow.append(
+ $j.sprintf(
+ '<td class="hdr" colspan="%s"> </td>',
+ colspan
+ )
+ );
+ }
+
+ resultsBox.find('thead').append(preheadingRow);
+ }
+
+ // Create header row.
+ hdrRow = $j('<tr class="hdr-row"></td>');
+
+ // Add columns to header row.
+ for (var i = 0; i < json.headings.length; i++) {
+ var heading = json.headings[i];
+ var th = $j('<th class="hdr"></th>');
+
+ // heading is an object...
+ if (typeof heading == 'object') {
+ // Add additional class.
+ if (heading['class'] != null) {
+ th.addClass(heading['class']);
+ }
+
+ // Add title.
+ if (heading['title'] != null) {
+ th.attr('title', heading['title']);
+ }
+
+ // Add text.
+ th.html(heading['text']);
+ }
+ // heading is just text...
+ else {
+ th.html(heading);
+ }
+
+ // Add th to header row.
+ hdrRow.append(th);
+ }
+
+ // Add header options unless no_options is set.
+ if (json.no_options != 1) {
+ var thOpt = $j('<th class="rhdr"></th>');
+
+ // Add additional class if it exists.
+ if (json.header_options['class']) {
+ thOpt.addClass(json.header_options['class']);
+ }
+
+ // Build the options.
+ buildOptions(thOpt, json.header_options);
+
+ // Add options cell to header row.
+ hdrRow.append(thOpt);
+ }
+
+ // Add header row.
+ resultsBox.find('thead').append(hdrRow);
+
+ if (json.rows != null && json.rows.length > 0) {
+ // Foreach over the table rows...
+ for ( var i = 0; i < json.rows.length; i++) {
+ var row = json.rows[i];
+ var tr = $j('<tr class="results-row"></tr>');
+
+ // Add id to row.
+ if (
row.id != null) {
+ tr.attr('id',
row.id);
+ }
+
+ // Unless the row class matches (warning|highlighted)-row then add
+ // the standard alt-bgx class.
+ if (row['class'] == null || (row['class'] != null && !
row['class'].match(/(warning|highlighted)-row/i))) {
+ tr.addClass('alt-bg' + altBG);
+ }
+
+ // Add any additional class.
+ if (row['class'] != null) {
+ tr.addClass(row['class']);
+ }
+
+ // Foreach over the data items in the row...
+ for ( var e = 0; e < row.data.length; e++) {
+ var elem = row.data[e];
+ var td = $j('<td class="dta"></td>');
+
+ // If we have an object...
+ if (typeof elem == 'object') {
+ // Add id to td if it exists.
+ if (elem['class'] != null) {
+ td.attr('id', elem['class']);
+ }
+
+ // Add additional class if it exists.
+ if (elem['class'] != null) {
+ td.addClass(elem['class']);
+ }
+
+ // Add style if it exists.
+ if (elem['td_style'] != null) {
+ var style = elem['td_style'];
+
+ style.replace(/^style="|"$/ig);
+
+ td.attr('style', style);
+ }
+
+ // Add colspan if it exists.
+ if (elem['colspan'] != null) {
+ td.attr('colspan', elem['colspan']);
+ }
+
+ // Add element text.
+ td.html(elem['text']);
+ }
+ // elem is not an object so just add the text.
+ else {
+ td.html(elem);
+ }
+
+ // Add last class if this is the last row in the table.
+ if (i == json.rows.length - 1) {
+ td.addClass('last');
+ }
+
+ // Add the column to the row.
+ tr.append(td);
+ }
+
+ // Add row options if necessary.
+ if (json.no_options != 1) {
+ var tdOpt = $j('<td class="rdta"></td>');
+ var optClasses = [];
+
+ // Add id if it exists.
+ if (row.options['id']) {
+ tdOpt.attr('id', row.options['id']);
+ }
+
+ // Add additional class if it exists.
+ if (row.options['class']) {
+ tdOpt.addClass(row.options['class']);
+ }
+
+ // Add last class if this is the last row in the table.
+ if (i == json.rows.length - 1) {
+ tdOpt.addClass('last');
+ }
+
+ // Add style if it exists.
+ if (row.options['td_style'] != null) {
+ var style = row.options['td_style'];
+
+ style.replace(/^style="|"$/ig);
+
+ tdOpt.attr('style', style);
+ }
+
+ // Build the options.
+ buildOptions(tdOpt, row.options);
+
+ // Add options cell to header row.
+ tr.append(tdOpt);
+ }
+
+ // Add row to table body.
+ resultsBox.find('tbody').append(tr);
+
+ // Switch bg color.
+ altBG = ( altBG == 1 ? 0 : 1 );
+ }
+ }
+ // No row data found...
+ else {
+ resultsBox.find('tbody').append(
+ $j.sprintf(
+ '<tr class="no-data"><td colspan="%s">No Data</td></tr>',
+ colspan
+ )
+ );
+ }
+
+ // Clear content and add resultsBox.
+ $j('#content').html('');
+ $j('#content').prepend(resultsBox);
+}
=======================================
--- /dev/null
+++ /trunk/root/js/jquery-1.4.3.min.js Mon Apr 4 09:08:43 2011
@@ -0,0 +1,166 @@
+/*!
+ * jQuery JavaScript Library v1.4.3
+ *
http://jquery.com/
+ *
+ * Copyright 2010, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ *
http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ *
http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Thu Oct 14 23:10:06 2010 -0400
+ */
+(function(E,A){function U(){return false}function ba(){return
true}function ja(a,b,d){d[0].type=a;return
c.event.handle.apply(b,d)}function Ga(a){var
b,d,e=[],f=[],h,k,l,n,s,v,B,D;k=c.data(this,this.nodeType?"events":"__events__");if(typeof
k==="function")k=k.events;if(!(a.liveFired===this||!k||!k.live||
a.button&&a.type==="click")){if(a.namespace)D=RegExp("(^|
\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|
$)");a.liveFired=this;var
H=k.live.slice(0);for(n=0;n<H.length;n++){k=H[n];k.origType.replace(X,
+"")===a.type?f.push(k.selector):H.splice(n--,1)}f=c(a.target).closest(f,a.currentTarget);s=0;for(v=f.length;s<v;s++){B=f[s];for(n=0;n<H.length;n++){k=H[n];if(B.selector===k.selector&&(!D|
|
D.test(k.namespace))){l=B.elem;h=null;if(k.preType==="mouseenter"||
k.preType==="mouseleave"){a.type=k.preType;h=c(a.relatedTarget).closest(k.selector)[0]}if(!h|
|
h!==l)e.push({elem:l,handleObj:k,level:B.level})}}}s=0;for(v=e.length;s<v;s++){f=e[s];if(d&&f.level>d)break;a.currentTarget=f.elem;a.data=f.handleObj.data;
+a.handleObj=f.handleObj;D=f.handleObj.origHandler.apply(f.elem,arguments);if(D===false|
|
a.isPropagationStopped()){d=f.level;if(D===false)b=false}}return
b}}function
Y(a,b){return(a&&a!=="*"?a+".":"")+b.replace(Ha,"`").replace(Ia,"&")}function
ka(a,b,d){if(c.isFunction(b))return
c.grep(a,function(f,h){return!!b.call(f,h,f)===d});else
if(b.nodeType)return c.grep(a,function(f){return f===b===d});else if(typeof
b==="string"){var e=c.grep(a,function(f){return
f.nodeType===1});if(Ja.test(b))return c.filter(b,
+e,!d);else b=c.filter(b,e)}return c.grep(a,function(f){return
c.inArray(f,b)>=0===d})}function la(a,b){var
d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var
e=c.data(a[d++]),f=c.data(this,e);if(e=e&&e.events){delete
f.handle;f.events={};for(var h in e)for(var k in
e[h])c.event.add(this,h,e[h][k],e[h][k].data)}}})}function
Ka(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text|
|b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}
+function ma(a,b,d){var
e=b==="width"?a.offsetWidth:a.offsetHeight;if(d==="border")return
e;c.each(b==="width"?La:Ma,function(){d||
(e-=parseFloat(c.css(a,"padding"+this))||
0);if(d==="margin")e+=parseFloat(c.css(a,"margin"+this))||0;else
e-=parseFloat(c.css(a,"border"+this+"Width"))||0});return e}function
ca(a,b,d,e){if(c.isArray(b)&&b.length)c.each(b,function(f,h){d||
Na.test(a)?e(a,h):ca(a+"["+(typeof h==="object"||
c.isArray(h)?f:"")+"]",h,d,e)});else if(!d&&b!=null&&typeof
b==="object")c.isEmptyObject(b)?
+e(a,""):c.each(b,function(f,h){ca(a+"["+f+"]",h,d,e)});else
e(a,b)}function S(a,b){var
d={};c.each(na.concat.apply([],na.slice(0,b)),function(){d[this]=a});return
d}function oa(a){if(!da[a]){var
b=c("<"+a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"|
|d==="")d="block";da[a]=d}return da[a]}function ea(a){return
c.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var
u=E.document,c=function(){function
a(){if(!b.isReady){try{u.documentElement.doScroll("left")}catch(i){setTimeout(a,
+1);return}b.ready()}}var b=function(i,r){return new
b.fn.init(i,r)},d=E.jQuery,e=E.$,f,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|
#([\w\-]+)$)/,k=/\S/,l=/^\s+/,n=/\s+$/,s=/\W/,v=/\d/,B=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,D=/^[\],:{}\s]*$/,H=/\\(?:["\\\/bfnrt]|
u[0-9a-fA-F]{4})/g,w=/"[^"\\\n\r]*"|true|false|null|
-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,G=/(?:^|:|,)(?:\s*\[)+/g,M=/(webkit)[
\/]([\w.]+)/,g=/(opera)(?:.*version)?[ \/]([\w.]+)/,j=/(msie)
([\w.]+)/,o=/(mozilla)(?:.*? rv:([\w.]+))?/,m=navigator.userAgent,p=false,
+q=[],t,x=Object.prototype.toString,C=Object.prototype.hasOwnProperty,P=Array.prototype.push,N=Array.prototype.slice,R=String.prototype.trim,Q=Array.prototype.indexOf,L={};b.fn=b.prototype={init:function(i,r){var
y,z,F;if(!i)return
this;if(i.nodeType){this.context=this[0]=i;this.length=1;return
this}if(i==="body"&&!r&&u.body){this.context=u;this[0]=u.body;this.selector="body";this.length=1;return
this}if(typeof
i==="string")if((y=h.exec(i))&&(y[1]|
|!r))if(y[1]){F=r?r.ownerDocument||
r:u;if(z=B.exec(i))if(b.isPlainObject(r)){i=
+[u.createElement(z[1])];b.fn.attr.call(i,r,true)}else
i=[F.createElement(z[1])];else{z=b.buildFragment([y[1]],[F]);i=(z.cacheable?z.fragment.cloneNode(true):z.fragment).childNodes}return
b.merge(this,i)}else{if((z=u.getElementById(y[2]))&&z.parentNode){if(
z.id!==y[2])return
f.find(i);this.length=1;this[0]=z}this.context=u;this.selector=i;return
this}else
if(!r&&!s.test(i)){this.selector=i;this.context=u;i=u.getElementsByTagName(i);return
b.merge(this,i)}else return!r||r.jquery?(r||f).find(i):b(r).find(i);
+else if(b.isFunction(i))return
f.ready(i);if(i.selector!==A){this.selector=i.selector;this.context=i.context}return
b.makeArray(i,this)},selector:"",jquery:"1.4.3",length:0,size:function(){return
this.length},toArray:function(){return
N.call(this,0)},get:function(i){return
i==null?this.toArray():i<0?this.slice(i)[0]:this[i]},pushStack:function(i,r,y){var
z=b();b.isArray(i)?P.apply(z,i):b.merge(z,i);z.prevObject=this;z.context=this.context;if(r==="find")z.selector=this.selector+(this.selector?" ":
+"")+y;else if(r)z.selector=this.selector+"."+r+"("+y+")";return
z},each:function(i,r){return
b.each(this,i,r)},ready:function(i){b.bindReady();if(b.isReady)i.call(u,b);else
q&&q.push(i);return this},eq:function(i){return
i===-1?this.slice(i):this.slice(i,+i+1)},first:function(){return
this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return
this.pushStack(N.apply(this,arguments),"slice",N.call(arguments).join(","))},map:function(i){return
this.pushStack(b.map(this,function(r,y){return i.call(r,
+y,r)}))},end:function(){return this.prevObject||
b(null)},push:P,sort:[].sort,splice:[].splice};b.fn.init.prototype=b.fn;b.extend=b.fn.extend=function(){var
i=arguments[0]||{},r=1,y=arguments.length,z=false,F,I,K,J,fa;if(typeof
i==="boolean"){z=i;i=arguments[1]||{};r=2}if(typeof
i!=="object"&&!b.isFunction(i))i={};if(y===r){i=this;--r}for(;r<y;r++)if((F=arguments[r])!=null)for(I
in F){K=i[I];J=F[I];if(i!==J)if(z&&J&&(b.isPlainObject(J)||
(fa=b.isArray(J)))){if(fa){fa=false;clone=K&&b.isArray(K)?K:[]}else clone=
+K&&b.isPlainObject(K)?K:{};i[I]=b.extend(z,clone,J)}else
if(J!==A)i[I]=J}return
i};b.extend({noConflict:function(i){E.$=e;if(i)E.jQuery=d;return
b},isReady:false,readyWait:1,ready:function(i){i===true&&b.readyWait--;if(!b.readyWait|
|i!==true&&!b.isReady){if(!u.body)return
setTimeout(b.ready,1);b.isReady=true;if(!(i!==true&&--b.readyWait>0)){if(q){for(var
r=0;i=q[r++];)i.call(u,b);q=null}b.fn.triggerHandler&&b(u).triggerHandler("ready")}}},bindReady:function(){if(!p){p=true;if(u.readyState==="complete")return
setTimeout(b.ready,
+1);if(u.addEventListener){u.addEventListener("DOMContentLoaded",t,false);E.addEventListener("load",b.ready,false)}else
if(u.attachEvent){u.attachEvent("onreadystatechange",t);E.attachEvent("onload",b.ready);var
i=false;try{i=E.frameElement==null}catch(r){}u.documentElement.doScroll&&i&&a()}}},isFunction:function(i){return
b.type(i)==="function"},isArray:Array.isArray|
|function(i){return
b.type(i)==="array"},isWindow:function(i){return i&&typeof
i==="object"&&"setInterval"in i},isNaN:function(i){return i==
+null||!v.test(i)||isNaN(i)},type:function(i){return
i==null?String(i):L[x.call(i)]||"object"},isPlainObject:function(i){if(!i||
b.type(i)!=="object"||i.nodeType||b.isWindow(i))return
false;if(i.constructor&&!C.call(i,"constructor")&&!C.call(i.constructor.prototype,"isPrototypeOf"))return
false;for(var r in i);return r===A||
C.call(i,r)},isEmptyObject:function(i){for(var r in i)return false;return
true},error:function(i){throw i;},parseJSON:function(i){if(typeof
i!=="string"||!i)return null;i=b.trim(i);
+if(D.test(i.replace(H,"@").replace(w,"]").replace(G,"")))return
E.JSON&&E.JSON.parse?E.JSON.parse(i):(new Function("return "+i))();else
b.error("Invalid
JSON: "+i)},noop:function(){},globalEval:function(i){if(i&&k.test(i)){var
r=u.getElementsByTagName("head")[0]||
u.documentElement,y=u.createElement("script");y.type="text/javascript";if(b.support.scriptEval)y.appendChild(u.createTextNode(i));else
y.text=i;r.insertBefore(y,r.firstChild);r.removeChild(y)}},nodeName:function(i,r){return
i.nodeName&&i.nodeName.toUpperCase()===
+r.toUpperCase()},each:function(i,r,y){var z,F=0,I=i.length,K=I===A||
b.isFunction(i);if(y)if(K)for(z in i){if(r.apply(i[z],y)===false)break}else
for(;F<I;){if(r.apply(i[F++],y)===false)break}else if(K)for(z in
i){if(r.call(i[z],z,i[z])===false)break}else
for(y=i[0];F<I&&r.call(y,F,y)!==false;y=i[++F]);return
i},trim:R?function(i){return i==null?"":R.call(i)}:function(i){return
i==null?"":i.toString().replace(l,"").replace(n,"")},makeArray:function(i,r){var
y=r||[];if(i!=null){var z=b.type(i);i.length==
+null||z==="string"||z==="function"||z==="regexp"||
b.isWindow(i)?P.call(y,i):b.merge(y,i)}return
y},inArray:function(i,r){if(r.indexOf)return r.indexOf(i);for(var
y=0,z=r.length;y<z;y++)if(r[y]===i)return
y;return-1},merge:function(i,r){var y=i.length,z=0;if(typeof
r.length==="number")for(var F=r.length;z<F;z++)i[y++]=r[z];else
for(;r[z]!==A;)i[y++]=r[z++];i.length=y;return i},grep:function(i,r,y){var
z=[],F;y=!!y;for(var
I=0,K=i.length;I<K;I++){F=!!r(i[I],I);y!==F&&z.push(i[I])}return
z},map:function(i,
+r,y){for(var
z=[],F,I=0,K=i.length;I<K;I++){F=r(i[I],I,y);if(F!=null)z[z.length]=F}return
z.concat.apply([],z)},guid:1,proxy:function(i,r,y){if(arguments.length===2)if(typeof
r==="string"){y=i;i=y[r];r=A}else
if(r&&!b.isFunction(r)){y=r;r=A}if(!r&&i)r=function(){return i.apply(y||
this,arguments)};if(i)r.guid=i.guid=i.guid||r.guid||b.guid++;return
r},access:function(i,r,y,z,F,I){var K=i.length;if(typeof
r==="object"){for(var J in r)b.access(i,J,r[J],z,F,y);return
i}if(y!==A){z=!I&&z&&b.isFunction(y);
+for(J=0;J<K;J++)F(i[J],r,z?y.call(i[J],J,F(i[J],r)):y,I);return i}return
K?F(i[0],r):A},now:function(){return(new
Date).getTime()},uaMatch:function(i){i=i.toLowerCase();i=M.exec(i)||
g.exec(i)||j.exec(i)||i.indexOf("compatible")<0&&o.exec(i)||
[];return{browser:i[1]||"",version:i[2]||"0"}},browser:{}});b.each("Boolean
Number String Function Array Date RegExp
Object".split(" "),function(i,r){L["[object "+r+"]"]=r.toLowerCase()});m=b.uaMatch(m);if(m.browser){b.browser[m.browser]=true;b.browser.version=
+m.version}if(b.browser.webkit)b.browser.safari=true;if(Q)b.inArray=function(i,r){return
Q.call(r,i)};if(!/\s/.test("\u00a0")){l=/^[\s\xA0]+/;n=/[\s\xA0]+$/}f=b(u);if(u.addEventListener)t=function(){u.removeEventListener("DOMContentLoaded",t,false);b.ready()};else
if(u.attachEvent)t=function(){if(u.readyState==="complete"){u.detachEvent("onreadystatechange",t);b.ready()}};return
E.jQuery=E.$=b}();(function(){c.support={};var
a=u.documentElement,b=u.createElement("script"),d=u.createElement("div"),
+e="script"+c.now();d.style.display="none";d.innerHTML="
<link/><table></table><a href='/a'
style='color:red;float:left;opacity:.55;'>a</a><input
type='checkbox'/>";var
f=d.getElementsByTagName("*"),h=d.getElementsByTagName("a")[0],k=u.createElement("select"),l=k.appendChild(u.createElement("option"));if(!(!f|
|!f.length|
|!h)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(h.getAttribute("style")),
+hrefNormalized:h.getAttribute("href")==="/a",opacity:/^0.55$/.test(h.style.opacity),cssFloat:!!h.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:l.selected,optDisabled:false,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableHiddenOffsets:true};k.disabled=true;c.support.optDisabled=!l.disabled;b.type="text/javascript";try{b.appendChild(u.createTextNode("window."+e+"=1;"))}catch(n){}a.insertBefore(b,
+a.firstChild);if(E[e]){c.support.scriptEval=true;delete
E[e]}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function
s(){c.support.noCloneEvent=false;d.detachEvent("onclick",s)});d.cloneNode(true).fireEvent("onclick")}d=u.createElement("div");d.innerHTML="<input
type='radio' name='radiotest'
checked='checked'/>";a=u.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var
s=u.createElement("div");
+s.style.width=s.style.paddingLeft="1px";u.body.appendChild(s);c.boxModel=c.support.boxModel=s.offsetWidth===2;if("zoom"in
s.style){s.style.display="inline";s.style.zoom=1;c.support.inlineBlockNeedsLayout=s.offsetWidth===2;s.style.display="";s.innerHTML="<div
style='width:4px;'></div>";c.support.shrinkWrapBlocks=s.offsetWidth!==2}s.innerHTML="<table><tr><td
style='padding:0;display:none'></td><td>t</td></tr></table>";var
v=s.getElementsByTagName("td");c.support.reliableHiddenOffsets=v[0].offsetHeight===
+0;v[0].style.display="";v[1].style.display="none";c.support.reliableHiddenOffsets=c.support.reliableHiddenOffsets&&v[0].offsetHeight===0;s.innerHTML="";u.body.removeChild(s).style.display="none"});a=function(s){var
v=u.createElement("div");s="on"+s;var
B=s in
v;if(!B){v.setAttribute(s,"return;");B=typeof v[s]==="function"}return
B};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=f=h=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",
+cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var
pa={},Oa=/^(?:\{.*\}|
\[.*\])$/;c.extend({cache:{},uuid:0,expando:"jQuery"+c.now(),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},data:function(a,b,d){if(c.acceptData(a)){a=a==E?pa:a;var
e=a.nodeType,f=e?a[c.expando]:null,h=c.cache;if(!(e&&!f&&typeof
b==="string"&&d===A)){if(e)f|
|(a[c.expando]=f=++c.uuid);else h=a;if(typeof
b==="object")if(e)h[f]=
+c.extend(h[f],b);else c.extend(h,b);else
if(e&&!h[f])h[f]={};a=e?h[f]:h;if(d!==A)a[b]=d;return typeof
b==="string"?a[b]:a}}},removeData:function(a,b){if(c.acceptData(a)){a=a==E?pa:a;var
d=a.nodeType,e=d?a[c.expando]:a,f=c.cache,h=d?f[e]:e;if(b){if(h){delete
h[b];d&&c.isEmptyObject(h)&&c.removeData(a)}}else
if(d&&c.support.deleteExpando)delete a[c.expando];else
if(a.removeAttribute)a.removeAttribute(c.expando);else if(d)delete
f[e];else for(var k in a)delete
a[k]}},acceptData:function(a){if(a.nodeName){var b=
+c.noData[a.nodeName.toLowerCase()];if(b)return!(b===true||
a.getAttribute("classid")!==b)}return
true}});c.fn.extend({data:function(a,b){if(typeof a==="undefined")return
this.length?c.data(this[0]):null;else if(typeof a==="object")return
this.each(function(){c.data(this,a)});var
d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===A){var
e=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(e===A&&this.length){e=c.data(this[0],a);if(e===A&&this[0].nodeType===1){e=this[0].getAttribute("data-"+a);if(typeof
e===
+"string")try{e=e==="true"?true:e==="false"?false:e==="null"?null:!c.isNaN(e)?parseFloat(e):Oa.test(e)?c.parseJSON(e):e}catch(f){}else
e=A}}return
e===A&&d[1]?this.data(d[0]):e}else return
this.each(function(){var
h=c(this),k=[d[0],b];h.triggerHandler("setData"+d[1]+"!",k);c.data(this,a,b);h.triggerHandler("changeData"+d[1]+"!",k)})},removeData:function(a){return
this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b|
|"fx")+"queue";var e=c.data(a,b);if(!d)return e||
+[];if(!e||c.isArray(d))e=c.data(a,b,c.makeArray(d));else e.push(d);return
e}},dequeue:function(a,b){b=b||"fx";var
d=c.queue(a,b),e=d.shift();if(e==="inprogress")e=d.shift();if(e){b==="fx"&&d.unshift("inprogress");e.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof
a!=="string"){b=a;a="fx"}if(b===A)return c.queue(this[0],a);return
this.each(function(){var
d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return
this.each(function(){c.dequeue(this,
+a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return
this.queue(b,function(){var
d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return
this.queue(a||"fx",[])}});var qa=/[\n\t]/g,ga=/\s+/,Pa=/\r/g,Qa=/^(?:href|
src|style)$/,Ra=/^(?:button|input)$/i,Sa=/^(?:button|input|object|select|
textarea)$/i,Ta=/^a(?:rea)?$/i,ra=/^(?:radio|
checkbox)$/i;c.fn.extend({attr:function(a,b){return
c.access(this,a,b,true,c.attr)},removeAttr:function(a){return
this.each(function(){c.attr(this,
+a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return
this.each(function(s){var
v=c(this);v.addClass(a.call(this,s,v.attr("class")))});if(a&&typeof
a==="string")for(var
b=(a||"").split(ga),d=0,e=this.length;d<e;d++){var
f=this[d];if(f.nodeType===1)if(f.className){for(var
h=" "+f.className+" ",k=f.className,l=0,n=b.length;l<n;l++)if(h.indexOf(" "+b[l]+" ")<0)k+=" "+b[l];f.className=c.trim(k)}else
f.className=a}return
this},removeClass:function(a){if(c.isFunction(a))return
this.each(function(n){var s=
+c(this);s.removeClass(a.call(this,n,s.attr("class")))});if(a&&typeof
a==="string"||a===A)for(var b=(a|
|"").split(ga),d=0,e=this.length;d<e;d++){var
f=this[d];if(f.nodeType===1&&f.className)if(a){for(var
h=(" "+f.className+" ").replace(qa," "),k=0,l=b.length;k<l;k++)h=h.replace(" "+b[k]+" "," ");f.className=c.trim(h)}else
f.className=""}return this},toggleClass:function(a,b){var d=typeof
a,e=typeof b==="boolean";if(c.isFunction(a))return
this.each(function(f){var h=c(this);h.toggleClass(a.call(this,
+f,h.attr("class"),b),b)});return
this.each(function(){if(d==="string")for(var
f,h=0,k=c(this),l=b,n=a.split(ga);f=n[h++];){l=e?l:!k.hasClass(f);k[l?"addClass":"removeClass"](f)}else
if(d==="undefined"||
d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=this.className|
|a===false?"":c.data(this,"__className__")|
|""}})},hasClass:function(a){a=" "+a+" ";for(var
b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(qa," ").indexOf(a)>-1)return
true;return false},
+val:function(a){if(!arguments.length){var
b=this[0];if(b){if(c.nodeName(b,"option")){var
d=b.attributes.value;return!d||
d.specified?b.value:b.text}if(c.nodeName(b,"select")){var
e=b.selectedIndex;d=[];var
f=b.options;b=b.type==="select-one";if(e<0)return null;var
h=b?e:0;for(e=b?e+1:f.length;h<e;h++){var
k=f[h];if(k.selected&&(c.support.optDisabled?!k.disabled:k.getAttribute("disabled")===null)&&(!k.parentNode.disabled|
|!c.nodeName(k.parentNode,"optgroup"))){a=c(k).val();if(b)return
a;d.push(a)}}return d}if(ra.test(b.type)&&
+!c.support.checkOn)return
b.getAttribute("value")===null?"on":b.value;return(b.value|
|"").replace(Pa,"")}return A}var l=c.isFunction(a);return
this.each(function(n){var
s=c(this),v=a;if(this.nodeType===1){if(l)v=a.call(this,n,s.val());if(v==null)v="";else
if(typeof v==="number")v+="";else
if(c.isArray(v))v=c.map(v,function(D){return
D==null?"":D+""});if(c.isArray(v)&&ra.test(this.type))this.checked=c.inArray(s.val(),v)>=0;else
if(c.nodeName(this,"select")){var
B=c.makeArray(v);c("option",this).each(function(){this.selected=
+c.inArray(c(this).val(),B)>=0});if(!B.length)this.selectedIndex=-1}else
this.value=v}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,e){if(!a|
|a.nodeType===3||a.nodeType===8)return A;if(e&&b in c.attrFn)return
c(a)[b](d);e=a.nodeType!==1||!c.isXMLDoc(a);var f=d!==A;b=e&&c.props[b]||
b;if(a.nodeType===1){var h=Qa.test(b);if((b in a||
a[b]!==A)&&e&&!h){if(f){b==="type"&&Ra.test(a.nodeName)&&a.parentNode&&c.error("type
property can't be changed");
+if(d===null)a.nodeType===1&&a.removeAttribute(b);else
a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return
a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:Sa.test(a.nodeName)|
|Ta.test(a.nodeName)&&a.href?0:A;return
a[b]}if(!c.support.style&&e&&b==="style"){if(f)a.style.cssText=""+d;return
a.style.cssText}f&&a.setAttribute(b,""+d);if(!a.attributes[b]&&a.hasAttribute&&!a.hasAttribute(b))return
A;a=!c.support.hrefNormalized&&e&&
+h?a.getAttribute(b,2):a.getAttribute(b);return a===null?A:a}}});var
X=/\.(.*)$/,ha=/^(?:textarea|input|select)$/i,Ha=/\./g,Ia=/ /g,Ua=/[^\w\s.|
`]/g,Va=function(a){return
a.replace(Ua,"\\$&")},sa={focusin:0,focusout:0};c.event={add:function(a,b,d,e){if(!(a.nodeType===3|
|
a.nodeType===8)){if(c.isWindow(a)&&a!==E&&!a.frameElement)a=E;if(d===false)d=U;var
f,h;if(d.handler){f=d;d=f.handler}if(!d.guid)d.guid=c.guid++;if(h=c.data(a)){var
k=a.nodeType?"events":"__events__",l=h[k],n=h.handle;if(typeof l===
+"function"){n=l.handle;l=l.events}else if(!l){a.nodeType||
(h[k]=h=function(){});h.events=l={}}if(!n)h.handle=n=function(){return
typeof
c!=="undefined"&&!c.event.triggered?c.event.handle.apply(n.elem,arguments):A};n.elem=a;b=b.split(" ");for(var
s=0,v;k=b[s++];){h=f?c.extend({},f):{handler:d,data:e};if(k.indexOf(".")>-1){v=k.split(".");k=v.shift();h.namespace=v.slice(0).sort().join(".")}else{v=[];h.namespace=""}h.type=k;if(!h.guid)h.guid=d.guid;var
B=l[k],D=c.event.special[k]||{};if(!B){B=l[k]=[];
+if(!D.setup||
D.setup.call(a,e,v,n)===false)if(a.addEventListener)a.addEventListener(k,n,false);else
a.attachEvent&&a.attachEvent("on"+k,n)}if(D.add){D.add.call(a,h);if(!h.handler.guid)h.handler.guid=d.guid}B.push(h);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,e){if(!(a.nodeType===3|
|a.nodeType===8)){if(d===false)d=U;var
f,h,k=0,l,n,s,v,B,D,H=a.nodeType?"events":"__events__",w=c.data(a),G=w&&w[H];if(w&&G){if(typeof
G==="function"){w=G;G=G.events}if(b&&b.type){d=b.handler;b=b.type}if(!b||
+typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(f in
G)c.event.remove(a,f+b)}else{for(b=b.split(" ");f=b[k++];){v=f;l=f.indexOf(".")<0;n=[];if(!l){n=f.split(".");f=n.shift();s=RegExp("(^|
\\.)"+c.map(n.slice(0).sort(),Va).join("\\.(?:.*\\.)?")+"(\\.|
$)")}if(B=G[f])if(d){v=c.event.special[f]||{};for(h=e||
0;h<B.length;h++){D=B[h];if(d.guid===D.guid){if(l||
s.test(D.namespace)){e==null&&B.splice(h--,1);v.remove&&v.remove.call(a,D)}if(e!=null)break}}if(B.length===0|
|e!=null&&B.length===1){if(!v.teardown||
+v.teardown.call(a,n)===false)c.removeEvent(a,f,w.handle);delete G[f]}}else
for(h=0;h<B.length;h++){D=B[h];if(l||
s.test(D.namespace)){c.event.remove(a,v,D.handler,h);B.splice(h--,1)}}}if(c.isEmptyObject(G)){if(b=w.handle)b.elem=null;delete
w.events;delete w.handle;if(typeof w==="function")c.removeData(a,H);else
c.isEmptyObject(w)&&c.removeData(a)}}}}},trigger:function(a,b,d,e){var
f=a.type||a;if(!e){a=typeof
a==="object"?a[c.expando]?a:c.extend(c.Event(f),a):c.Event(f);if(f.indexOf("!")>=0){a.type=
+f=f.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[f]&&c.each(c.cache,function(){this.events&&this.events[f]&&c.event.trigger(a,b,this.handle.elem)})}if(!d|
|
d.nodeType===3||d.nodeType===8)return
A;a.result=A;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(e=d.nodeType?c.data(d,"handle"):(c.data(d,"__events__")|
|{}).handle)&&e.apply(d,b);e=d.parentNode||
d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+f]&&d["on"+f].apply(d,b)===
+false){a.result=false;a.preventDefault()}}catch(h){}if(!a.isPropagationStopped()&&e)c.event.trigger(a,b,e,true);else
if(!a.isDefaultPrevented()){e=a.target;var
k,l=f.replace(X,""),n=c.nodeName(e,"a")&&l==="click",s=c.event.special[l]|
|
{};if((!s._default||
s._default.call(d,a)===false)&&!n&&!(e&&e.nodeName&&c.noData[e.nodeName.toLowerCase()])){try{if(e[l]){if(k=e["on"+l])e["on"+l]=null;c.event.triggered=true;e[l]()}}catch(v){}if(k)e["on"+l]=k;c.event.triggered=false}}},handle:function(a){var
b,d,e;
+d=[];var f,h=c.makeArray(arguments);a=h[0]=c.event.fix(a||
E.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;if(!b){e=a.type.split(".");a.type=e.shift();d=e.slice(0).sort();e=RegExp("(^|
\\.)"+d.join("\\.(?:.*\\.)?")+"(\\.|$)")}a.namespace=a.namespace||
d.join(".");f=c.data(this,this.nodeType?"events":"__events__");if(typeof
f==="function")f=f.events;d=(f||
{})[a.type];if(f&&d){d=d.slice(0);f=0;for(var k=d.length;f<k;f++){var
l=d[f];if(b||e.test(l.namespace)){a.handler=l.handler;a.data=
+l.data;a.handleObj=l;l=l.handler.apply(this,h);if(l!==A){a.result=l;if(l===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return
a.result},props:"altKey
attrChange attrName bubbles button cancelable
charCode clientX clientY ctrlKey currentTarget data detail eventPhase
fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY
pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey
srcElement target toElement view wheelDelta which".split(" "),
+fix:function(a){if(a[c.expando])return a;var b=a;a=c.Event(b);for(var
d=this.props.length,e;d;){e=this.props[--d];a[e]=b[e]}if(!a.target)a.target=a.srcElement|
|
u;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=u.documentElement;d=u.body;a.pageX=a.clientX+(b&&b.scrollLeft|
|d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||
0);a.pageY=a.clientY+(b&&b.scrollTop||
+d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||
0)}if(a.which==null&&(a.charCode!=null||
a.keyCode!=null))a.which=a.charCode!=null?a.charCode:a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==A)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return
a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,Y(a.origType,a.selector),c.extend({},a,{handler:Ga,guid:a.handler.guid}))},remove:function(a){c.event.remove(this,
+Y(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,d){if(c.isWindow(this))this.onbeforeunload=d},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};c.removeEvent=u.removeEventListener?function(a,b,d){a.removeEventListener&&a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent&&a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return
new
c.Event(a);if(a&&a.type){this.originalEvent=a;this.type=a.type}else
this.type=a;this.timeStamp=
+c.now();this[c.expando]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=ba;var
a=this.originalEvent;if(a)if(a.preventDefault)a.preventDefault();else
a.returnValue=false},stopPropagation:function(){this.isPropagationStopped=ba;var
a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=ba;this.stopPropagation()},isDefaultPrevented:U,isPropagationStopped:U,isImmediatePropagationStopped:U};
+var ta=function(a){var
b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},ua=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?ua:ta,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?ua:ta)}}});if(!c.support.submitBubbles)c.event.special.submit={setup:function(){if(this.nodeName.toLowerCase()!==
+"form"){c.event.add(this,"click.specialSubmit",function(a){var
b=a.target,d=b.type;if((d==="submit"||
d==="image")&&c(b).closest("form").length){a.liveFired=A;return
ja("submit",this,arguments)}});c.event.add(this,"keypress.specialSubmit",function(a){var
b=a.target,d=b.type;if((d==="text"||
d==="password")&&c(b).closest("form").length&&a.keyCode===13){a.liveFired=A;return
ja("submit",this,arguments)}})}else return
false},teardown:function(){c.event.remove(this,".specialSubmit")}};if(!c.support.changeBubbles){var
V,
+va=function(a){var b=a.type,d=a.value;if(b==="radio"||
b==="checkbox")d=a.checked;else
if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(e){return
e.selected}).join("-"):"";else
if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return
d},Z=function(a,b){var d=a.target,e,f;if(!(!ha.test(d.nodeName)||
d.readOnly)){e=c.data(d,"_change_data");f=va(d);if(a.type!=="focusout"||
d.type!=="radio")c.data(d,"_change_data",f);if(!(e===A||f===e))if(e!=null||
f){a.type="change";a.liveFired=
+A;return
c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:Z,beforedeactivate:Z,click:function(a){var
b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||
b.nodeName.toLowerCase()==="select")return
Z.call(this,a)},keydown:function(a){var
b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"|
|a.keyCode===32&&(d==="checkbox"||d==="radio")||
d==="select-multiple")return
Z.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,"_change_data",va(a))}},setup:function(){if(this.type===
+"file")return false;for(var a in
V)c.event.add(this,a+".specialChange",V[a]);return
ha.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return
ha.test(this.nodeName)}};V=c.event.special.change.filters;V.focus=V.beforeactivate}u.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function
d(e){e=c.event.fix(e);e.type=b;return
c.event.trigger(e,null,e.target)}c.event.special[b]={setup:function(){sa[b]++===0&&u.addEventListener(a,d,true)},teardown:function(){--sa[b]===
+0&&u.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,e,f){if(typeof
d==="object"){for(var
h in d)this[b](h,e,d[h],f);return
this}if(c.isFunction(e)||e===false){f=e;e=A}var
k=b==="one"?c.proxy(f,function(n){c(this).unbind(n,k);return
f.apply(this,arguments)}):f;if(d==="unload"&&b!=="one")this.one(d,e,f);else{h=0;for(var
l=this.length;h<l;h++)c.event.add(this[h],d,k,e)}return
this}});c.fn.extend({unbind:function(a,b){if(typeof
a==="object"&&!a.preventDefault)for(var d in a)this.unbind(d,
+a[d]);else{d=0;for(var
e=this.length;d<e;d++)c.event.remove(this[d],a,b)}return
this},delegate:function(a,b,d,e){return
this.live(b,d,e,a)},undelegate:function(a,b,d){return
arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return
this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){var
d=c.Event(a);d.preventDefault();d.stopPropagation();c.event.trigger(d,b,this[0]);return
d.result}},toggle:function(a){for(var b=arguments,d=
+1;d<b.length;)c.proxy(a,b[d++]);return
this.click(c.proxy(a,function(e){var f=(c.data(this,"lastToggle"+a.guid)||
0)%d;c.data(this,"lastToggle"+a.guid,f+1);e.preventDefault();return
b[f].apply(this,arguments)||false}))},hover:function(a,b){return
this.mouseenter(a).mouseleave(b||a)}});var
wa={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,e,f,h){var
k,l=0,n,s,v=h||this.selector;h=h?this:c(this.context);if(typeof d===
+"object"&&!d.preventDefault){for(k in d)h[b](k,e,d[k],v);return
this}if(c.isFunction(e)){f=e;e=A}for(d=(d|
|"").split(" ");(k=d[l++])!=null;){n=X.exec(k);s="";if(n){s=n[0];k=k.replace(X,"")}if(k==="hover")d.push("mouseenter"+s,"mouseleave"+s);else{n=k;if(k==="focus"|
|k==="blur"){d.push(wa[k]+s);k+=s}else k=(wa[k]||
k)+s;if(b==="live"){s=0;for(var
B=h.length;s<B;s++)c.event.add(h[s],"live."+Y(k,v),{data:e,selector:v,handler:f,origType:k,origHandler:f,preType:n})}else
h.unbind("live."+Y(k,v),f)}}return this}});
+c.each("blur focus focusin focusout load resize scroll unload click
dblclick mousedown mouseup mousemove mouseover mouseout mouseenter
mouseleave change select submit keydown keypress keyup
error".split(" "),function(a,b){c.fn[b]=function(d,e){if(e==null){e=d;d=null}return
arguments.length>0?this.bind(b,d,e):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});E.attachEvent&&!E.addEventListener&&c(E).bind("unload",function(){for(var
a in
c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});
+(function(){function a(g,j,o,m,p,q){p=0;for(var t=m.length;p<t;p++){var
x=m[p];if(x){x=x[g];for(var
C=false;x;){if(x.sizcache===o){C=m[x.sizset];break}if(x.nodeType===1&&!q){x.sizcache=o;x.sizset=p}if(x.nodeName.toLowerCase()===j){C=x;break}x=x[g]}m[p]=C}}}function
b(g,j,o,m,p,q){p=0;for(var t=m.length;p<t;p++){var
x=m[p];if(x){x=x[g];for(var
C=false;x;){if(x.sizcache===o){C=m[x.sizset];break}if(x.nodeType===1){if(!q){x.sizcache=o;x.sizset=p}if(typeof
j!=="string"){if(x===j){C=true;break}}else if(l.filter(j,
+[x]).length>0){C=x;break}}x=x[g]}m[p]=C}}}var d=/((?:\((?:\([^()]+\)|
[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^
>+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|
\n)*)/g,e=0,f=Object.prototype.toString,h=false,k=true;[0,0].sort(function(){k=false;return
0});var l=function(g,j,o,m){o=o||[];var p=j=j||
u;if(j.nodeType!==1&&j.nodeType!==9)return[];if(!g||typeof
g!=="string")return o;var
q=[],t,x,C,P,N=true,R=l.isXML(j),Q=g,L;do{d.exec("");if(t=d.exec(Q)){Q=t[3];q.push(t[1]);if(t[2]){P=t[3];
+break}}}while(t);if(q.length>1&&s.exec(g))if(q.length===2&&n.relative[q[0]])x=M(q[0]+q[1],j);else
for(x=n.relative[q[0]]?[j]:l(q.shift(),j);q.length;){g=q.shift();if(n.relative[g])g+=q.shift();x=M(g,x)}else{if(!m&&q.length>1&&j.nodeType===9&&!R&&n.match.ID.test(q[0])&&!n.match.ID.test(q[q.length-1])){t=l.find(q.shift(),j,R);j=t.expr?l.filter(t.expr,t.set)[0]:t.set[0]}if(j){t=m?{expr:q.pop(),set:D(m)}:l.find(q.pop(),q.length===1&&(q[0]==="~"|
|
q[0]==="+")&&j.parentNode?j.parentNode:j,R);x=t.expr?l.filter(t.expr,
+t.set):t.set;if(q.length>0)C=D(x);else
N=false;for(;q.length;){t=L=q.pop();if(n.relative[L])t=q.pop();else
L="";if(t==null)t=j;n.relative[L](C,t,R)}}else C=[]}C||(C=x);C||l.error(L||
g);if(f.call(C)==="[object
Array]")if(N)if(j&&j.nodeType===1)for(g=0;C[g]!=null;g++){if(C[g]&&(C[g]===true|
|C[g].nodeType===1&&l.contains(j,C[g])))o.push(x[g])}else
for(g=0;C[g]!=null;g++)C[g]&&C[g].nodeType===1&&o.push(x[g]);else
o.push.apply(o,C);else D(C,o);if(P){l(P,p,o,m);l.uniqueSort(o)}return
o};l.uniqueSort=function(g){if(w){h=
+k;g.sort(w);if(h)for(var
j=1;j<g.length;j++)g[j]===g[j-1]&&g.splice(j--,1)}return
g};l.matches=function(g,j){return
l(g,null,null,j)};l.matchesSelector=function(g,j){return
l(j,null,null,[g]).length>0};l.find=function(g,j,o){var
m;if(!g)return[];for(var p=0,q=n.order.length;p<q;p++){var
t=n.order[p],x;if(x=n.leftMatch[t].exec(g)){var
C=x[1];x.splice(1,1);if(C.substr(C.length-1)!=="\\"){x[1]=(x[1]|
|"").replace(/\\/g,"");m=n.find[t](x,j,o);if(m!=null){g=g.replace(n.match[t],"");break}}}}m|
|(m=j.getElementsByTagName("*"));
+return{set:m,expr:g}};l.filter=function(g,j,o,m){for(var
p=g,q=[],t=j,x,C,P=j&&j[0]&&l.isXML(j[0]);g&&j.length;){for(var N in
n.filter)if((x=n.leftMatch[N].exec(g))!=null&&x[2]){var
R=n.filter[N],Q,L;L=x[1];C=false;x.splice(1,1);if(L.substr(L.length-1)!=="\\"){if(t===q)q=[];if(n.preFilter[N])if(x=n.preFilter[N](x,t,o,q,m,P)){if(x===true)continue}else
C=Q=true;if(x)for(var i=0;(L=t[i])!=null;i++)if(L){Q=R(L,x,i,t);var
r=m^!!Q;if(o&&Q!=null)if(r)C=true;else t[i]=false;else
if(r){q.push(L);C=true}}if(Q!==
+A){o||
(t=q);g=g.replace(n.match[N],"");if(!C)return[];break}}}if(g===p)if(C==null)l.error(g);else
break;p=g}return t};l.error=function(g){throw"Syntax error, unrecognized
expression: "+g;};var
n=l.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|
\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|
\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|
\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|
\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|
\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/,
+POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|
$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|
[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return
g.getAttribute("href")}},relative:{"+":function(g,j){var o=typeof
j==="string",m=o&&!/\W/.test(j);o=o&&!m;if(m)j=j.toLowerCase();m=0;for(var
p=g.length,q;m<p;m++)if(q=g[m]){for(;(q=q.previousSibling)&&q.nodeType!==1;);g[m]=o|
|q&&q.nodeName.toLowerCase()===
+j?q||false:q===j}o&&l.filter(j,g,true)},">":function(g,j){var o=typeof
j==="string",m,p=0,q=g.length;if(o&&!/\W/.test(j))for(j=j.toLowerCase();p<q;p++){if(m=g[p]){o=m.parentNode;g[p]=o.nodeName.toLowerCase()===j?o:false}}else{for(;p<q;p++)if(m=g[p])g[p]=o?m.parentNode:m.parentNode===j;o&&l.filter(j,g,true)}},"":function(g,j,o){var
m=e++,p=b,q;if(typeof
j==="string"&&!/\W/.test(j)){q=j=j.toLowerCase();p=a}p("parentNode",j,m,g,q,o)},"~":function(g,j,o){var
m=e++,p=b,q;if(typeof j==="string"&&!/\W/.test(j)){q=
+j=j.toLowerCase();p=a}p("previousSibling",j,m,g,q,o)}},find:{ID:function(g,j,o){if(typeof
j.getElementById!=="undefined"&&!o)return(g=j.getElementById(g[1]))&&g.parentNode?[g]:[]},NAME:function(g,j){if(typeof
j.getElementsByName!=="undefined"){for(var
o=[],m=j.getElementsByName(g[1]),p=0,q=m.length;p<q;p++)m[p].getAttribute("name")===g[1]&&o.push(m[p]);return
o.length===0?null:o}},TAG:function(g,j){return
j.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,j,o,m,p,q){g=" "+g[1].replace(/\\/g,
+"")+" ";if(q)return g;q=0;for(var
t;(t=j[q])!=null;q++)if(t)if(p^(t.className&&(" "+t.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))o|
|m.push(t);else if(o)j[q]=false;return false},ID:function(g){return
g[1].replace(/\\/g,"")},TAG:function(g){return
g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var
j=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"|
|!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=j[1]+(j[2]||
1)-0;g[3]=j[3]-0}g[0]=e++;return g},ATTR:function(g,j,o,
+m,p,q){j=g[1].replace(/\\/g,"");if(!q&&n.attrMap[j])g[1]=n.attrMap[j];if(g[2]==="~=")g[4]=" "+g[4]+" ";return
g},PSEUDO:function(g,j,o,m,p){if(g[1]==="not")if((d.exec(g[3])|
|"").length>1|
|
/^\w/.test(g[3]))g[3]=l(g[3],null,null,j);else{g=l.filter(g[3],j,o,true^p);o|
|m.push.apply(m,g);return false}else if(n.match.POS.test(g[0])||
n.match.CHILD.test(g[0]))return true;return
g},POS:function(g){g.unshift(true);return
g}},filters:{enabled:function(g){return
g.disabled===false&&g.type!=="hidden"},disabled:function(g){return
g.disabled===
+true},checked:function(g){return
g.checked===true},selected:function(g){return
g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,j,o){return!!l(o[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===
+g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type|
|
g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|
textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,j){return
j===0},last:function(g,j,o,m){return
j===m.length-1},even:function(g,j){return j%2===0},odd:function(g,j){return
j%2===1},lt:function(g,j,o){return j<o[3]-0},gt:function(g,j,o){return
j>o[3]-0},nth:function(g,j,o){return o[3]-
+0===j},eq:function(g,j,o){return
o[3]-0===j}},filter:{PSEUDO:function(g,j,o,m){var
p=j[1],q=n.filters[p];if(q)return q(g,o,j,m);else
if(p==="contains")return(g.textContent||g.innerText||l.getText([g])|
|"").indexOf(j[3])>=0;else
if(p==="not"){j=j[3];o=0;for(m=j.length;o<m;o++)if(j[o]===g)return
false;return true}else l.error("Syntax error, unrecognized
expression: "+p)},CHILD:function(g,j){var
o=j[1],m=g;switch(o){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return
false;if(o===
+"first")return
true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return
false;return true;case "nth":o=j[2];var p=j[3];if(o===1&&p===0)return
true;var q=j[0],t=g.parentNode;if(t&&(t.sizcache!==q||!g.nodeIndex)){var
x=0;for(m=t.firstChild;m;m=m.nextSibling)if(m.nodeType===1)m.nodeIndex=++x;t.sizcache=q}m=g.nodeIndex-p;return
o===0?m===0:m%o===0&&m/o>=0}},ID:function(g,j){return
g.nodeType===1&&g.getAttribute("id")===j},TAG:function(g,j){return
j==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===
+j},CLASS:function(g,j){return(" "+(g.className||
g.getAttribute("class"))+" ").indexOf(j)>-1},ATTR:function(g,j){var
o=j[1];o=n.attrHandle[o]?n.attrHandle[o](g):g[o]!=null?g[o]:g.getAttribute(o);var
m=o+"",p=j[2],q=j[4];return
o==null?p==="!=":p==="="?m===q:p==="*="?m.indexOf(q)>=0:p==="~="?(" "+m+" ").indexOf(q)>=0:!q?m&&o!==false:p==="!="?m!==q:p==="^="?m.indexOf(q)===0:p==="$="?m.substr(m.length-q.length)===q:p==="|
="?m===q||m.substr(0,q.length+1)===q+"-":false},POS:function(g,j,o,m){var
p=n.setFilters[j[2]];
+if(p)return
p(g,o,j,m)}}},s=n.match.POS,v=function(g,j){return"\\"+(j-0+1)},B;for(B in
n.match){n.match[B]=RegExp(n.match[B].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[B]=RegExp(/(^(?:.|
\r|\n)*?)/.source+n.match[B].source.replace(/\\(\d+)/g,v))}var
D=function(g,j){g=Array.prototype.slice.call(g,0);if(j){j.push.apply(j,g);return
j}return
g};try{Array.prototype.slice.call(u.documentElement.childNodes,0)}catch(H){D=function(g,j){var
o=j||[],m=0;if(f.call(g)==="[object Array]")Array.prototype.push.apply(o,
+g);else if(typeof g.length==="number")for(var
p=g.length;m<p;m++)o.push(g[m]);else for(;g[m];m++)o.push(g[m]);return
o}}var
w,G;if(u.documentElement.compareDocumentPosition)w=function(g,j){if(g===j){h=true;return
0}if(!g.compareDocumentPosition||!j.compareDocumentPosition)return
g.compareDocumentPosition?-1:1;return
g.compareDocumentPosition(j)&4?-1:1};else{w=function(g,j){var
o=[],m=[],p=g.parentNode,q=j.parentNode,t=p;if(g===j){h=true;return 0}else
if(p===q)return G(g,j);else if(p){if(!q)return 1}else return-1;
+for(;t;){o.unshift(t);t=t.parentNode}for(t=q;t;){m.unshift(t);t=t.parentNode}p=o.length;q=m.length;for(t=0;t<p&&t<q;t++)if(o[t]!==m[t])return
G(o[t],m[t]);return
t===p?G(g,m[t],-1):G(o[t],j,1)};G=function(g,j,o){if(g===j)return
o;for(g=g.nextSibling;g;){if(g===j)return-1;g=g.nextSibling}return
1}}l.getText=function(g){for(var
j="",o,m=0;g[m];m++){o=g[m];if(o.nodeType===3|
|
o.nodeType===4)j+=o.nodeValue;else
if(o.nodeType!==8)j+=l.getText(o.childNodes)}return j};(function(){var
g=u.createElement("div"),
+j="script"+(new Date).getTime();g.innerHTML="<a name='"+j+"'/>";var
o=u.documentElement;o.insertBefore(g,o.firstChild);if(u.getElementById(j)){
n.find.ID=function(m,p,q){if(typeof
p.getElementById!=="undefined"&&!q)return(p=p.getElementById(m[1]))?
p.id===m[1]|
|typeof
p.getAttributeNode!=="undefined"&&p.getAttributeNode("id").nodeValue===m[1]?[p]:A:[]};
n.filter.ID=function(m,p){var
q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return
m.nodeType===1&&q&&q.nodeValue===p}}o.removeChild(g);
+o=g=null})();(function(){var
g=u.createElement("div");g.appendChild(u.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(j,o){var
m=o.getElementsByTagName(j[1]);if(j[1]==="*"){for(var
p=[],q=0;m[q];q++)m[q].nodeType===1&&p.push(m[q]);m=p}return
m};g.innerHTML="<a href='#'></a>";if(g.firstChild&&typeof
g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(j){return
j.getAttribute("href",2)};g=null})();u.querySelectorAll&&
+function(){var g=l,j=u.createElement("div");j.innerHTML="<p
class='TEST'></p>";if(!(j.querySelectorAll&&j.querySelectorAll(".TEST").length===0)){l=function(m,p,q,t){p=p|
|u;if(!t&&!l.isXML(p))if(p.nodeType===9)try{return
D(p.querySelectorAll(m),q)}catch(x){}else
if(p.nodeType===1&&p.nodeName.toLowerCase()!=="object"){var
C=
p.id,P=
p.id="__sizzle__";try{return
D(p.querySelectorAll("#"+P+" "+m),q)}catch(N){}finally{if(C)
p.id=C;else
p.removeAttribute("id")}}return g(m,p,q,t)};for(var o in g)l[o]=g[o];
+j=null}}();(function(){var g=u.documentElement,j=g.matchesSelector||
g.mozMatchesSelector||g.webkitMatchesSelector||
g.msMatchesSelector,o=false;try{j.call(u.documentElement,":sizzle")}catch(m){o=true}if(j)l.matchesSelector=function(p,q){try{if(o|
|!n.match.PSEUDO.test(q))return j.call(p,q)}catch(t){}return
l(q,null,null,[p]).length>0}})();(function(){var
g=u.createElement("div");g.innerHTML="<div class='test e'></div><div
class='test'></div>";if(!(!g.getElementsByClassName||
g.getElementsByClassName("e").length===
+0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(j,o,m){if(typeof
o.getElementsByClassName!=="undefined"&&!m)return
o.getElementsByClassName(j[1])};g=null}}})();l.contains=u.documentElement.contains?function(g,j){return
g!==j&&(g.contains?g.contains(j):true)}:function(g,j){return!!(g.compareDocumentPosition(j)&16)};l.isXML=function(g){return(g=(g?g.ownerDocument|
|
g:0).documentElement)?g.nodeName!=="HTML":false};var M=function(g,
+j){for(var
o=[],m="",p,q=j.nodeType?[j]:j;p=n.match.PSEUDO.exec(g);){m+=p[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;p=0;for(var
t=q.length;p<t;p++)l(g,q[p],o);return
l.filter(m,o)};c.find=l;c.expr=l.selectors;c.expr[":"]=c.expr.filters;c.unique=l.uniqueSort;c.text=l.getText;c.isXMLDoc=l.isXML;c.contains=l.contains})();var
Wa=/Until$/,Xa=/^(?:parents|prevUntil|
prevAll)/,Ya=/,/,Ja=/^.[^:#\[\.,]*$/,Za=Array.prototype.slice,$a=c.expr.match.POS;c.fn.extend({find:function(a){for(var
b=this.pushStack("",
+"find",a),d=0,e=0,f=this.length;e<f;e++){d=b.length;c.find(a,this[e],b);if(e>0)for(var
h=d;h<b.length;h++)for(var
k=0;k<d;k++)if(b[k]===b[h]){b.splice(h--,1);break}}return
b},has:function(a){var
b=c(a);return this.filter(function(){for(var
d=0,e=b.length;d<e;d++)if(c.contains(this,b[d]))return
true})},not:function(a){return
this.pushStack(ka(this,a,false),"not",a)},filter:function(a){return
this.pushStack(ka(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,
+b){var d=[],e,f,h=this[0];if(c.isArray(a)){var
k={},l,n=1;if(h&&a.length){e=0;for(f=a.length;e<f;e++){l=a[e];k[l]||
(k[l]=c.expr.match.POS.test(l)?c(l,b||
this.context):l)}for(;h&&h.ownerDocument&&h!==b;){for(l in
k){e=k[l];if(e.jquery?e.index(h)>-1:c(h).is(e))d.push({selector:l,elem:h,level:n})}h=h.parentNode;n++}}return
d}k=$a.test(a)?c(a,b||
this.context):null;e=0;for(f=this.length;e<f;e++)for(h=this[e];h;)if(k?k.index(h)>-1:c.find.matchesSelector(h,a)){d.push(h);break}else{h=h.parentNode;if(!h|
|
+!h.ownerDocument||h===b)break}d=d.length>1?c.unique(d):d;return
this.pushStack(d,"closest",a)},index:function(a){if(!a||typeof
a==="string")return
c.inArray(this[0],a?c(a):this.parent().children());return
c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var d=typeof
a==="string"?c(a,b||
this.context):c.makeArray(a),e=c.merge(this.get(),d);return
this.pushStack(!d[0]||!d[0].parentNode||d[0].parentNode.nodeType===11|
|!e[0]||!e[0].parentNode||
e[0].parentNode.nodeType===11?e:c.unique(e))},andSelf:function(){return
this.add(this.prevObject)}});
+c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return
c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return
c.dir(a,"parentNode",d)},next:function(a){return
c.nth(a,2,"nextSibling")},prev:function(a){return
c.nth(a,2,"previousSibling")},nextAll:function(a){return
c.dir(a,"nextSibling")},prevAll:function(a){return
c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return
c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return
c.dir(a,"previousSibling",
+d)},siblings:function(a){return
c.sibling(a.parentNode.firstChild,a)},children:function(a){return
c.sibling(a.firstChild)},contents:function(a){return
c.nodeName(a,"iframe")?a.contentDocument||
a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,e){var
f=c.map(this,b,d);Wa.test(a)||(e=d);if(e&&typeof
e==="string")f=c.filter(e,f);f=this.length>1?c.unique(f):f;if((this.length>1|
|Ya.test(e))&&Xa.test(a))f=f.reverse();return
this.pushStack(f,a,Za.call(arguments).join(","))}});
+c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return
b.length===1?c.find.matchesSelector(b[0],a)?[b[0]]:[]:c.find.matches(a,b)},dir:function(a,b,d){var
e=[];for(a=a[b];a&&a.nodeType!==9&&(d===A||a.nodeType!==1|
|!c(a).is(d));){a.nodeType===1&&e.push(a);a=a[b]}return
e},nth:function(a,b,d){b=b||1;for(var
e=0;a;a=a[d])if(a.nodeType===1&&++e===b)break;return
a},sibling:function(a,b){for(var
d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var
xa=/ jQuery\d+="(?:\d+|null)"/g,
+$=/^\s+/,ya=/<(?!area|br|col|embed|hr|img|input|link|meta|
param)(([\w:]+)[^>]*)\/>/ig,za=/<([\w:]+)/,ab=/<tbody/i,bb=/<|
&#?\w+;/,Aa=/<(?:script|object|embed|option|style)/i,Ba=/checked\s*(?:[^=]|
=\s*.checked.)/i,cb=/\=([^="'>\s]+\/)>/g,O={option:[1,"<select
multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],
+area:[1,"<map>","</map>"],_default:[0,"",""]};O.optgroup=O.option;O.tbody=O.tfoot=O.colgroup=O.caption=O.thead;O.th=O.td;if(!c.support.htmlSerialize)O._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return
this.each(function(b){var
d=c(this);d.text(a.call(this,b,d.text()))});if(typeof
a!=="object"&&a!==A)return
this.empty().append((this[0]&&this[0].ownerDocument|
|
u).createTextNode(a));return
c.text(this)},wrapAll:function(a){if(c.isFunction(a))return
this.each(function(d){c(this).wrapAll(a.call(this,
+d))});if(this[0]){var
b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var
d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return
d}).append(this)}return
this},wrapInner:function(a){if(c.isFunction(a))return
this.each(function(b){c(this).wrapInner(a.call(this,b))});return
this.each(function(){var
b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return
this.each(function(){c(this).wrapAll(a)})},
+unwrap:function(){return
this.parent().each(function(){c.nodeName(this,"body")||
c(this).replaceWith(this.childNodes)}).end()},append:function(){return
this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return
this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return
this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else
if(arguments.length){var a=
+c(arguments[0]);a.push.apply(a,this.toArray());return
this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return
this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this.nextSibling)});else
if(arguments.length){var
a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return
a}},remove:function(a,b){for(var d=0,e;(e=this[d])!=null;d++)if(!a||
c.filter(a,[e]).length){if(!b&&e.nodeType===1){c.cleanData(e.getElementsByTagName("*"));
+c.cleanData([e])}e.parentNode&&e.parentNode.removeChild(e)}return
this},empty:function(){for(var
a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);return
this},clone:function(a){var
b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var
d=this.outerHTML,e=this.ownerDocument;if(!d){d=e.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return
c.clean([d.replace(xa,"").replace(cb,'="$1">').replace($,
+"")],e)[0]}else return
this.cloneNode(true)});if(a===true){la(this,b);la(this.find("*"),b.find("*"))}return
b},html:function(a){if(a===A)return
this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(xa,""):null;else
if(typeof a==="string"&&!Aa.test(a)&&(c.support.leadingWhitespace|
|!$.test(a))&&!O[(za.exec(a)||
["",""])[1].toLowerCase()]){a=a.replace(ya,"<$1></$2>");try{for(var
b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(e){this.empty().append(a)}}else
c.isFunction(a)?
+this.each(function(f){var
h=c(this);h.html(a.call(this,f,h.html()))}):this.empty().append(a);return
this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(c.isFunction(a))return
this.each(function(b){var
d=c(this),e=d.html();d.replaceWith(a.call(this,b,e))});if(typeof
a!=="string")a=c(a).detach();return this.each(function(){var
b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else
return
this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return
this.remove(a,
+true)},domManip:function(a,b,d){var
e,f,h=a[0],k=[],l;if(!c.support.checkClone&&arguments.length===3&&typeof
h==="string"&&Ba.test(h))return
this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(h))return
this.each(function(s){var
v=c(this);a[0]=h.call(this,s,b?v.html():A);v.domManip(a,b,d)});if(this[0]){e=h&&h.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:c.buildFragment(a,this,k);l=e.fragment;if(f=l.childNodes.length===1?l=l.firstChild:
+l.firstChild){b=b&&c.nodeName(f,"tr");f=0;for(var
n=this.length;f<n;f++)d.call(b?c.nodeName(this[f],"table")?this[f].getElementsByTagName("tbody")[0]|
|
this[f].appendChild(this[f].ownerDocument.createElement("tbody")):this[f]:this[f],f>0|
|e.cacheable||
this.length>1?l.cloneNode(true):l)}k.length&&c.each(k,Ka)}return
this}});c.buildFragment=function(a,b,d){var
e,f,h;b=b&&b[0]?b[0].ownerDocument||b[0]:u;if(a.length===1&&typeof
a[0]==="string"&&a[0].length<512&&b===u&&!Aa.test(a[0])&&(c.support.checkClone|
|
+!Ba.test(a[0]))){f=true;if(h=c.fragments[a[0]])if(h!==1)e=h}if(!e){e=b.createDocumentFragment();c.clean(a,b,e,d)}if(f)c.fragments[a[0]]=h?e:1;return{fragment:e,cacheable:f}};c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var
e=[];d=c(d);var
f=this.length===1&&this[0].parentNode;if(f&&f.nodeType===11&&f.childNodes.length===1&&d.length===1){d[b](this[0]);return
this}else{f=0;for(var
h=
+d.length;f<h;f++){var
k=(f>0?this.clone(true):this).get();c(d[f])[b](k);e=e.concat(k)}return
this.pushStack(e,a,d.selector)}}});c.extend({clean:function(a,b,d,e){b=b||
u;if(typeof b.createElement==="undefined")b=b.ownerDocument||
b[0]&&b[0].ownerDocument||u;for(var
f=[],h=0,k;(k=a[h])!=null;h++){if(typeof k==="number")k+="";if(k){if(typeof
k==="string"&&!bb.test(k))k=b.createTextNode(k);else if(typeof
k==="string"){k=k.replace(ya,"<$1></$2>");var l=(za.exec(k)||
["",""])[1].toLowerCase(),n=O[l]||O._default,
+s=n[0],v=b.createElement("div");for(v.innerHTML=n[1]+k+n[2];s--;)v=v.lastChild;if(!c.support.tbody){s=ab.test(k);l=l==="table"&&!s?v.firstChild&&v.firstChild.childNodes:n[1]==="<table>"&&!s?v.childNodes:[];for(n=l.length-1;n>=0;--n)c.nodeName(l[n],"tbody")&&!l[n].childNodes.length&&l[n].parentNode.removeChild(l[n])}!c.support.leadingWhitespace&&$.test(k)&&v.insertBefore(b.createTextNode($.exec(k)[0]),v.firstChild);k=v.childNodes}if(k.nodeType)f.push(k);else
f=c.merge(f,k)}}if(d)for(h=0;f[h];h++)if(e&&
+c.nodeName(f[h],"script")&&(!f[h].type||
f[h].type.toLowerCase()==="text/javascript"))e.push(f[h].parentNode?f[h].parentNode.removeChild(f[h]):f[h]);else{f[h].nodeType===1&&f.splice.apply(f,[h+1,0].concat(c.makeArray(f[h].getElementsByTagName("script"))));d.appendChild(f[h])}return
f},cleanData:function(a){for(var
b,d,e=c.cache,f=c.event.special,h=c.support.deleteExpando,k=0,l;(l=a[k])!=null;k++)if(!(l.nodeName&&c.noData[l.nodeName.toLowerCase()]))if(d=l[c.expando]){if((b=e[d])&&b.events)for(var
n in b.events)f[n]?
+c.event.remove(l,n):c.removeEvent(l,n,b.handle);if(h)delete
l[c.expando];else l.removeAttribute&&l.removeAttribute(c.expando);delete
e[d]}}});var
Ca=/alpha\([^)]*\)/i,db=/opacity=([^)]*)/,eb=/-([a-z])/ig,fb=/([A-Z])/g,Da=/^-?\d+(?:px)?$/i,gb=/^-?\d/,hb={position:"absolute",visibility:"hidden",display:"block"},La=["Left","Right"],Ma=["Top","Bottom"],W,ib=u.defaultView&&u.defaultView.getComputedStyle,jb=function(a,b){return
b.toUpperCase()};c.fn.css=function(a,b){if(arguments.length===2&&b===A)return
this;
+return c.access(this,a,b,true,function(d,e,f){return
f!==A?c.style(d,e,f):c.css(d,e)})};c.extend({cssHooks:{opacity:{get:function(a,b){if(b){var
d=W(a,"opacity","opacity");return d===""?"1":d}else return
a.style.opacity}}},cssNumber:{zIndex:true,fontWeight:true,opacity:true,zoom:true,lineHeight:true},cssProps:{"float":c.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,d,e){if(!(!a|
|a.nodeType===3||a.nodeType===8||!a.style)){var
f,h=c.camelCase(b),k=a.style,l=c.cssHooks[h];b=c.cssProps[h]||
+h;if(d!==A){if(!(typeof d==="number"&&isNaN(d)||d==null)){if(typeof
d==="number"&&!c.cssNumber[h])d+="px";if(!l||!("set"in l)||
(d=l.set(a,d))!==A)try{k[b]=d}catch(n){}}}else{if(l&&"get"in
l&&(f=l.get(a,false,e))!==A)return f;return k[b]}}},css:function(a,b,d){var
e,f=c.camelCase(b),h=c.cssHooks[f];b=c.cssProps[f]||f;if(h&&"get"in
h&&(e=h.get(a,true,d))!==A)return e;else if(W)return
W(a,b,f)},swap:function(a,b,d){var e={},f;for(f in
b){e[f]=a.style[f];a.style[f]=b[f]}d.call(a);for(f in b)a.style[f]=
+e[f]},camelCase:function(a){return
a.replace(eb,jb)}});c.curCSS=c.css;c.each(["height","width"],function(a,b){c.cssHooks[b]={get:function(d,e,f){var
h;if(e){if(d.offsetWidth!==0)h=ma(d,b,f);else
c.swap(d,hb,function(){h=ma(d,b,f)});return
h+"px"}},set:function(d,e){if(Da.test(e)){e=parseFloat(e);if(e>=0)return
e+"px"}else return
e}}});if(!c.support.opacity)c.cssHooks.opacity={get:function(a,b){return
db.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)|
|"")?parseFloat(RegExp.$1)/100+"":
+b?"1":""},set:function(a,b){var d=a.style;d.zoom=1;var
e=c.isNaN(b)?"":"alpha(opacity="+b*100+")",f=d.filter|
|"";d.filter=Ca.test(f)?f.replace(Ca,e):d.filter+" "+e}};if(ib)W=function(a,b,d){var
e;d=d.replace(fb,"-$1").toLowerCase();if(!(b=a.ownerDocument.defaultView))return
A;if(b=b.getComputedStyle(a,null)){e=b.getPropertyValue(d);if(e===""&&!c.contains(a.ownerDocument.documentElement,a))e=c.style(a,d)}return
e};else if(u.documentElement.currentStyle)W=function(a,b){var
d,e,f=a.currentStyle&&a.currentStyle[b],
+h=a.style;if(!Da.test(f)&&gb.test(f)){d=h.left;e=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;h.left=b==="fontSize"?"1em":f|
|
0;f=h.pixelLeft+"px";h.left=d;a.runtimeStyle.left=e}return
f};if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var
b=a.offsetHeight;return a.offsetWidth===0&&b===0|
|!c.support.reliableHiddenOffsets&&(a.style.display||
c.css(a,"display"))==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var
kb=c.now(),lb=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
+mb=/^(?:select|textarea)/i,nb=/^(?:color|date|datetime|email|hidden|month|
number|password|range|search|tel|text|time|url|week)$/i,ob=/^(?:GET|HEAD|
DELETE)$/,Na=/\[\]$/,T=/\=\?(&|
$)/,ia=/\?/,pb=/([?&])_=[^&]*/,qb=/^(\w+:)?\/\/([^\/?#]+)/,rb=/%20/g,sb=/#.*$/,Ea=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof
a!=="string"&&Ea)return Ea.apply(this,arguments);else
if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var
f=a.slice(e,a.length);a=a.slice(0,e)}e="GET";if(b)if(c.isFunction(b)){d=
+b;b=null}else if(typeof
b==="object"){b=c.param(b,c.ajaxSettings.traditional);e="POST"}var
h=this;c.ajax({url:a,type:e,dataType:"html",data:b,complete:function(k,l){if(l==="success"|
|
l==="notmodified")h.html(f?c("<div>").append(k.responseText.replace(lb,"")).find(f):k.responseText);d&&h.each(d,[k.responseText,l,k])}});return
this},serialize:function(){return
c.param(this.serializeArray())},serializeArray:function(){return
this.map(function(){return
this.elements?c.makeArray(this.elements):this}).filter(function(){return
this.name&&
+!this.disabled&&(this.checked||mb.test(this.nodeName)||
nb.test(this.type))}).map(function(a,b){var d=c(this).val();return
d==null?null:c.isArray(d)?c.map(d,function(e){return{name:
b.name,value:e}}):{name:
b.name,value:d}}).get()}});c.each("ajaxStart
ajaxStop ajaxComplete ajaxError ajaxSuccess
ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return
this.bind(b,d)}});c.extend({get:function(a,b,d,e){if(c.isFunction(b)){e=e||
d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:e})},
+getScript:function(a,b){return
c.get(a,null,b,"script")},getJSON:function(a,b,d){return
c.get(a,b,d,"json")},post:function(a,b,d,e){if(c.isFunction(b)){e=e||
d;d=b;b={}}return
c.ajax({type:"POST",url:a,data:b,success:d,dataType:e})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return
new E.XMLHttpRequest},accepts:{xml:"application/xml,
text/xml",html:"text/html",
+script:"text/javascript, application/javascript",json:"application/json,
text/javascript",text:"text/plain",_default:"*/*"}},ajax:function(a){var
b=c.extend(true,{},c.ajaxSettings,a),d,e,f,h=b.type.toUpperCase(),k=ob.test(h);b.url=b.url.replace(sb,"");b.context=a&&a.context!=null?a.context:b;if(b.data&&b.processData&&typeof
b.data!=="string")b.data=c.param(b.data,b.traditional);if(b.dataType==="jsonp"){if(h==="GET")T.test(b.url)|
|(b.url+=(ia.test(b.url)?"&":"?")+(b.jsonp||"callback")+"=?");else
if(!b.data||
+!T.test(b.data))b.data=(b.data?b.data+"&":"")+(b.jsonp|
|"callback")+"=?";b.dataType="json"}if(b.dataType==="json"&&(b.data&&T.test(b.data)|
|T.test(b.url))){d=b.jsonpCallback|
|"jsonp"+kb++;if(b.data)b.data=(b.data+"").replace(T,"="+d+"$1");b.url=b.url.replace(T,"="+d+"$1");b.dataType="script";var
l=E[d];E[d]=function(m){f=m;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);if(c.isFunction(l))l(m);else{E[d]=A;try{delete
E[d]}catch(p){}}v&&v.removeChild(B)}}if(b.dataType==="script"&&b.cache===null)b.cache=
+false;if(b.cache===false&&h==="GET"){var
n=c.now(),s=b.url.replace(pb,"$1_="+n);b.url=s+(s===b.url?(ia.test(b.url)?"&":"?")+"_="+n:"")}if(b.data&&h==="GET")b.url+=(ia.test(b.url)?"&":"?")+b.data;b.global&&c.active++===0&&c.event.trigger("ajaxStart");n=(n=qb.exec(b.url))&&(n[1]&&n[1]!==location.protocol|
|n[2]!==location.host);if(b.dataType==="script"&&h==="GET"&&n){var
v=u.getElementsByTagName("head")[0]||
u.documentElement,B=u.createElement("script");if(b.scriptCharset)B.charset=b.scriptCharset;B.src=
+b.url;if(!d){var
D=false;B.onload=B.onreadystatechange=function(){if(!D&&(!this.readyState||
this.readyState==="loaded"||
this.readyState==="complete")){D=true;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);B.onload=B.onreadystatechange=null;v&&B.parentNode&&v.removeChild(B)}}}v.insertBefore(B,v.firstChild);return
A}var
H=false,w=b.xhr();if(w){b.username?w.open(h,b.url,b.async,b.username,b.password):w.open(h,b.url,b.async);try{if(b.data!=null&&!k|
|a&&a.contentType)w.setRequestHeader("Content-Type",
+b.contentType);if(b.ifModified){c.lastModified[b.url]&&w.setRequestHeader("If-Modified-Since",c.lastModified[b.url]);c.etag[b.url]&&w.setRequestHeader("If-None-Match",c.etag[b.url])}n|
|
w.setRequestHeader("X-Requested-With","XMLHttpRequest");w.setRequestHeader("Accept",b.dataType&&b.accepts[b.dataType]?b.accepts[b.dataType]+",
*/*;
q=0.01":b.accepts._default)}catch(G){}if(b.beforeSend&&b.beforeSend.call(b.context,w,b)===false){b.global&&c.active--===1&&c.event.trigger("ajaxStop");w.abort();return
false}b.global&&
+c.triggerGlobal(b,"ajaxSend",[w,b]);var
M=w.onreadystatechange=function(m){if(!w||w.readyState===0||m==="abort"){H||
c.handleComplete(b,w,e,f);H=true;if(w)w.onreadystatechange=c.noop}else
if(!H&&w&&(w.readyState===4||
m==="timeout")){H=true;w.onreadystatechange=c.noop;e=m==="timeout"?"timeout":!c.httpSuccess(w)?"error":b.ifModified&&c.httpNotModified(w,b.url)?"notmodified":"success";var
p;if(e==="success")try{f=c.httpData(w,b.dataType,b)}catch(q){e="parsererror";p=q}if(e==="success"|
|e==="notmodified")d||
+c.handleSuccess(b,w,e,f);else c.handleError(b,w,e,p);d||
c.handleComplete(b,w,e,f);m==="timeout"&&w.abort();if(b.async)w=null}};try{var
g=w.abort;w.abort=function(){w&&g.call&&g.call(w);M("abort")}}catch(j){}b.async&&b.timeout>0&&setTimeout(function(){w&&!H&&M("timeout")},b.timeout);try{w.send(k|
|
b.data==null?null:b.data)}catch(o){c.handleError(b,w,null,o);c.handleComplete(b,w,e,f)}b.async|
|M();return w}},param:function(a,b){var
d=[],e=function(h,k){k=c.isFunction(k)?k():k;d[d.length]=encodeURIComponent(h)+
+"="+encodeURIComponent(k)};if(b===A)b=c.ajaxSettings.traditional;if(c.isArray(a)|
|
a.jquery)c.each(a,function(){e(
this.name,this.value)});else for(var f in
a)ca(f,a[f],b,e);return
d.join("&").replace(rb,"+")}});c.extend({active:0,lastModified:{},etag:{},handleError:function(a,b,d,e){a.error&&a.error.call(a.context,b,d,e);a.global&&c.triggerGlobal(a,"ajaxError",[b,a,e])},handleSuccess:function(a,b,d,e){a.success&&a.success.call(a.context,e,d,b);a.global&&c.triggerGlobal(a,"ajaxSuccess",[b,a])},handleComplete:function(a,
+b,d){a.complete&&a.complete.call(a.context,b,d);a.global&&c.triggerGlobal(a,"ajaxComplete",[b,a]);a.global&&c.active--===1&&c.event.trigger("ajaxStop")},triggerGlobal:function(a,b,d){(a.context&&a.context.url==null?c(a.context):c.event).trigger(b,d)},httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"|
|
a.status>=200&&a.status<300||a.status===304||
a.status===1223}catch(b){}return false},httpNotModified:function(a,b){var
d=a.getResponseHeader("Last-Modified"),e=a.getResponseHeader("Etag");
+if(d)c.lastModified[b]=d;if(e)c.etag[b]=e;return
a.status===304},httpData:function(a,b,d){var
e=a.getResponseHeader("content-type")||"",f=b==="xml"|
|!b&&e.indexOf("xml")>=0;a=f?a.responseXML:a.responseText;f&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof
a==="string")if(b==="json"||!b&&e.indexOf("json")>=0)a=c.parseJSON(a);else
if(b==="script"||!b&&e.indexOf("javascript")>=0)c.globalEval(a);return
a}});if(E.ActiveXObject)c.ajaxSettings.xhr=
+function(){if(E.location.protocol!=="file:")try{return new
E.XMLHttpRequest}catch(a){}try{return new
E.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}};c.support.ajax=!!c.ajaxSettings.xhr();var
da={},tb=/^(?:toggle|show|
hide)$/,ub=/^([+\-]=)?([\d+.\-]+)(.*)$/,aa,na=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b,d){if(a|
|a===0)return this.animate(S("show",3),a,b,d);else{a=
+0;for(b=this.length;a<b;a++){if(!c.data(this[a],"olddisplay")&&this[a].style.display==="none")this[a].style.display="";this[a].style.display===""&&c.css(this[a],"display")==="none"&&c.data(this[a],"olddisplay",oa(this[a].nodeName))}for(a=0;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")|
|"";return
this}},hide:function(a,b,d){if(a||a===0)return
this.animate(S("hide",3),a,b,d);else{a=0;for(b=this.length;a<b;a++){d=c.css(this[a],"display");d!=="none"&&c.data(this[a],"olddisplay",d)}for(a=
+0;a<b;a++)this[a].style.display="none";return
this}},_toggle:c.fn.toggle,toggle:function(a,b,d){var e=typeof
a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else
a==null||e?this.each(function(){var
f=e?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(S("toggle",3),a,b,d);return
this},fadeTo:function(a,b,d,e){return
this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d,e)},animate:function(a,b,d,e){var
f=c.speed(b,d,e);if(c.isEmptyObject(a))return this.each(f.complete);
+return this[f.queue===false?"each":"queue"](function(){var
h=c.extend({},f),k,l=this.nodeType===1,n=l&&c(this).is(":hidden"),s=this;for(k
in a){var v=c.camelCase(k);if(k!==v){a[v]=a[k];delete
a[k];k=v}if(a[k]==="hide"&&n||a[k]==="show"&&!n)return
h.complete.call(this);if(l&&(k==="height"||
k==="width")){h.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY];if(c.css(this,"display")==="inline"&&c.css(this,"float")==="none")if(c.support.inlineBlockNeedsLayout)if(oa(this.nodeName)===
+"inline")this.style.display="inline-block";else{this.style.display="inline";this.style.zoom=1}else
this.style.display="inline-block"}if(c.isArray(a[k])){(h.specialEasing=h.specialEasing|
|
{})[k]=a[k][1];a[k]=a[k][0]}}if(h.overflow!=null)this.style.overflow="hidden";h.curAnim=c.extend({},a);c.each(a,function(B,D){var
H=new
c.fx(s,h,B);if(tb.test(D))H[D==="toggle"?n?"show":"hide":D](a);else{var
w=ub.exec(D),G=H.cur(true)|
|0;if(w){var M=parseFloat(w[2]),g=w[3]|
|"px";if(g!=="px"){c.style(s,B,(M||1)+g);
+G=(M||
1)/H.cur(true)*G;c.style(s,B,G+g)}if(w[1])M=(w[1]==="-="?-1:1)*M+G;H.custom(G,M,g)}else
H.custom(G,D,"")}});return true})},stop:function(a,b){var
d=c.timers;a&&this.queue([]);this.each(function(){for(var
e=d.length-1;e>=0;e--)if(d[e].elem===this){b&&d[e](true);d.splice(e,1)}});b|
|this.dequeue();return
this}});c.each({slideDown:S("show",1),slideUp:S("hide",1),slideToggle:S("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,e,f){return
this.animate(b,
+d,e,f)}});c.extend({speed:function(a,b,d){var e=a&&typeof
a==="object"?c.extend({},a):{complete:d||!d&&b||
c.isFunction(a)&&a,duration:a,easing:d&&b||
b&&!c.isFunction(b)&&b};e.duration=c.fx.off?0:typeof
e.duration==="number"?e.duration:e.duration in
c.fx.speeds?c.fx.speeds[e.duration]:c.fx.speeds._default;e.old=e.complete;e.complete=function(){e.queue!==false&&c(this).dequeue();c.isFunction(e.old)&&e.old.call(this)};return
e},easing:{linear:function(a,b,d,e){return
d+e*a},swing:function(a,b,d,e){return(-Math.cos(a*
+Math.PI)/2+0.5)*e+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|
|
c.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style|
|
this.elem.style[this.prop]==null))return this.elem[this.prop];var
a=parseFloat(c.css(this.elem,this.prop));return
a&&a>-1E4?a:0},custom:function(a,b,d){function e(h){return f.step(h)}
+this.startTime=c.now();this.start=a;this.end=b;this.unit=d||this.unit|
|"px";this.now=this.start;this.pos=this.state=0;var
f=this;a=c.fx;e.elem=this.elem;if(e()&&c.timers.push(e)&&!aa)aa=setInterval(a.tick,a.interval)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"|
|
this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;
+this.custom(this.cur(),0)},step:function(a){var b=c.now(),d=true;if(a||
b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var
e in
this.options.curAnim)if(this.options.curAnim[e]!==true)d=false;if(d){if(this.options.overflow!=null&&!c.support.shrinkWrapBlocks){var
f=this.elem,h=this.options;c.each(["","X","Y"],function(l,n){f.style["overflow"+n]=h.overflow[l]})}this.options.hide&&c(this.elem).hide();if(this.options.hide|
|
+this.options.show)for(var k in
this.options.curAnim)c.style(this.elem,k,this.options.orig[k]);this.options.complete.call(this.elem)}return
false}else{a=b-this.startTime;this.state=a/this.options.duration;b=this.options.easing|
|
(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]|
|
b](this.state,a,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return
true}};c.extend(c.fx,{tick:function(){for(var a=
+c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
c.fx.stop()},interval:13,stop:function(){clearInterval(aa);aa=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"|
|a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else
a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return
c.grep(c.timers,function(b){return a===
+b.elem}).length};var vb=/^t(?:able|d|h)$/i,Fa=/^(?:body|
html)$/i;c.fn.offset="getBoundingClientRect"in
u.documentElement?function(a){var b=this[0],d;if(a)return
this.each(function(k){c.offset.setOffset(this,a,k)});if(!b|
|!b.ownerDocument)return null;if(b===b.ownerDocument.body)return
c.offset.bodyOffset(b);try{d=b.getBoundingClientRect()}catch(e){}var
f=b.ownerDocument,h=f.documentElement;if(!d||!c.contains(h,b))return d||
{top:0,left:0};b=f.body;f=ea(f);return{top:d.top+(f.pageYOffset||
c.support.boxModel&&
+h.scrollTop||b.scrollTop)-(h.clientTop||b.clientTop||
0),left:d.left+(f.pageXOffset||c.support.boxModel&&h.scrollLeft||
b.scrollLeft)-(h.clientLeft||b.clientLeft||0)}}:function(a){var
b=this[0];if(a)return
this.each(function(s){c.offset.setOffset(this,a,s)});if(!b|
|!b.ownerDocument)return null;if(b===b.ownerDocument.body)return
c.offset.bodyOffset(b);c.offset.initialize();var
d=b.offsetParent,e=b.ownerDocument,f,h=e.documentElement,k=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;
+for(var
l=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==k&&b!==h;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;f=e?e.getComputedStyle(b,null):b.currentStyle;l-=b.scrollTop;n-=b.scrollLeft;if(b===d){l+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&vb.test(b.nodeName))){l+=parseFloat(f.borderTopWidth)|
|0;n+=parseFloat(f.borderLeftWidth)||
0}d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&f.overflow!=="visible"){l+=
+parseFloat(f.borderTopWidth)||0;n+=parseFloat(f.borderLeftWidth)||
0}f=f}if(f.position==="relative"||
f.position==="static"){l+=k.offsetTop;n+=k.offsetLeft}if(c.offset.supportsFixedPosition&&f.position==="fixed"){l+=Math.max(h.scrollTop,k.scrollTop);n+=Math.max(h.scrollLeft,k.scrollLeft)}return{top:l,left:n}};c.offset={initialize:function(){var
a=u.body,b=u.createElement("div"),d,e,f,h=parseFloat(c.css(a,"marginTop"))||
0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",
+height:"1px",visibility:"hidden"});b.innerHTML="<div
style='position:absolute;top:0;left:0;margin:0;border:5px solid
#000;padding:0;width:1px;height:1px;'><div></div></div><table
style='position:absolute;top:0;left:0;margin:0;border:5px solid
#000;padding:0;width:1px;height:1px;' cellpadding='0'
cellspacing='0'><tr><td></td></tr></table>";a.insertBefore(b,a.firstChild);d=b.firstChild;e=d.firstChild;f=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=e.offsetTop!==5;this.doesAddBorderForTableAndCells=
+f.offsetTop===5;e.style.position="fixed";e.style.top="20px";this.supportsFixedPosition=e.offsetTop===20|
|
e.offsetTop===15;e.style.position=e.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==h;a.removeChild(b);c.offset.initialize=c.noop},bodyOffset:function(a){var
b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.css(a,
+"marginTop"))||0;d+=parseFloat(c.css(a,"marginLeft"))||
0}return{top:b,left:d}},setOffset:function(a,b,d){var
e=c.css(a,"position");if(e==="static")a.style.position="relative";var
f=c(a),h=f.offset(),k=c.css(a,"top"),l=c.css(a,"left"),n=e==="absolute"&&c.inArray("auto",[k,l])>-1;e={};var
s={};if(n)s=f.position();k=n?s.top:parseInt(k,10)||
0;l=n?s.left:parseInt(l,10)||
0;if(c.isFunction(b))b=b.call(a,d,h);if(b.top!=null)e.top=b.top-h.top+k;if(b.left!=null)e.left=b.left-h.left+l;"using"in
b?b.using.call(a,
+e):f.css(e)}};c.fn.extend({position:function(){if(!this[0])return null;var
a=this[0],b=this.offsetParent(),d=this.offset(),e=Fa.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.css(a,"marginTop"))|
|0;d.left-=parseFloat(c.css(a,"marginLeft"))||
0;e.top+=parseFloat(c.css(b[0],"borderTopWidth"))||
0;e.left+=parseFloat(c.css(b[0],"borderLeftWidth"))||
0;return{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return
this.map(function(){for(var a=this.offsetParent||
u.body;a&&!Fa.test(a.nodeName)&&
+c.css(a,"position")==="static";)a=a.offsetParent;return
a})}});c.each(["Left","Top"],function(a,b){var
d="scroll"+b;c.fn[d]=function(e){var f=this[0],h;if(!f)return
null;if(e!==A)return
this.each(function(){if(h=ea(this))h.scrollTo(!a?e:c(h).scrollLeft(),a?e:c(h).scrollTop());else
this[d]=e});else return(h=ea(f))?"pageXOffset"in
h?h[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&h.document.documentElement[d]|
|h.document.body[d]:f[d]}});c.each(["Height","Width"],function(a,b){var
d=b.toLowerCase();
+c.fn["inner"+b]=function(){return
this[0]?parseFloat(c.css(this[0],d,"padding")):null};c.fn["outer"+b]=function(e){return
this[0]?parseFloat(c.css(this[0],d,e?"margin":"border")):null};c.fn[d]=function(e){var
f=this[0];if(!f)return e==null?null:this;if(c.isFunction(e))return
this.each(function(h){var k=c(this);k[d](e.call(this,h,k[d]()))});return
c.isWindow(f)?f.document.compatMode==="CSS1Compat"&&f.document.documentElement["client"+b]|
|
f.document.body["client"+b]:f.nodeType===9?Math.max(f.documentElement["client"+
+b],f.body["scroll"+b],f.documentElement["scroll"+b],f.body["offset"+b],f.documentElement["offset"+b]):e===A?parseFloat(c.css(f,d)):this.css(d,typeof
e==="string"?e:e+"px")}})})(window);
=======================================
--- /dev/null
+++ /trunk/root/js/jquery.address.min.js Mon Apr 4 09:08:43 2011
@@ -0,0 +1,32 @@
+/*
+ * jQuery Address Plugin v1.3.2
+ *
http://www.asual.com/jquery/address/
+ *
+ * Copyright (c) 2009-2010 Rostislav Hristov
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ *
http://jquery.org/license
+ *
+ * Date: 2011-02-04 12:34:19 +0200 (Fri, 04 Feb 2011)
+ */
+(function(c){c.address=function(){var
z=function(a){c(c.address).trigger(c.extend(c.Event(a),function(){for(var
b={},e=c.address.parameterNames(),h=0,q=e.length;h<q;h++)b[e[h]]=c.address.parameter(e[h]);return{value:c.address.value(),path:c.address.path(),pathNames:c.address.pathNames(),parameterNames:e,parameters:b,queryString:c.address.queryString()}}.call(c.address)))},A=function(a,b,e){c(c.address).bind(a,b,e);return
c.address},C=function(){return
B.pushState&&d.state!==i},u=function(){return("/"+
+g.pathname.replace(new
RegExp(d.state),"")+g.search+(K()?"#"+K():"")).replace(ba,"/")},K=function(){var
a=g.href.indexOf("#");return
a!=-1?D(g.href.substr(a+1),l):""},w=function(){return
C()?u():K()},va=function(){return"javascript"},r=function(a){a=a.toString();return(d.strict&&a.substr(0,1)!="/"?"/":"")+a},D=function(a,b){if(d.crawlable&&b)return(a!=""?"!":"")+a;return
a.replace(/^\!/,"")},E=function(a,b){return
parseInt(a.css(b),10)},ca=function(a){for(var
b,e,h=0,q=a.childNodes.length;h<q;h++){if(a.childNodes[h].src)b=
+String(a.childNodes[h].src);if(e=ca(a.childNodes[h]))b=e}return
b},O=function(){if(!T){var
a=w(),b=f!=a;if(F&&p<523){if(L!=B.length){L=B.length;if(J[L-1]!==i)f=J[L-1];M(l)}}else
if(b)if(G&&p<7)g.reload();else{G&&p<8&&d.history&&x(W,50);f=a;M(l)}}},M=function(a){z(da);z(a?ea:fa);x(ga,10)},ga=function(){if(d.tracker!=="null"&&d.tracker!==null){var
a=c.isFunction(d.tracker)?d.tracker:k[d.tracker],b=(g.pathname+g.search+(c.address&&!C()?c.address.value():"")).replace(/\/\//,"/").replace(/^\/$/,"");if(c.isFunction(a))a(b);
+else if(c.isFunction(k.urchinTracker))k.urchinTracker(b);else
if(k.pageTracker!==i&&c.isFunction(k.pageTracker._trackPageview))k.pageTracker._trackPageview(b);else
k._gaq!==i&&c.isFunction(k._gaq.push)&&k._gaq.push(["_trackPageview",decodeURI(b)])}},W=function(){var
a=va()+":"+l+";document.open();document.writeln('<html><head><title>"+n.title.replace("'","\\'")+"</title><script>var "+s+'
= "'+encodeURIComponent(w())+(n.domain!=g.hostname?'";document.domain="'+n.domain:"")+"\";<\/script></head></html>');document.close();";
+if(p<7)o.src=a;else
o.contentWindow.location.replace(a)},ia=function(){if(P&&ha!=-1){var
a,b=P.substr(ha+1).split("&");for(v=0;v<b.length;v++){a=b[v].split("=");if(/^(autoUpdate|
crawlable|history|strict|wrap)$/.test(a[0]))d[a[0]]=isNaN(a[1])?/^(true|
yes)$/i.test(a[1]):parseInt(a[1],10)!==0;if(/^(state|
tracker)$/.test(a[0]))d[a[0]]=a[1]}P=null}f=w()},ka=function(){if(!ja){ja=m;ia();var
a=function(){wa.call(this);xa.call(this)},b=c("body").ajaxComplete(a);a();if(d.wrap){c("body
> *").wrapAll('<div style="padding:'+
+(E(b,"marginTop")+E(b,"paddingTop"))+"px "+(E(b,"marginRight")+E(b,"paddingRight"))+"px "+(E(b,"marginBottom")+E(b,"paddingBottom"))+"px "+(E(b,"marginLeft")+E(b,"paddingLeft"))+'px;"
/>').parent().wrap('<div
id="'+s+'"
style="height:100%;overflow:auto;position:relative;'+(F?window.statusbar.visible&&!/chrome/i.test(X)?"":"resize:both;":"")+'"
/>');c("html,
body").css({height:"100%",margin:0,padding:0,overflow:"hidden"});F&&c('<style
type="text/css" />').appendTo("head").text("#"+s+"::-webkit-resizer {
background-color: #fff; }")}if(G&&
+p<8){a=n.getElementsByTagName("frameset")[0];o=n.createElement((a?"":"i")+"frame");if(a){a.insertAdjacentElement("beforeEnd",o);a[a.cols?"cols":"rows"]+=",0";o.noResize=m;o.frameBorder=o.frameSpacing=0}else{o.style.display="none";o.style.width=o.style.height=0;o.tabIndex=-1;n.body.insertAdjacentElement("afterBegin",o)}x(function(){c(o).bind("load",function(){var
e=o.contentWindow;f=e[s]!==i?c.address.decode(e[s]):"";if(f!=w()){M(l);g.hash=D(f,m)}});o.contentWindow[s]===i&&W()},50)}else
if(F){if(p<
+418){c(n.body).append('<form id="'+s+'"
style="position:absolute;top:-9999px;"
method="get"></form>');Y=n.getElementById(s)}if(g[s]===i)g[s]={};if(g[s][g.pathname]!==i)J=g[s][g.pathname].split(",")}x(function(){z("init");M(l)},1);if(!C())if(G&&p>7|
|!G&&"on"+Q in k)if(k.addEventListener)k.addEventListener(Q,O,l);else
k.attachEvent&&k.attachEvent("on"+Q,O);else ya(O,50)}},wa=function(){var
a,b=c("a"),e=b.size(),h=-1;x(function(){if(++h!=e){a=c(b.get(h));
a.is('[rel*="address:"]')&&a.address();x(arguments.callee,
+1)}},1)},za=function(){if(f!=w()){f=w();M(l)}},Aa=function(){if(k.removeEventListener)k.removeEventListener(Q,O,l);else
k.detachEvent&&k.detachEvent("on"+Q,O)},xa=function(){if(d.crawlable){var
a=g.pathname.replace(/\/$/,"");c("body").html().indexOf("_escaped_fragment_")!=-1&&c("a[href]:not([href^=http]), ,
a[href*="+document.domain+"]").each(function(){var
b=c(this).attr("href").replace(/^http:/,"").replace(new
RegExp(a+"/?$"),"");if(b==""|
|
b.indexOf("_escaped_fragment_")!=-1)c(this).attr("href",
+"#"+c.address.decode(b.replace(/\/(.*)\?_escaped_fragment_=(.*)$/,"!$2")))})}},la=function(a){return
a.replace(/\+/g," ")},H=function(a){return
ma(na(a)).replace(/%20/g,"+")},oa=function(a){return
a.split("#")[0].split("?")[0]},pa=function(a){a=oa(a);var
b=a.replace(ba,"/").split("/");if(a.substr(0,1)=="/"|
|
a.length===0)b.splice(0,1);a.substr(a.length-1,1)=="/"&&b.splice(b.length-1,1);return
b},R=function(a){a=a.split("?");return
a.slice(1,a.length).join("?").split("#")[0]},qa=function(a,b){if(b=
+R(b)){params=b.split("&");b=[];for(v=0;v<params.length;v++){var
e=params[v].split("=");if(e[0]==a||
c.address.decode(e[0])==a)b.push(e.slice(1).join("="))}if(b.length!==0)return
b.length!=1?b:b[0]}},ra=function(a){var
b=R(a);a=[];if(b&&b.indexOf("=")!=-1){b=b.split("&");for(var
e=0;e<b.length;e++){var
h=b[e].split("=")[0];c.inArray(h,a)==-1&&a.push(h)}}return
a},U=function(a){a=a.split("#");return
a.slice(1,a.length).join("#")},i,s="jQueryAddress",Q="hashchange",da="change",ea="internalChange",fa=
+"externalChange",m=true,l=false,d={autoUpdate:m,crawlable:l,history:m,strict:m,wrap:l},t=c.browser,p=parseFloat(c.browser.version),sa=t.mozilla,G=t.msie,ta=t.opera,F=t.webkit|
|
t.safari,Z=l,k=function(){try{return
top.document!==i?top:window}catch(a){return
window}}(),n=k.document,B=k.history,g=k.location,ya=setInterval,x=setTimeout,ma=encodeURIComponent,na=decodeURIComponent,ba=/\/{2,9}/g,X=navigator.userAgent,o,Y,P=ca(document),ha=P?P.indexOf("?"):-1,$=n.title,L=B.length,T=l,ja=l,aa=m,ua=m,V=l,J=
+[],f=w();if(G){p=parseFloat(X.substr(X.indexOf("MSIE")+4));if(n.documentMode&&n.documentMode!=p)p=n.documentMode!=8?7:8;c(document).bind("propertychange",function(){if(n.title!=$&&n.title.indexOf("#"+w())!=-1)n.title=$})}if(Z=sa&&p>=1|
|
G&&p>=6||ta&&p>=9.5||F&&p>=312){for(var
v=1;v<L;v++)J.push("");J.push(f);if(ta)history.navigationMode="compatible";if(document.readyState=="complete")var
Ba=setInterval(function(){if(c.address){ka();clearInterval(Ba)}},50);else{ia();c(ka)}t=u();if(d.state!==i)if(B.pushState)t.substr(0,
+3)=="/#/"&&g.replace(d.state.replace(/^\/$/,"")+t.substr(2));else
t!="/"&&t.replace(/^\/#/,"")!=K()&&g.replace(d.state.replace(/^\/$/,"")+"/#"+t);c(window).bind({popstate:za,unload:Aa})}else!Z&&K()!=""|
|
F&&p<418&&K()!=""&&g.search!=""?g.replace(g.href.substr(0,g.href.indexOf("#"))):ga();return{bind:function(a,b,e){return
A(a,b,e)},init:function(a){return A("init",a)},change:function(a){return
A(da,a)},internalChange:function(a){return
A(ea,a)},externalChange:function(a){return A(fa,a)},baseURL:function(){var
a=
+g.href;if(a.indexOf("#")!=-1)a=a.substr(0,a.indexOf("#"));if(/\/$/.test(a))a=a.substr(0,a.length-1);return
a},autoUpdate:function(a){if(a!==i){d.autoUpdate=a;return
this}return
d.autoUpdate},crawlable:function(a){if(a!==i){d.crawlable=a;return
this}return d.crawlable},history:function(a){if(a!==i){d.history=a;return
this}return d.history},state:function(a){if(a!==i){d.state=a;return
this}return d.state},strict:function(a){if(a!==i){d.strict=a;return
this}return d.strict},tracker:function(a){if(a!==
+i){d.tracker=a;return this}return
d.tracker},wrap:function(a){if(a!==i){d.wrap=a;return this}return
d.wrap},update:function(){V=m;this.value(f);V=l;return
this},encode:function(a){var
b=pa(a),e=ra(a),h=R(a),q=U(a),I=a.substr(0,1),N=a.substr(a.length-1),j="";c.each(b,function(y,S){j+="/"+H(S)});if(h!==""){j+="?";if(e.length===0)j+=h;else{c.each(e,function(y,S){y=qa(S,a);if(typeof
y!=="string")c.each(y,function(Da,Ca){j+=H(S)+"="+H(Ca)+"&"});else
j+=H(S)+"="+H(y)+"&"});j=j.substr(0,j.length-1)}}if(q!==
+"")j+="#"+H(q);if(I!="/"&&j.substr(0,1)=="/")j=j.substr(1);if(I=="/"&&j.substr(0,1)!="/")j="/"+j;if(/#|
&|
\?/.test(N))j+=N;return j},decode:function(a){if(a!==i){var
b=[],e=function(I){return na(I.toString().replace(/\+/g,"%20"))};if(typeof
a=="object"&&a.length!==i){for(var
h=0,q=a.length;h<q;h++)b[h]=e(a[h]);return b}else return
e(a)}},title:function(a){if(a!==i){x(function(){$=n.title=a;if(ua&&o&&o.contentWindow&&o.contentWindow.document){o.contentWindow.document.title=a;ua=l}if(!aa&&sa)g.replace(g.href.indexOf("#")!=
+-1?g.href:g.href+"#");aa=l},50);return this}return
n.title},value:function(a){if(a!==i){a=r(a);if(d.autoUpdate)a=this.encode(a);if(a=="/")a="";if(f==a&&!V)return;aa=m;f=a;if(d.autoUpdate|
|
V){M(m);if(C())B[d.history?"pushState":"replaceState"]({},"",d.state.replace(/\/$/,"")+(f==""?"/":f));else{T=m;J[B.length]=f;if(F)if(d.history){g[s][g.pathname]=J.toString();L=B.length+1;if(p<418){if(g.search==""){Y.action="#"+D(f,m);Y.submit()}}else
if(p<523||f==""){a=n.createEvent("MouseEvents");a.initEvent("click",
+m,m);var b=n.createElement("a");b.href="#"+D(f,m);b.dispatchEvent(a)}else
g.hash="#"+D(f,m)}else g.replace("#"+D(f,m));else
if(f!=w())if(d.history)g.hash="#"+D(this.decode(r(f)),m);else
g.replace("#"+D(f,m));G&&p<8&&d.history&&x(W,50);if(F)x(function(){T=l},1);else
T=l}}return this}if(!Z)return null;return
this.decode(r(f))},path:function(a){if(a!==i){var
b=R(r(f)),e=U(r(f));this.value(a+(b?"?"+b:"")+(e?"#"+e:""));return
this}return this.decode(oa(r(f)))},pathNames:function(){return
this.decode(pa(r(f)))},
+queryString:function(a){if(a!==i){var
b=U(r(f));this.value(this.path()+(a?"?"+a:"")+(b?"#"+b:""));return
this}return this.decode(R(r(f)))},parameter:function(a,b,e){var
h,q;if(b!==i){var
I=this.parameterNames();q=[];b=b?ma(b):"";for(h=0;h<I.length;h++){var
N=I[h],j=this.parameter(N);if(typeof j=="string")j=[j];if(N==a)j=b===null||
b===""?[]:e?j.concat([b]):[b];for(var
y=0;y<j.length;y++)q.push(N+"="+la(H(j[y])))}c.inArray(a,I)==-1&&b!==null&&b!==""&&q.push(a+"="+la(H(b)));this.queryString(q.join("&"));
+return this}return
this.decode(qa(a,r(f)))},parameterNames:function(){return
this.decode(ra(r(f)))},hash:function(a){if(a!==i){this.value(r(f).split("#")[0]+(a?"#"+a:""));return
this}return
this.decode(U(r(f)))}}}();c.fn.address=function(z){if(!c(this).attr("address")){var
A=function(C){if(c(this).is("a")){var
u=z?z.call(this):/address:/.test(c(this).attr("rel"))?c(this).attr("rel").split("address:")[1].split(" ")[0]:c.address.state()!==undefined&&c.address.state()!="/"?c(this).attr("href").replace(new
RegExp("^(.*"+
+c.address.state()+"|\\.)"),""):c(this).attr("href").replace(/^(#\!?|
\.)/,"");c.address.value(u);C.preventDefault()}};c(this).click(A).live("click",A).live("submit",function(C){if(c(this).is("form")){var
u=c(this).attr("action");u=z?z.call(this):(u.indexOf("?")!=-1?u.replace(/&$/,""):u+"?")+c.address.decode(c(this).serialize());c.address.value(u);C.preventDefault()}}).attr("address",true)}return
this}})(jQuery);
=======================================
--- /dev/null
+++ /trunk/root/js/jquery.blockUI.js Mon Apr 4 09:08:43 2011
@@ -0,0 +1,493 @@
+/*!
+ * jQuery blockUI plugin
+ * Version 2.38 (29-MAR-2011)
+ * @requires jQuery v1.2.3 or later
+ *
+ * Examples at:
http://malsup.com/jquery/block/
+ * Copyright (c) 2007-2010 M. Alsup
+ * Dual licensed under the MIT and GPL licenses:
+ *
http://www.opensource.org/licenses/mit-license.php
+ *
http://www.gnu.org/licenses/gpl.html
+ *
+ * Thanks to Amir-Hossein Sobhi for some excellent contributions!
+ */
+
+;(function($) {
+
+if (/1\.(0|1|2)\.(0|1|2)/.test($.fn.jquery) || /^1.1/.test($.fn.jquery)) {
+ alert('blockUI requires jQuery v1.2.3 or later! You are using v' +
$.fn.jquery);
+ return;
+}
+
+$.fn._fadeIn = $.fn.fadeIn;
+
+var noOp = function() {};
+
+// this bit is to ensure we don't call setExpression when we shouldn't
(with extra muscle to handle
+// retarded userAgent strings on Vista)
+var mode = document.documentMode || 0;
+var setExpr = $.browser.msie && (($.browser.version < 8 && !mode) || mode
< 8);
+var ie6 = $.browser.msie && /MSIE 6.0/.test(navigator.userAgent) && !mode;
+
+// global $ methods for blocking/unblocking the entire page
+$.blockUI = function(opts) { install(window, opts); };
+$.unblockUI = function(opts) { remove(window, opts); };
+
+// convenience method for quick growl-like notifications
(
http://www.google.com/search?q=growl)
+$.growlUI = function(title, message, timeout, onClose) {
+ var $m = $('<div class="growlUI"></div>');
+ if (title) $m.append('<h1>'+title+'</h1>');
+ if (message) $m.append('<h2>'+message+'</h2>');
+ if (timeout == undefined) timeout = 3000;
+ $.blockUI({
+ message: $m, fadeIn: 700, fadeOut: 1000, centerY: false,
+ timeout: timeout, showOverlay: false,
+ onUnblock: onClose,
+ css: $.blockUI.defaults.growlCSS
+ });
+};
+
+// plugin method for blocking element content
+$.fn.block = function(opts) {
+ return this.unblock({ fadeOut: 0 }).each(function() {
+ if ($.css(this,'position') == 'static')
+ this.style.position = 'relative';
+ if ($.browser.msie)
+ this.style.zoom = 1; // force 'hasLayout'
+ install(this, opts);
+ });
+};
+
+// plugin method for unblocking element content
+$.fn.unblock = function(opts) {
+ return this.each(function() {
+ remove(this, opts);
+ });
+};
+
+$.blockUI.version = 2.38; // 2nd generation blocking at no extra cost!
+
+// override these in your code to change the default behavior and style
+$.blockUI.defaults = {
+ // message displayed when blocking (use null for no message)
+ message: '<h1>Please wait...</h1>',
+
+ title: null, // title string; only used when theme == true
+ draggable: true, // only used when theme == true (requires jquery-ui.js
to be loaded)
+
+ theme: false, // set to true to use with jQuery UI themes
+
+ // styles for the message when blocking; if you wish to disable
+ // these and use an external stylesheet then do this in your code:
+ // $.blockUI.defaults.css = {};
+ css: {
+ padding: 0,
+ margin: 0,
+ width: '30%',
+ top: '40%',
+ left: '35%',
+ textAlign: 'center',
+ color: '#000',
+ border: '3px solid #aaa',
+ backgroundColor:'#fff',
+ cursor: 'wait'
+ },
+
+ // minimal style set used when themes are used
+ themedCSS: {
+ width: '30%',
+ top: '40%',
+ left: '35%'
+ },
+
+ // styles for the overlay
+ overlayCSS: {
+ backgroundColor: '#000',
+ opacity: 0.6,
+ cursor: 'wait'
+ },
+
+ // styles applied when using $.growlUI
+ growlCSS: {
+ width: '350px',
+ top: '10px',
+ left: '',
+ right: '10px',
+ border: 'none',
+ padding: '5px',
+ opacity: 0.6,
+ cursor: 'default',
+ color: '#fff',
+ backgroundColor: '#000',
+ '-webkit-border-radius': '10px',
+ '-moz-border-radius': '10px',
+ 'border-radius': '10px'
+ },
+
+ // IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w
+ // (hat tip to Jorge H. N. de Vasconcelos)
+ iframeSrc: /^https/i.test(window.location.href |
| '') ? 'javascript:false' : 'about:blank',
+
+ // force usage of iframe in non-IE browsers (handy for blocking applets)
+ forceIframe: false,
+
+ // z-index for the blocking overlay
+ baseZ: 1000,
+
+ // set these to true to have the message automatically centered
+ centerX: true, // <-- only effects element blocking (page block
controlled via css above)
+ centerY: true,
+
+ // allow body element to be stetched in ie6; this makes blocking look
better
+ // on "short" pages. disable if you wish to prevent changes to the body
height
+ allowBodyStretch: true,
+
+ // enable if you want key and mouse events to be disabled for content
that is blocked
+ bindEvents: true,
+
+ // be default blockUI will supress tab navigation from leaving blocking
content
+ // (if bindEvents is true)
+ constrainTabKey: true,
+
+ // fadeIn time in millis; set to 0 to disable fadeIn on block
+ fadeIn: 200,
+
+ // fadeOut time in millis; set to 0 to disable fadeOut on unblock
+ fadeOut: 400,
+
+ // time in millis to wait before auto-unblocking; set to 0 to disable
auto-unblock
+ timeout: 0,
+
+ // disable if you don't want to show the overlay
+ showOverlay: true,
+
+ // if true, focus will be placed in the first available input field when
+ // page blocking
+ focusInput: true,
+
+ // suppresses the use of overlay styles on FF/Linux (due to performance
issues with opacity)
+ applyPlatformOpacityRules: true,
+
+ // callback method invoked when fadeIn has completed and blocking message
is visible
+ onBlock: null,
+
+ // callback method invoked when unblocking has completed; the callback is
+ // passed the element that has been unblocked (which is the window object
for page
+ // blocks) and the options that were passed to the unblock call:
+ // onUnblock(element, options)
+ onUnblock: null,
+
+ // don't ask; if you really must know:
http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
+ quirksmodeOffsetHack: 4,
+
+ // class name of the message block
+ blockMsgClass: 'blockMsg'
+};
+
+// private data and functions follow...
+
+var pageBlock = null;
+var pageBlockEls = [];
+
+function install(el, opts) {
+ var full = (el == window);
+ var msg = opts && opts.message !== undefined ? opts.message : undefined;
+ opts = $.extend({}, $.blockUI.defaults, opts || {});
+ opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS,
opts.overlayCSS || {});
+ var css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
+ var themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS
|| {});
+ msg = msg === undefined ? opts.message : msg;
+
+ // remove the current block (if there is one)
+ if (full && pageBlock)
+ remove(window, {fadeOut:0});
+
+ // if an existing element is being used as the blocking content then we
capture
+ // its current place in the DOM (and current display style) so we can
restore
+ // it when we unblock
+ if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
+ var node = msg.jquery ? msg[0] : msg;
+ var data = {};
+ $(el).data('blockUI.history', data);
+ data.el = node;
+ data.parent = node.parentNode;
+ data.display = node.style.display;
+ data.position = node.style.position;
+ if (data.parent)
+ data.parent.removeChild(node);
+ }
+
+ var z = opts.baseZ;
+
+ // blockUI uses 3 layers for blocking, for simplicity they are all used
on every platform;
+ // layer1 is the iframe layer which is used to supress bleed through of
underlying content
+ // layer2 is the overlay layer which has opacity and a wait cursor (by
default)
+ // layer3 is the message content that is displayed while blocking
+
+ var lyr1 = ($.browser.msie || opts.forceIframe)
+ ? $('<iframe class="blockUI" style="z-index:'+ (z++)
+';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0"
src="'+opts.iframeSrc+'"></iframe>')
+ : $('<div class="blockUI" style="display:none"></div>');
+
+ var lyr2 = opts.theme
+ ? $('<div class="blockUI blockOverlay ui-widget-overlay"
style="z-index:'+ (z++) +';display:none"></div>')
+ : $('<div class="blockUI blockOverlay" style="z-index:'+ (z++)
+';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');
+
+ var lyr3, s;
+ if (opts.theme && full) {
+ s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage ui-dialog
ui-widget ui-corner-all"
style="z-index:'+z+';display:none;position:fixed">' +
+ '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all
blockTitle">'+(opts.title || ' ')+'</div>' +
+ '<div class="ui-widget-content ui-dialog-content"></div>' +
+ '</div>';
+ }
+ else if (opts.theme) {
+ s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement
ui-dialog ui-widget ui-corner-all"
style="z-index:'+z+';display:none;position:absolute">' +
+ '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all
blockTitle">'+(opts.title || ' ')+'</div>' +
+ '<div class="ui-widget-content ui-dialog-content"></div>' +
+ '</div>';
+ }
+ else if (full) {
+ s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage"
style="z-index:'+z+';display:none;position:fixed"></div>';
+ }
+ else {
+ s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement"
style="z-index:'+z+';display:none;position:absolute"></div>';
+ }
+ lyr3 = $(s);
+
+ // if we have a message, style it
+ if (msg) {
+ if (opts.theme) {
+ lyr3.css(themedCSS);
+ lyr3.addClass('ui-widget-content');
+ }
+ else
+ lyr3.css(css);
+ }
+
+ // style the overlay
+ if (!opts.theme && (!opts.applyPlatformOpacityRules |
| !($.browser.mozilla && /Linux/.test(navigator.platform))))
+ lyr2.css(opts.overlayCSS);
+ lyr2.css('position', full ? 'fixed' : 'absolute');
+
+ // make iframe layer transparent in IE
+ if ($.browser.msie || opts.forceIframe)
+ lyr1.css('opacity',0.0);
+
+ //$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
+ var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el);
+ $.each(layers, function() {
+ this.appendTo($par);
+ });
+
+ if (opts.theme && opts.draggable && $.fn.draggable) {
+ lyr3.draggable({
+ handle: '.ui-dialog-titlebar',
+ cancel: 'li'
+ });
+ }
+
+ // ie7 must use absolute positioning in quirks mode and to account for
activex issues (when scrolling)
+ var expr = setExpr && (!$.boxModel || $('object,embed', full ? null :
el).length > 0);
+ if (ie6 || expr) {
+ // give body 100% height
+ if (full && opts.allowBodyStretch && $.boxModel)
+ $('html,body').css('height','100%');
+
+ // fix ie6 issue when blocked element has a border width
+ if ((ie6 || !$.boxModel) && !full) {
+ var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');
+ var fixT = t ? '(0 - '+t+')' : 0;
+ var fixL = l ? '(0 - '+l+')' : 0;
+ }
+
+ // simulate fixed position
+ $.each([lyr1,lyr2,lyr3], function(i,o) {
+ var s = o[0].style;
+ s.position = 'absolute';
+ if (i < 2) {
+ full ? s.setExpression('height','Math.max(document.body.scrollHeight,
document.body.offsetHeight) -
(jQuery.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"')
+ : s.setExpression('height','this.parentNode.offsetHeight + "px"');
+ full ? s.setExpression('width','jQuery.boxModel &&
document.documentElement.clientWidth || document.body.clientWidth + "px"')
+ : s.setExpression('width','this.parentNode.offsetWidth + "px"');
+ if (fixL) s.setExpression('left', fixL);
+ if (fixT) s.setExpression('top', fixT);
+ }
+ else if (opts.centerY) {
+ if (full)
s.setExpression('top','(document.documentElement.clientHeight ||
document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah =
document.documentElement.scrollTop ? document.documentElement.scrollTop :
document.body.scrollTop) + "px"');
+ s.marginTop = 0;
+ }
+ else if (!opts.centerY && full) {
+ var top = (opts.css && opts.css.top) ? parseInt(opts.css.top) : 0;
+ var expression = '((document.documentElement.scrollTop ?
document.documentElement.scrollTop : document.body.scrollTop) + '+top+')
+ "px"';
+ s.setExpression('top',expression);
+ }
+ });
+ }
+
+ // show the message
+ if (msg) {
+ if (opts.theme)
+ lyr3.find('.ui-widget-content').append(msg);
+ else
+ lyr3.append(msg);
+ if (msg.jquery || msg.nodeType)
+ $(msg).show();
+ }
+
+ if (($.browser.msie || opts.forceIframe) && opts.showOverlay)
+ lyr1.show(); // opacity is zero
+ if (opts.fadeIn) {
+ var cb = opts.onBlock ? opts.onBlock : noOp;
+ var cb1 = (opts.showOverlay && !msg) ? cb : noOp;
+ var cb2 = msg ? cb : noOp;
+ if (opts.showOverlay)
+ lyr2._fadeIn(opts.fadeIn, cb1);
+ if (msg)
+ lyr3._fadeIn(opts.fadeIn, cb2);
+ }
+ else {
+ if (opts.showOverlay)
+ lyr2.show();
+ if (msg)
+ lyr3.show();
+ if (opts.onBlock)
+ opts.onBlock();
+ }
+
+ // bind key and mouse events
+ bind(1, el, opts);
+
+ if (full) {
+ pageBlock = lyr3[0];
+ pageBlockEls = $(':input:enabled:visible',pageBlock);
+ if (opts.focusInput)
+ setTimeout(focus, 20);
+ }
+ else
+ center(lyr3[0], opts.centerX, opts.centerY);
+
+ if (opts.timeout) {
+ // auto-unblock
+ var to = setTimeout(function() {
+ full ? $.unblockUI(opts) : $(el).unblock(opts);
+ }, opts.timeout);
+ $(el).data('blockUI.timeout', to);
+ }
+};
+
+// remove the block
+function remove(el, opts) {
+ var full = (el == window);
+ var $el = $(el);
+ var data = $el.data('blockUI.history');
+ var to = $el.data('blockUI.timeout');
+ if (to) {
+ clearTimeout(to);
+ $el.removeData('blockUI.timeout');
+ }
+ opts = $.extend({}, $.blockUI.defaults, opts || {});
+ bind(0, el, opts); // unbind events
+
+ var els;
+ if (full) // crazy selector to handle odd field errors in ie6/7
+ els = $('body').children().filter('.blockUI').add('body > .blockUI');
+ else
+ els = $('.blockUI', el);
+
+ if (full)
+ pageBlock = pageBlockEls = null;
+
+ if (opts.fadeOut) {
+ els.fadeOut(opts.fadeOut);
+ setTimeout(function() { reset(els,data,opts,el); }, opts.fadeOut);
+ }
+ else
+ reset(els, data, opts, el);
+};
+
+// move blocking element back into the DOM where it started
+function reset(els,data,opts,el) {
+ els.each(function(i,o) {
+ // remove via DOM calls so we don't lose event handlers
+ if (this.parentNode)
+ this.parentNode.removeChild(this);
+ });
+
+ if (data && data.el) {
+ data.el.style.display = data.display;
+ data.el.style.position = data.position;
+ if (data.parent)
+ data.parent.appendChild(data.el);
+ $(el).removeData('blockUI.history');
+ }
+
+ if (typeof opts.onUnblock == 'function')
+ opts.onUnblock(el,opts);
+};
+
+// bind/unbind the handler
+function bind(b, el, opts) {
+ var full = el == window, $el = $(el);
+
+ // don't bother unbinding if there is nothing to unbind
+ if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))
+ return;
+ if (!full)
+ $el.data('blockUI.isBlocked', b);
+
+ // don't bind events when overlay is not in use or if bindEvents is false
+ if (!opts.bindEvents || (b && !opts.showOverlay))
+ return;
+
+ // bind anchors and inputs for mouse and key events
+ var events = 'mousedown mouseup keydown keypress';
+ b ? $(document).bind(events, opts, handler) : $(document).unbind(events,
handler);
+
+// former impl...
+// var $e = $('a,:input');
+// b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
+};
+
+// event handler to suppress keyboard/mouse events when blocking
+function handler(e) {
+ // allow tab navigation (conditionally)
+ if (e.keyCode && e.keyCode == 9) {
+ if (pageBlock && e.data.constrainTabKey) {
+ var els = pageBlockEls;
+ var fwd = !e.shiftKey && e.target === els[els.length-1];
+ var back = e.shiftKey && e.target === els[0];
+ if (fwd || back) {
+ setTimeout(function(){focus(back)},10);
+ return false;
+ }
+ }
+ }
+ var opts = e.data;
+ // allow events within the message content
+ if ($(e.target).parents('div.' + opts.blockMsgClass).length > 0)
+ return true;
+
+ // allow events for content that is not being blocked
+ return $(e.target).parents().children().filter('div.blockUI').length == 0;
+};
+
+function focus(back) {
+ if (!pageBlockEls)
+ return;
+ var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];
+ if (e)
+ e.focus();
+};
+
+function center(el, x, y) {
+ var p = el.parentNode, s = el.style;
+ var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');
+ var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');
+ if (x) s.left = l > 0 ? (l+'px') : '0';
+ if (y) s.top = t > 0 ? (t+'px') : '0';
+};
+
+function sz(el, p) {
+ return parseInt($.css(el,p))||0;
+};
+
+})(jQuery);
=======================================
--- /dev/null
+++ /trunk/root/js/jquery.form.js Mon Apr 4 09:08:43 2011
@@ -0,0 +1,813 @@
+/*!
+ * jQuery Form Plugin
+ * version: 2.67 (12-MAR-2011)
+ * @requires jQuery v1.3.2 or later
+ *
+ * Examples and documentation at:
http://malsup.com/jquery/form/
+ * Dual licensed under the MIT and GPL licenses:
+ *
http://www.opensource.org/licenses/mit-license.php
+ *
http://www.gnu.org/licenses/gpl.html
+ */
+;(function($) {
+
+/*
+ Usage Note:
+ -----------
+ Do not use both ajaxSubmit and ajaxForm on the same form. These
+ functions are intended to be exclusive. Use ajaxSubmit if you want
+ to bind your own submit handler to the form. For example,
+
+ $(document).ready(function() {
+ $('#myForm').bind('submit', function(e) {
+ e.preventDefault(); // <-- important
+ $(this).ajaxSubmit({
+ target: '#output'
+ });
+ });
+ });
+
+ Use ajaxForm when you want the plugin to manage all the event binding
+ for you. For example,
+
+ $(document).ready(function() {
+ $('#myForm').ajaxForm({
+ target: '#output'
+ });
+ });
+
+ When using ajaxForm, the ajaxSubmit function will be invoked for you
+ at the appropriate time.
+*/
+
+/**
+ * ajaxSubmit() provides a mechanism for immediately submitting
+ * an HTML form using AJAX.
+ */
+$.fn.ajaxSubmit = function(options) {
+ // fast fail if nothing selected (
http://dev.jquery.com/ticket/2752)
+ if (!this.length) {
+ log('ajaxSubmit: skipping submit process - no element selected');
+ return this;
+ }
+
+ if (typeof options == 'function') {
+ options = { success: options };
+ }
+
+ var action = this.attr('action');
+ var url = (typeof action === 'string') ? $.trim(action) : '';
+ if (url) {
+ // clean url (don't include hash vaue)
+ url = (url.match(/^([^#]+)/)||[])[1];
+ }
+ url = url || window.location.href || '';
+
+ options = $.extend(true, {
+ url: url,
+ type: this[0].getAttribute('method') || 'GET', // IE7 massage (see issue
57)
+ iframeSrc: /^https/i.test(window.location.href |
| '') ? 'javascript:false' : 'about:blank'
+ }, options);
+
+ // hook for manipulating the form data before it is extracted;
+ // convenient for use with rich editors like tinyMCE or FCKEditor
+ var veto = {};
+ this.trigger('form-pre-serialize', [this, options, veto]);
+ if (veto.veto) {
+ log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
+ return this;
+ }
+
+ // provide opportunity to alter form data before it is serialized
+ if (options.beforeSerialize && options.beforeSerialize(this, options) ===
false) {
+ log('ajaxSubmit: submit aborted via beforeSerialize callback');
+ return this;
+ }
+
+ var n,v,a = this.formToArray(options.semantic);
+ if (options.data) {
+ options.extraData = options.data;
+ for (n in options.data) {
+ if(options.data[n] instanceof Array) {
+ for (var k in options.data[n]) {
+ a.push( { name: n, value: options.data[n][k] } );
+ }
+ }
+ else {
+ v = options.data[n];
+ v = $.isFunction(v) ? v() : v; // if value is fn, invoke it
+ a.push( { name: n, value: v } );
+ }
+ }
+ }
+
+ // give pre-submit callback an opportunity to abort the submit
+ if (options.beforeSubmit && options.beforeSubmit(a, this, options) ===
false) {
+ log('ajaxSubmit: submit aborted via beforeSubmit callback');
+ return this;
+ }
+
+ // fire vetoable 'validate' event
+ this.trigger('form-submit-validate', [a, this, options, veto]);
+ if (veto.veto) {
+ log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
+ return this;
+ }
+
+ var q = $.param(a);
+
+ if (options.type.toUpperCase() == 'GET') {
+ options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
+ options.data = null; // data is null for 'get'
+ }
+ else {
+ options.data = q; // data is the query string for 'post'
+ }
+
+ var $form = this, callbacks = [];
+ if (options.resetForm) {
+ callbacks.push(function() { $form.resetForm(); });
+ }
+ if (options.clearForm) {
+ callbacks.push(function() { $form.clearForm(); });
+ }
+
+ // perform a load on the target only if dataType is not provided
+ if (!options.dataType && options.target) {
+ var oldSuccess = options.success || function(){};
+ callbacks.push(function(data) {
+ var fn = options.replaceTarget ? 'replaceWith' : 'html';
+ $(options.target)[fn](data).each(oldSuccess, arguments);
+ });
+ }
+ else if (options.success) {
+ callbacks.push(options.success);
+ }
+
+ options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr
as 3rd arg
+ var context = options.context || options; // jQuery 1.4+ supports
scope context
+ for (var i=0, max=callbacks.length; i < max; i++) {
+ callbacks[i].apply(context, [data, status, xhr || $form, $form]);
+ }
+ };
+
+ // are there files to upload?
+ var fileInputs = $('input:file', this).length > 0;
+ var mp = 'multipart/form-data';
+ var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') ==
mp);
+
+ // options.iframe allows user to force iframe mode
+ // 06-NOV-09: now defaulting to iframe mode if file input is detected
+ if (options.iframe !== false && (fileInputs || options.iframe ||
multipart)) {
+ // hack to fix Safari hang (thanks to Tim Molendijk for this)
+ // see:
http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
+ if (options.closeKeepAlive) {
+ $.get(options.closeKeepAlive, fileUpload);
+ }
+ else {
+ fileUpload();
+ }
+ }
+ else {
+ $.ajax(options);
+ }
+
+ // fire 'notify' event
+ this.trigger('form-submit-notify', [this, options]);
+ return this;
+
+
+ // private function for handling file uploads (hat tip to YAHOO!)
+ function fileUpload() {
+ var form = $form[0];
+
+ if ($(':input[name=submit],:input[id=submit]', form).length) {
+ // if there is an input with a name or id of 'submit' then we won't be
+ // able to invoke the submit fn on the form (at least not x-browser)
+ alert('Error: Form elements must not have name or id of "submit".');
+ return;
+ }
+
+ var s = $.extend(true, {}, $.ajaxSettings, options);
+ s.context = s.context || s;
+ var id = 'jqFormIO' + (new Date().getTime()), fn = '_'+id;
+ var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+
s.iframeSrc +'" />');
+ var io = $io[0];
+
+ $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
+
+ var xhr = { // mock object
+ aborted: 0,
+ responseText: null,
+ responseXML: null,
+ status: 0,
+ statusText: 'n/a',
+ getAllResponseHeaders: function() {},
+ getResponseHeader: function() {},
+ setRequestHeader: function() {},
+ abort: function() {
+ log('aborting upload...');
+ var e = 'aborted';
+ this.aborted = 1;
+ $io.attr('src', s.iframeSrc); // abort op in progress
+ xhr.error = e;
+ s.error && s.error.call(s.context, xhr, 'error', e);
+ g && $.event.trigger("ajaxError", [xhr, s, e]);
+ s.complete && s.complete.call(s.context, xhr, 'error');
+ }
+ };
+
+ var g = s.global;
+ // trigger ajax global events so that activity/block indicators work
like normal
+ if (g && ! $.active++) {
+ $.event.trigger("ajaxStart");
+ }
+ if (g) {
+ $.event.trigger("ajaxSend", [xhr, s]);
+ }
+
+ if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
+ if (s.global) {
+ $.active--;
+ }
+ return;
+ }
+ if (xhr.aborted) {
+ return;
+ }
+
+ var timedOut = 0;
+
+ // add submitting element to data if we know it
+ var sub = form.clk;
+ if (sub) {
+ var n =
sub.name;
+ if (n && !sub.disabled) {
+ s.extraData = s.extraData || {};
+ s.extraData[n] = sub.value;
+ if (sub.type == "image") {
+ s.extraData[n+'.x'] = form.clk_x;
+ s.extraData[n+'.y'] = form.clk_y;
+ }
+ }
+ }
+
+ // take a breath so that pending repaints get some cpu time before the
upload starts
+ function doSubmit() {
+ // make sure form attrs are set
+ var t = $form.attr('target'), a = $form.attr('action');
+
+ // update form attrs in IE friendly way
+ form.setAttribute('target',id);
+ if (form.getAttribute('method') != 'POST') {
+ form.setAttribute('method', 'POST');
+ }
+ if (form.getAttribute('action') != s.url) {
+ form.setAttribute('action', s.url);
+ }
+
+ // ie borks in some cases when setting encoding
+ if (! s.skipEncodingOverride) {
+ $form.attr({
+ encoding: 'multipart/form-data',
+ enctype: 'multipart/form-data'
+ });
+ }
+
+ // support timout
+ if (s.timeout) {
+ setTimeout(function() { timedOut = true; cb(); }, s.timeout);
+ }
+
+ // add "extra" data to form if provided in options
+ var extraInputs = [];
+ try {
+ if (s.extraData) {
+ for (var n in s.extraData) {
+ extraInputs.push(
+ $('<input type="hidden" name="'+n+'" value="'+s.extraData[n]+'" />')
+ .appendTo(form)[0]);
+ }
+ }
+
+ // add iframe to doc and submit the form
+ $io.appendTo('body');
+ io.attachEvent ? io.attachEvent('onload', cb) :
io.addEventListener('load', cb, false);
+ form.submit();
+ }
+ finally {
+ // reset attrs and remove "extra" input elements
+ form.setAttribute('action',a);
+ if(t) {
+ form.setAttribute('target', t);
+ } else {
+ $form.removeAttr('target');
+ }
+ $(extraInputs).remove();
+ }
+ }
+
+ if (s.forceSync) {
+ doSubmit();
+ }
+ else {
+ setTimeout(doSubmit, 10); // this lets dom updates render
+ }
+
+ var data, doc, domCheckCount = 50;
+
+ function cb() {
+ if (xhr.aborted) {
+ return;
+ }
+
+ var doc = io.contentWindow ? io.contentWindow.document :
io.contentDocument ? io.contentDocument : io.document;
+ if (!doc || doc.location.href == s.iframeSrc) {
+ // response not received yet
+ return;
+ }
+ io.detachEvent ? io.detachEvent('onload', cb) :
io.removeEventListener('load', cb, false);
+
+ var ok = true;
+ try {
+ if (timedOut) {
+ throw 'timeout';
+ }
+
+ var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
+ log('isXml='+isXml);
+ if (!isXml && window.opera && (doc.body == null || doc.body.innerHTML
== '')) {
+ if (--domCheckCount) {
+ // in some browsers (Opera) the iframe DOM is not always traversable
when
+ // the onload callback fires, so we loop a bit to accommodate
+ log('requeing onLoad callback, DOM not available');
+ setTimeout(cb, 250);
+ return;
+ }
+ // let this fall through because server response could be an empty
document
+ //log('Could not access iframe DOM after mutiple tries.');
+ //throw 'DOMException: not available';
+ }
+
+ //log('response detected');
+ xhr.responseText = doc.body ? doc.body.innerHTML :
doc.documentElement ? doc.documentElement.innerHTML : null;
+ xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
+ xhr.getResponseHeader = function(header){
+ var headers = {'content-type': s.dataType};
+ return headers[header];
+ };
+
+ var scr = /(json|script)/.test(s.dataType);
+ if (scr || s.textarea) {
+ // see if user embedded response in textarea
+ var ta = doc.getElementsByTagName('textarea')[0];
+ if (ta) {
+ xhr.responseText = ta.value;
+ }
+ else if (scr) {
+ // account for browsers injecting pre around json response
+ var pre = doc.getElementsByTagName('pre')[0];
+ var b = doc.getElementsByTagName('body')[0];
+ if (pre) {
+ xhr.responseText = pre.textContent;
+ }
+ else if (b) {
+ xhr.responseText = b.innerHTML;
+ }
+ }
+ }
+ else if (s.dataType == 'xml' && !xhr.responseXML &&
xhr.responseText != null) {
+ xhr.responseXML = toXml(xhr.responseText);
+ }
+
+ data = httpData(xhr, s.dataType, s);
+ }
+ catch(e){
+ log('error caught:',e);
+ ok = false;
+ xhr.error = e;
+ s.error && s.error.call(s.context, xhr, 'error', e);
+ g && $.event.trigger("ajaxError", [xhr, s, e]);
+ }
+
+ if (xhr.aborted) {
+ log('upload aborted');
+ ok = false;
+ }
+
+ // ordering of these callbacks/triggers is odd, but that's how $.ajax
does it
+ if (ok) {
+ s.success && s.success.call(s.context, data, 'success', xhr);
+ g && $.event.trigger("ajaxSuccess", [xhr, s]);
+ }
+
+ g && $.event.trigger("ajaxComplete", [xhr, s]);
+
+ if (g && ! --$.active) {
+ $.event.trigger("ajaxStop");
+ }
+
+ s.complete && s.complete.call(s.context, xhr, ok ? 'success' : 'error');
+
+ // clean up
+ setTimeout(function() {
+ $io.removeData('form-plugin-onload');
+ $io.remove();
+ xhr.responseXML = null;
+ }, 100);
+ }
+
+ var toXml = $.parseXML || function(s, doc) { // use parseXML if
available (jQuery 1.5+)
+ if (window.ActiveXObject) {
+ doc = new ActiveXObject('Microsoft.XMLDOM');
+ doc.async = 'false';
+ doc.loadXML(s);
+ }
+ else {
+ doc = (new DOMParser()).parseFromString(s, 'text/xml');
+ }
+ return (doc && doc.documentElement &&
doc.documentElement.nodeName != 'parsererror') ? doc : null;
+ };
+ var parseJSON = $.parseJSON || function(s) {
+ return window['eval']('(' + s + ')');
+ };
+
+ var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
+ var ct = xhr.getResponseHeader('content-type') || '',
+ xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
+ data = xml ? xhr.responseXML : xhr.responseText;
+
+ if (xml && data.documentElement.nodeName === 'parsererror') {
+ $.error && $.error('parsererror');
+ }
+ if (s && s.dataFilter) {
+ data = s.dataFilter(data, type);
+ }
+ if (typeof data === 'string') {
+ if (type === 'json' || !type && ct.indexOf('json') >= 0) {
+ data = parseJSON(data);
+ } else if (type === "script" || !type && ct.indexOf("javascript") >=
0) {
+ $.globalEval(data);
+ }
+ }
+ return data;
+ };
+ }
+};
+
+/**
+ * ajaxForm() provides a mechanism for fully automating form submission.
+ *
+ * The advantages of using this method instead of ajaxSubmit() are:
+ *
+ * 1: This method will include coordinates for <input type="image" />
elements (if the element
+ * is used to submit the form).
+ * 2. This method will include the submit element's name/value data (for
the element that was
+ * used to submit the form).
+ * 3. This method binds the submit() method to the form for you.
+ *
+ * The options argument for ajaxForm works exactly as it does for
ajaxSubmit. ajaxForm merely
+ * passes the options argument along after properly binding events for
submit elements and
+ * the form itself.
+ */
+$.fn.ajaxForm = function(options) {
+ // in jQuery 1.3+ we can fix mistakes with the ready state
+ if (this.length === 0) {
+ var o = { s: this.selector, c: this.context };
+ if (!$.isReady && o.s) {
+ log('DOM not ready, queuing ajaxForm');
+ $(function() {
+ $(o.s,o.c).ajaxForm(options);
+ });
+ return this;
+ }
+ // is your DOM ready?
http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
+ log('terminating; zero elements found by selector' + ($.isReady ? '' : '
(DOM not ready)'));
+ return this;
+ }
+
+ return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) {
+ if (!e.isDefaultPrevented()) { // if event has been canceled, don't
proceed
+ e.preventDefault();
+ $(this).ajaxSubmit(options);
+ }
+ }).bind('click.form-plugin', function(e) {
+ var target = e.target;
+ var $el = $(target);
+ if (!($
el.is(":submit,input:image"))) {
+ // is this a child element of the submit el? (ex: a span within a
button)
+ var t = $el.closest(':submit');
+ if (t.length == 0) {
+ return;
+ }
+ target = t[0];
+ }
+ var form = this;
+ form.clk = target;
+ if (target.type == 'image') {
+ if (e.offsetX != undefined) {
+ form.clk_x = e.offsetX;
+ form.clk_y = e.offsetY;
+ } else if (typeof $.fn.offset == 'function') { // try to use dimensions
plugin
+ var offset = $el.offset();
+ form.clk_x = e.pageX - offset.left;
+ form.clk_y = e.pageY - offset.top;
+ } else {
+ form.clk_x = e.pageX - target.offsetLeft;
+ form.clk_y = e.pageY - target.offsetTop;
+ }
+ }
+ // clear form vars
+ setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; },
100);
+ });
+};
+
+// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
+$.fn.ajaxFormUnbind = function() {
+ return this.unbind('submit.form-plugin click.form-plugin');
+};
+
+/**
+ * formToArray() gathers form element data into an array of objects that
can
+ * be passed to any of the following ajax functions: $.get, $.post, or
load.
+ * Each object in the array has both a 'name' and 'value' property. An
example of
+ * an array for a simple login form might be:
+ *
+ * [ { name: 'username', value: 'jresig' }, { name: 'password',
value: 'secret' } ]
+ *
+ * It is this array that is passed to pre-submit callback functions
provided to the
+ * ajaxSubmit() and ajaxForm() methods.
+ */
+$.fn.formToArray = function(semantic) {
+ var a = [];
+ if (this.length === 0) {
+ return a;
+ }
+
+ var form = this[0];
+ var els = semantic ? form.getElementsByTagName('*') : form.elements;
+ if (!els) {
+ return a;
+ }
+
+ var i,j,n,v,el,max,jmax;
+ for(i=0, max=els.length; i < max; i++) {
+ el = els[i];
+ n =
el.name;
+ if (!n) {
+ continue;
+ }
+
+ if (semantic && form.clk && el.type == "image") {
+ // handle image inputs on the fly when semantic == true
+ if(!el.disabled && form.clk == el) {
+ a.push({name: n, value: $(el).val()});
+ a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value:
form.clk_y});
+ }
+ continue;
+ }
+
+ v = $.fieldValue(el, true);
+ if (v && v.constructor == Array) {
+ for(j=0, jmax=v.length; j < jmax; j++) {
+ a.push({name: n, value: v[j]});
+ }
+ }
+ else if (v !== null && typeof v != 'undefined') {
+ a.push({name: n, value: v});
+ }
+ }
+
+ if (!semantic && form.clk) {
+ // input type=='image' are not found in elements array! handle it here
+ var $input = $(form.clk), input = $input[0];
+ n =
input.name;
+ if (n && !input.disabled && input.type == 'image') {
+ a.push({name: n, value: $input.val()});
+ a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value:
form.clk_y});
+ }
+ }
+ return a;
+};
+
+/**
+ * Serializes form data into a 'submittable' string. This method will
return a string
+ * in the format: name1=value1&name2=value2
+ */
+$.fn.formSerialize = function(semantic) {
+ //hand off to jQuery.param for proper encoding
+ return $.param(this.formToArray(semantic));
+};
+
+/**
+ * Serializes all field elements in the jQuery object into a query string.
+ * This method will return a string in the format:
name1=value1&name2=value2
+ */
+$.fn.fieldSerialize = function(successful) {
+ var a = [];
+ this.each(function() {
+ var n =
this.name;
+ if (!n) {
+ return;
+ }
+ var v = $.fieldValue(this, successful);
+ if (v && v.constructor == Array) {
+ for (var i=0,max=v.length; i < max; i++) {
+ a.push({name: n, value: v[i]});
+ }
+ }
+ else if (v !== null && typeof v != 'undefined') {
+ a.push({name:
this.name, value: v});
+ }
+ });
+ //hand off to jQuery.param for proper encoding
+ return $.param(a);
+};
+
+/**
+ * Returns the value(s) of the element in the matched set. For example,
consider the following form:
+ *
+ * <form><fieldset>
+ * <input name="A" type="text" />
+ * <input name="A" type="text" />
+ * <input name="B" type="checkbox" value="B1" />
+ * <input name="B" type="checkbox" value="B2"/>
+ * <input name="C" type="radio" value="C1" />
+ * <input name="C" type="radio" value="C2" />
+ * </fieldset></form>
+ *
+ * var v = $(':text').fieldValue();
+ * // if no values are entered into the text inputs
+ * v == ['','']
+ * // if values entered into the text inputs are 'foo' and 'bar'
+ * v == ['foo','bar']
+ *
+ * var v = $(':checkbox').fieldValue();
+ * // if neither checkbox is checked
+ * v === undefined
+ * // if both checkboxes are checked
+ * v == ['B1', 'B2']
+ *
+ * var v = $(':radio').fieldValue();
+ * // if neither radio is checked
+ * v === undefined
+ * // if first radio is checked
+ * v == ['C1']
+ *
+ * The successful argument controls whether or not the field element must
be 'successful'
+ * (per
http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
+ * The default value of the successful argument is true. If this value is
false the value(s)
+ * for each element is returned.
+ *
+ * Note: This method *always* returns an array. If no valid value can be
determined the
+ * array will be empty, otherwise it will contain one or more values.
+ */
+$.fn.fieldValue = function(successful) {
+ for (var val=[], i=0, max=this.length; i < max; i++) {
+ var el = this[i];
+ var v = $.fieldValue(el, successful);
+ if (v === null || typeof v == 'undefined' || (v.constructor == Array
&& !v.length)) {
+ continue;
+ }
+ v.constructor == Array ? $.merge(val, v) : val.push(v);
+ }
+ return val;
+};
+
+/**
+ * Returns the value of the field element.
+ */
+$.fieldValue = function(el, successful) {
+ var n =
el.name, t = el.type, tag = el.tagName.toLowerCase();
+ if (successful === undefined) {
+ successful = true;
+ }
+
+ if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
+ (t == 'checkbox' || t == 'radio') && !el.checked ||
+ (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
+ tag == 'select' && el.selectedIndex == -1)) {
+ return null;
+ }
+
+ if (tag == 'select') {
+ var index = el.selectedIndex;
+ if (index < 0) {
+ return null;
+ }
+ var a = [], ops = el.options;
+ var one = (t == 'select-one');
+ var max = (one ? index+1 : ops.length);
+ for(var i=(one ? index : 0); i < max; i++) {
+ var op = ops[i];
+ if (op.selected) {
+ var v = op.value;
+ if (!v) { // extra pain for IE...
+ v = (op.attributes && op.attributes['value']
&& !(op.attributes['value'].specified)) ? op.text : op.value;
+ }
+ if (one) {
+ return v;
+ }
+ a.push(v);
+ }
+ }
+ return a;
+ }
+ return $(el).val();
+};
+
+/**
+ * Clears the form data. Takes the following actions on the form's input
fields:
+ * - input text fields will have their 'value' property set to the empty
string
+ * - select elements will have their 'selectedIndex' property set to -1
+ * - checkbox and radio inputs will have their 'checked' property set to
false
+ * - inputs of type submit, button, reset, and hidden will *not* be
effected
+ * - button elements will *not* be effected
+ */
+$.fn.clearForm = function() {
+ return this.each(function() {
+ $('input,select,textarea', this).clearFields();
+ });
+};
+
+/**
+ * Clears the selected form elements.
+ */
+$.fn.clearFields = $.fn.clearInputs = function() {
+ return this.each(function() {
+ var t = this.type, tag = this.tagName.toLowerCase();
+ if (t == 'text' || t == 'password' || tag == 'textarea') {
+ this.value = '';
+ }
+ else if (t == 'checkbox' || t == 'radio') {
+ this.checked = false;
+ }
+ else if (tag == 'select') {
+ this.selectedIndex = -1;
+ }
+ });
+};
+
+/**
+ * Resets the form data. Causes all form elements to be reset to their
original value.
+ */
+$.fn.resetForm = function() {
+ return this.each(function() {
+ // guard against an input with the name of 'reset'
+ // note that IE reports the reset function as an 'object'
+ if (typeof this.reset == 'function' || (typeof this.reset == 'object'
&& !this.reset.nodeType)) {
+ this.reset();
+ }
+ });
+};
+
+/**
+ * Enables or disables any matching elements.
+ */
+$.fn.enable = function(b) {
+ if (b === undefined) {
+ b = true;
+ }
+ return this.each(function() {
+ this.disabled = !b;
+ });
+};
+
+/**
+ * Checks/unchecks any matching checkboxes or radio buttons and
+ * selects/deselects and matching option elements.
+ */
+$.fn.selected = function(select) {
+ if (select === undefined) {
+ select = true;
+ }
+ return this.each(function() {
+ var t = this.type;
+ if (t == 'checkbox' || t == 'radio') {
+ this.checked = select;
+ }
+ else if (this.tagName.toLowerCase() == 'option') {
+ var $sel = $(this).parent('select');
+ if (select && $sel[0] && $sel[0].type == 'select-one') {
+ // deselect all other options
+ $sel.find('option').selected(false);
+ }
+ this.selected = select;
+ }
+ });
+};
+
+// helper fn for console logging
+// set $.fn.ajaxSubmit.debug to true to enable debug logging
+function log() {
+ if ($.fn.ajaxSubmit.debug) {
+ var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
+ if (window.console && window.console.log) {
+ window.console.log(msg);
+ }
+ else if (window.opera && window.opera.postError) {
+ window.opera.postError(msg);
+ }
+ }
+};
+
+})(jQuery);
=======================================
--- /dev/null
+++ /trunk/root/js/jquery.sprintf.js Mon Apr 4 09:08:43 2011
@@ -0,0 +1,626 @@
+/*
+ * jQuery sprintf - perl based functionallity for sprintf and friends.
+ *
+ * Copyright © 2008 Carl Fürstenberg
+ *
+ * Released under GPL, BSD, or MIT license.
+ *
---------------------------------------------------------------------------
+ * GPL:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <
http://www.gnu.org/licenses/>.
+ *
+ * Copyright (c) The Regents of the University of California.
+ * All rights reserved.
+ *
+ *
---------------------------------------------------------------------------
+ * BSD:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
WAY
+ °* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *
---------------------------------------------------------------------------
+ * MIT:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
copy
+ * of this software and associated documentation files (the "Software"),
to deal
+ * in the Software without restriction, including without limitation the
rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN
+ * THE SOFTWARE.
+ *
+ *
---------------------------------------------------------------------------
+ *
+ * Version: 0.0.6
+ */
+
+/**
+ * Inserts the arguments into the format and returns the formated string
+ *
+ * @example alert($.vsprintf( "%s %s", [ "Hello", "world" ] ));
+ *
+ * @param String format the format to use
+ * @param Array args the arguments to insert into the format
+ * @return String the formated string
+ */
+jQuery.vsprintf = function jQuery_vsprintf( format, args ) {
+ if( format == null ) {
+ throw "Not enough arguments for vsprintf";
+ }
+ if( args == null ) {
+ args = [];
+ }
+
+ function _sprintf_format( type, value, flags ) {
+
+ // Similar to how perl printf works
+ if( value == undefined ) {
+ if( type == 's' ) {
+ return '';
+ } else {
+ return '0';
+ }
+ }
+
+ var result;
+ var prefix = '';
+ var fill = '';
+ var fillchar = ' ';
+ if( flags['short'] || flags['long'] || flags['long_long'] ) {
+ /* This is pretty ugly, but as JS ignores bit lengths except
+ * somewhat when working with bit operators.
+ * So we fake a bit :) */
+ switch( type ) {
+ case 'e':
+ case 'f':
+ case 'G':
+ case 'E':
+ case 'G':
+ case 'd': /* signed */
+ if( flags['short'] ) {
+ if( value >= 32767 ) {
+ value = 32767;
+ } else if( value <= -32767-1 ) {
+ value = -32767-1;
+ }
+ } else if ( flags['long'] ) {
+ if( value >=
2147483647 ) {
+ value =
2147483647;
+ } else if( value <= -2147483647-1 ) {
+ value = -2147483647-1;
+ }
+ } else /*if ( flags['long_long'] )*/ {
+ if( value >= 9223372036854775807 ) {
+ value = 9223372036854775807;
+ } else if( value <= -9223372036854775807-1 ) {
+ value = -9223372036854775807-1;
+ }
+ }
+ break;
+ case 'X':
+ case 'B':
+ case 'u':
+ case 'o':
+ case 'x':
+ case 'b': /* unsigned */
+ if( value < 0 ) {
+ /* Pretty ugly, but one only solution */
+ value = Math.abs( value ) - 1;
+ }
+ if( flags['short'] ) {
+ if( value >= 65535 ) {
+ value = 65535;
+ }
+ } else if ( flags['long'] ) {
+ if( value >= 4294967295 ) {
+ value = 4294967295;
+ }
+
+ } else /*if ( flags['long_long'] )*/ {
+ if( value >= 18446744073709551615 ) {
+ value = 18446744073709551615;
+ }
+
+ }
+ break;
+ }
+ }
+ switch( type ) {
+ case 'c':
+ result = String.fromCharCode( parseInt( value ) );
+ break;
+ case 's':
+ result = value.toString();
+ break;
+ case 'd':
+ result = (new Number( parseInt( value ) ) ).toString();
+ break;
+ case 'u':
+ result = (new Number( parseInt( value ) ) ).toString();
+ break;
+ case 'o':
+ result = (new Number( parseInt( value ) ) ).toString(8);
+ break;
+ case 'x':
+ result = (new Number( parseInt( value ) ) ).toString(16);
+ break;
+ case 'B':
+ case 'b':
+ result = (new Number( parseInt( value ) ) ).toString(2);
+ break;
+ case 'e':
+ var digits = flags['precision'] ? flags['precision'] : 6;
+ result = (new Number( value ) ).toExponential( digits ).toString();
+ break;
+ case 'f':
+ var digits = flags['precision'] ? flags['precision'] : 6;
+ result = (new Number( value ) ).toFixed( digits ).toString();
+ break;
+ case 'g':
+ var digits = flags['precision'] ? flags['precision'] : 6;
+ result = (new Number( value ) ).toPrecision( digits ).toString();
+ break;
+ case 'X':
+ result = (new Number( parseInt( value ) ) ).toString(16).toUpperCase();
+ break;
+ case 'E':
+ var digits = flags['precision'] ? flags['precision'] : 6;
+ result = (new Number( value ) ).toExponential( digits
).toString().toUpperCase();
+ break;
+ case 'G':
+ var digits = flags['precision'] ? flags['precision'] : 6;
+ result = (new Number( value ) ).toPrecision( digits
).toString().toUpperCase();
+ break;
+ }
+
+ if(flags['+'] && parseFloat( value ) > 0 &&
['d','e','f','g','E','G'].indexOf(type) != -1 ) {
+ prefix = '+';
+ }
+
+ if(flags[' '] && parseFloat( value ) > 0 &&
['d','e','f','g','E','G'].indexOf(type) != -1 ) {
+ prefix = ' ';
+ }
+
+ if( flags['#'] && parseInt( value ) != 0 ) {
+ switch(type) {
+ case 'o':
+ prefix = '0';
+ break;
+ case 'x':
+ case 'X':
+ prefix = '0x';
+ break;
+ case 'b':
+ prefix = '0b';
+ break;
+ case 'B':
+ prefix = '0B';
+ break;
+ }
+ }
+
+ if( flags['0'] && !flags['-'] ) {
+ fillchar = '0';
+ }
+
+ if( flags['width'] && flags['width'] > ( result.length + prefix.length )
) {
+ var tofill = flags['width'] - result.length - prefix.length;
+ for( var i = 0; i < tofill; ++i ) {
+ fill += fillchar;
+ }
+ }
+
+ if( flags['-'] && !flags['0'] ) {
+ result += fill;
+ } else {
+ result = fill + result;
+ }
+
+ return prefix + result;
+ };
+
+ var result = "";
+
+ var index = 0;
+ var current_index = 0;
+ var flags = {
+ 'long': false,
+ 'short': false,
+ 'long_long': false
+ };
+ var in_operator = false;
+ var relative = false;
+ var precision = false;
+ var fixed = false;
+ var vector = false;
+ var bitwidth = false;
+ var vector_delimiter = '.';
+
+ for( var i = 0; i < format.length; ++i ) {
+ var current_char = format.charAt(i);
+ if( in_operator ) {
+ // backward compat
+ switch( current_char ) {
+ case 'i':
+ current_char = 'd';
+ break;
+ case 'D':
+ flags['long'] = true;
+ current_char = 'd';
+ break;
+ case 'U':
+ flags['long'] = true;
+ current_char = 'u';
+ break;
+ case 'O':
+ flags['long'] = true;
+ current_char = 'o';
+ break;
+ case 'F':
+ current_char = 'f';
+ break;
+ }
+ switch( current_char ) {
+ case 'c':
+ case 's':
+ case 'd':
+ case 'u':
+ case 'o':
+ case 'x':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'X':
+ case 'E':
+ case 'G':
+ case 'b':
+ case 'B':
+ var value = args[current_index];
+ if( vector ) {
+ var fixed_value = value;
+ if( value instanceof Array ) {
+ // if the value is an array, assume to work on it directly
+ fixed_value = value;
+ } else if ( typeof(value) == 'string' || value instanceof String ) {
+ // normal behavour, assume string is a bitmap
+ fixed_value = value.split('').map( function( value ) { return
value.charCodeAt(); } );
+ } else if ( ( typeof(value) == 'number' || value instanceof Number )
&& flags['bitwidth'] ) {
+ // if we defined a width, assume we want to vectorize the bits
directly
+ fixed_value = [];
+ do {
+ fixed_value.unshift( value & ~(~0 << flags['bitwidth'] ) );
+ } while( value >>>= flags['bitwidth'] );
+ } else {
+ fixed_value = value.toString().split('').map( function( value ) {
return value.charCodeAt(); } );
+
+ }
+ result += fixed_value.map( function( value ) {
+ return _sprintf_format( current_char, value, flags );
+ }).join( vector_delimiter );
+ } else {
+ result += _sprintf_format( current_char, value, flags );
+ }
+ if( !fixed ) {
+ ++index;
+ }
+ current_index = index;
+ flags = {};
+ relative = false;
+ in_operator = false;
+ precision = false;
+ fixed = false;
+ vector = false;
+ bitwidth = false;
+ vector_delimiter = '.';
+ break;
+ case 'v':
+ vector = true;
+ break;
+ case ' ':
+ case '0':
+ case '-':
+ case '+':
+ case '#':
+ flags[current_char] = true;
+ break;
+ case '*':
+ relative = true;
+ break;
+ case '.':
+ precision = true;
+ break;
+ case '@':
+ bitwidth = true;
+ break;
+ case 'l':
+ if( flags['long'] ) {
+ flags['long_long'] = true;
+ flags['long'] = false;
+ } else {
+ flags['long'] = true;
+ flags['long_long'] = false;
+ }
+ flags['short'] = false;
+ break;
+ case 'q':
+ case 'L':
+ flags['long_long'] = true;
+ flags['long'] = false;
+ flags['short'] = false;
+ break;
+ case 'h':
+ flags['short'] = true;
+ flags['long'] = false;
+ flags['long_long'] = false;
+ break;
+ }
+ if( /\d/.test( current_char ) ) {
+ var num = parseInt( format.substr( i ) );
+ var len = num.toString().length;
+ i += len - 1;
+ var next = format.charAt( i + 1 );
+ if( next == '$' ) {
+ if( num < 0 || num > args.length ) {
+ throw "out of bound";
+ }
+ if( relative ) {
+ if( precision ) {
+ flags['precision'] = args[num - 1];
+ precision = false;
+ } else if( format.charAt( i + 2 ) == 'v' ) {
+ vector_delimiter = args[num - 1];
+ }else {
+ flags['width'] = args[num - 1];
+ }
+ relative = false;
+ } else {
+ fixed = true;
+ current_index = num - 1;
+ }
+ ++i;
+ } else if( precision ) {
+ flags['precision'] = num;
+ precision = false;
+ } else if( bitwidth ) {
+ flags['bitwidth'] = num;
+ bitwidth = false;
+ } else {
+ flags['width'] = num;
+ }
+ } else if ( relative && !/\d/.test( format.charAt( i + 1 ) ) ) {
+ if( precision ) {
+ flags['precision'] = args[current_index];
+ precision = false;
+ } else if( format.charAt( i + 1 ) == 'v' ) {
+ vector_delimiter = args[current_index];
+ } else {
+ flags['width'] = args[current_index];
+ }
+ ++index;
+ if( !fixed ) {
+ current_index++;
+ }
+ relative = false;
+ }
+ } else {
+ if( current_char == '%' ) {
+ // If the next character is an %, then we have an escaped %,
+ // we'll take this as an exception to the normal lookup, as
+ // we don't want/need to process this.
+ if( format.charAt(i+1) == '%' ) {
+ result += '%';
+ ++i;
+ continue;
+ }
+ in_operator = true;
+ continue;
+ } else {
+ result += current_char;
+ continue;
+ }
+ }
+ }
+ return result;
+};
+
+/**
+ * Inserts the arguments§ into the format and returns the formated string
+ *
+ * @example alert($.sprintf( "%s %s", "Hello", "world" ));
+ *
+ * @param String format the format to use
+ * @param Object args... the arguments to insert into the format
+ * @return String the formated string
+ */
+
+jQuery.sprintf = function jQuery_sprintf() {
+ if( arguments.length == 0 ) {
+ throw "Not enough arguments for sprintf";
+ }
+
+ var args = Array.prototype.slice.call(arguments);
+ var format = args.shift();
+
+ return jQuery.vsprintf( format, args );
+};
+
+/**
+ * Inserts the arguments into the format and appends the formated string
+ * to the objects in question.
+ *
+ * @example $('p').printf( "%d <strong>%s</strong>", 2, "world" );
+ *
+ * @before <p>Hello</p>
+ *
+ * @after <p>Hello2 <strong>world</strong></p>
+ *
+ * @param String format the format to use
+ * @param Object args... the arguments to insert into the format
+ */
+
+jQuery.fn.printf = function jQuery_fn_printf() {
+ if( arguments.length == 0 ) {
+ throw "Not enough arguments for sprintf";
+ }
+ var args = Array.prototype.slice.call(arguments);
+ var format = args.shift();
+
+ return this.append( jQuery.vsprintf( format, args ) );
+};
+
+/**
+ * Inserts the arguments into the format and appends the formated string
+ * to the objects in question.
+ *
+ * @example $('p').vprintf( "%d <strong>%s</strong>", [ 2, "world" ] );
+ *
+ * @before <p>Hello</p>
+ *
+ * @after <p>Hello2 <strong>world</strong></p>
+ *
+ * @param String format the format to use
+ * @param Array args the arguments to insert into the format
+ */
+jQuery.fn.vprintf = function jQuery_fn_vprintf( format, args ) {
+ if( arguments.length == 0 ) {
+ throw "Not enough arguments for sprintf";
+ }
+
+ return this.append( jQuery.vsprintf( format, args ) );
+};
+
+/**
+ * Formats the objects html in question and replaces the content
+ * with the formated content
+ *
+ * @example $('p').vformat( [ "Hello", "world" ] );
+ *
+ * @before <p>%s %s</p>
+ *
+ * @after <p>Hello world</p>
+ *
+ * @param Array args the arguments to insert into the format
+ */
+
+jQuery.fn.vformat = function jQuery_fn_vformat( args ) {
+ if( arguments.length == 0 ) {
+ throw "Not enough arguments for sprintf";
+ }
+ return this.each( function() {
+ self = jQuery(this);
+ self.html( jQuery.vsprintf( self.html(), args ) )
+ }
+ );
+}
+
+/**
+ * Formats the objects html in question and replaces the content
+ * with the formated content
+ *
+ * @example $('p').format( "Hello", "world" );
+ *
+ * @before <p>%s %s</p>
+ *
+ * @after <p>Hello world</p>
+ *
+ * @param Object args... the arguments to insert into the format
+ */
+jQuery.fn.format = function jQuery_fn_format() {
+ if( arguments.length == 0 ) {
+ throw "Not enough arguments for sprintf";
+ }
+ var args = Array.prototype.slice.call(arguments);
+ return this.each( function() {
+ self = jQuery(this);
+ self.html( jQuery.vsprintf( self.html(), args ) )
+ }
+ );
+}
+
+/**
+ * Inserts the arguments into the format and prints formated string
+ * to console or dump
+ *
+ * @example $.printf( "%s %s", "Hello", "world" );
+ *
+ * @param String format the format to use
+ * @param Object args... the arguments to insert into the format
+ */
+jQuery.printf = function jQuery_printf() {
+ if( arguments.length == 0 ) {
+ throw "Not enough arguments for sprintf";
+ }
+ var args = Array.prototype.slice.call(arguments);
+ var format = args.shift();
+ var ret = jQuery.vsprintf( format, args );
+
+ if( window.console ) {
+
window.console.info( ret );
+ } else {
+ window.dump( ret );
+ }
+};
+/**
+ * Inserts the arguments into the format and prints formated string
+ * to console or dump
+ *
+ * @example $.vprintf( "%s %s", [ "Hello", "world" ] );
+ *
+ * @param String format the format to use
+ * @param Array args the arguments to insert into the format
+ */
+jQuery.vprintf = function jQuery_vprintf( format, args ) {
+ if( arguments.length == 0 ) {
+ throw "Not enough arguments for sprintf";
+ }
+ var ret = jQuery.vsprintf( format, args );
+
+ if( window.console ) {
+
window.console.info( ret );
+ } else {
+ window.dump( ret );
+ }
+
+};
=======================================
--- /dev/null
+++ /trunk/root/js/jquery.url.min.js Mon Apr 4 09:08:43 2011
@@ -0,0 +1,11 @@
+/*
+jQuery Url Plugin
+ * Version 1.0
+ * 2009-03-22 19:30:05
+ * URL:
http://ajaxcssblog.com/jquery/url-read-get-variables/
+ * Description: jQuery Url Plugin gives the ability to read GET parameters
from the actual URL
+ * Author: Matthias Jäggli
+ * Copyright: Copyright (c) 2009 Matthias Jäggli
+ * Licence: dual, MIT/GPLv2
+*/
+(function($){$.url={};$.extend($.url,{_params:{},init:function(){var
paramsRaw="";try{paramsRaw=(document.location.href.split("?",2)[1]|
|"").split("#")[0].split("&")||[];for(var i=0;i<paramsRaw.length;i++){var
single=paramsRaw[i].split("=");if(single[0])this._params[single[0]]=unescape(single[1]);}}catch(e){alert(e);}},param:function(name){return
this._params[name]||"";},paramAll:function(){return
this._params;}});$.url.init();})(jQuery);
=======================================
--- /trunk/Changes Mon Jan 24 10:05:53 2011
+++ /trunk/Changes Mon Apr 4 09:08:43 2011
@@ -1,5 +1,18 @@
This file documents the revision history for Perl extension Gantry
+3.79 Wed Mar 31 15:22:00 CDT 2011
+ - Added javascript functions to enable display of gantry forms/results
+ via ajax.
+ - Added needed jquery dependencies.
+ - Updated Gantry.pm to allow returning of errors in json format
+ to support ajax frontends.
+ - Incorporated functionality of AjaxCRUD plugin into CRUD plugin to
allow
+ CRUD to support ajax forms.
+ - Added TO_JSON method to View.pm and Form.pm to allow to_json method
of
+ the JSON library to convert their data stuctures into json format.
+ - Updated TablePerms.pm to allow links containing request parameters to
+ be output correctly. Also updated it to process rel option.
+
3.78 Mon Jan 24 12:04:00 CDT 2011
- Don't output <br> after hidden form elements.
=======================================
--- /trunk/MANIFEST Wed Dec 2 08:55:29 2009
+++ /trunk/MANIFEST Mon Apr 4 09:08:43 2011
@@ -73,6 +73,7 @@
lib/Gantry/Plugins/Calendar.pm
lib/Gantry/Plugins/CRUD.pm
lib/Gantry/Plugins/DBIxClassConn.pm
+lib/Gantry/Plugins/JSONConf.pm
lib/Gantry/Plugins/PageCache.pm
lib/Gantry/Plugins/Shibboleth.pm
lib/Gantry/Plugins/SOAP/Doc.pm
@@ -173,10 +174,18 @@
root/images/tenttut/tentopening.png
root/images/tlc-gray-block.gif
root/images/trc-gray-block.gif
+root/js/ajaxForm.js
+root/js/ajaxResults.js
root/js/datePicker.js
root/js/gantry-yui-calendar.js
root/js/gantry.js
+root/js/jquery-1.4.3.min.js
+root/js/jquery.address.min.js
+root/js/jquery.blockUI.js
+root/js/jquery.form.js
root/js/jquery.js
+root/js/jquery.sprintf.js
+root/js/jquery.url.min.js
root/
login.tt
root/
main.tt
root/moxie/
delete.tt
=======================================
--- /trunk/lib/Gantry/Plugins/CRUD.pm Wed Feb 10 10:12:18 2010
+++ /trunk/lib/Gantry/Plugins/CRUD.pm Mon Apr 4 09:08:43 2011
@@ -3,6 +3,7 @@
use strict;
use Carp;
use Data::FormValidator;
+use JSON ();
use Gantry::Utils::CRUDHelp qw(
clean_dates clean_params form_profile write_file verify_permission
@@ -66,6 +67,16 @@
croak 'delete_action not defined or misspelled';
}
}
+
+sub success_action {
+ my $self = shift;
+
+ if ( defined $self->{success_action} ) {
+ return $self->{success_action}
+ }
+
+ return undef;
+}
sub form {
my $self = shift;
@@ -117,20 +128,27 @@
#-------------------------------------------------
sub add {
my ( $self, $your_self, $data ) = @_;
-
- # Use the specified default template in the config if no
- # template was specified to the crud module and there is a
- # default defined.
- if (
- ( ! $self->{ignore_default_template} ) and
- ( $your_self->fish_config( 'default_form_template' ) )
- ) {
- $your_self->stash->view->template(
- $your_self->fish_config( 'default_form_template' )
- );
+ my $form_data = {};
+
+ if ($self->{ajax_form}) {
+ # Disable template processing
+ $your_self->template_disable( 1 );
}
else {
- $your_self->stash->view->template( $self->template );
+ # Use the specified default template in the config if no
+ # template was specified to the crud module and there is a
+ # default defined.
+ if (
+ ( ! $self->{ignore_default_template} ) and
+ ( $your_self->fish_config( 'default_form_template' ) )
+ ) {
+ $your_self->stash->view->template(
+ $your_self->fish_config( 'default_form_template' )
+ );
+ }
+ else {
+ $your_self->stash->view->template( $self->template );
+ }
}
$your_self->stash->view->title( 'Add ' . $self->text_descr )
@@ -138,22 +156,45 @@
my $params = $your_self->get_param_hash();
- # Redirect if user pressed 'Cancel'
+ # Handle form cancel action.
if ( $params->{cancel} ) {
- my $redirect = $self->_find_redirect(
- {
- gantry_site => $your_self,
- data => $data,
- user_req => 'add',
- action => 'cancel',
- }
- );
-
- return $your_self->relocate( $redirect );
+ # Return a response for ajax forms.
+ if ( $self->{ajax_form} ) {
+ my $response = $self->_handle_action(
+ {
+ gantry_site => $your_self,
+ data => $data,
+ user_req => 'add',
+ action => 'cancel',
+ }
+ );
+
+ return $response;
+ }
+ # Redirect for regular forms.
+ else {
+ my $redirect = $self->_find_redirect(
+ {
+ gantry_site => $your_self,
+ data => $data,
+ user_req => 'add',
+ action => 'cancel',
+ }
+ );
+
+ return $your_self->relocate( $redirect );
+ }
+ }
+
+ if ( $data ) {
+ $form_data = { %$data, user_req => 'add' };
+ }
+ else {
+ $form_data->{user_req} = 'add';
}
# get and hold the form description
- my $form = $self->form->( $your_self, $data );
+ my $form = $self->form->( $your_self, $form_data );
# Check form data
my $show_form = 0;
@@ -196,6 +237,17 @@
if ( $your_self->method eq 'POST' ) {
$your_self->stash->view->form->results( $results );
}
+
+ # If this is an ajax form...
+ if ( $self->{ajax_form} ) {
+ # Return json data.
+ return $self->_jsonify(
+ $your_self->stash->view->title(),
+ $form,
+ $data,
+ $params
+ );
+ }
}
else {
my $redirect;
@@ -219,17 +271,31 @@
$self->add_action->( $your_self, $params, $data );
- # Find redirect.
- $redirect = $self->_find_redirect(
- {
- gantry_site => $your_self,
- data => $data,
- action => $action,
- user_req => 'add'
- }
- );
-
- return $your_self->relocate( $redirect );
+ if ( $self->{ajax_form} ) {
+ my $response = $self->_handle_action(
+ {
+ gantry_site => $your_self,
+ data => $data,
+ action => $action,
+ user_req => 'add'
+ }
+ );
+
+ return $response;
+ }
+ else {
+ # Find redirect.
+ $redirect = $self->_find_redirect(
+ {
+ gantry_site => $your_self,
+ data => $data,
+ action => $action,
+ user_req => 'add'
+ }
+ );
+
+ return $your_self->relocate( $redirect );
+ }
}
} # END: add
@@ -238,20 +304,27 @@
#-------------------------------------------------
sub edit {
my ( $self, $your_self, $data ) = @_;
-
- # Use the specified default template in the config if no
- # template was specified to the crud module and there is a
- # default defined.
- if (
- ( ! $self->{ignore_default_template} ) and
- ( $your_self->fish_config( 'default_form_template' ) )
- ) {
- $your_self->stash->view->template(
- $your_self->fish_config( 'default_form_template' )
- );
+ my $form_data;
+
+ if ( $self->{ajax_form} ) {
+ # Disable template processing
+ $your_self->template_disable( 1 );
}
else {
- $your_self->stash->view->template( $self->template );
+ # Use the specified default template in the config if no
+ # template was specified to the crud module and there is a
+ # default defined.
+ if (
+ ( ! $self->{ignore_default_template} ) and
+ ( $your_self->fish_config( 'default_form_template' ) )
+ ) {
+ $your_self->stash->view->template(
+ $your_self->fish_config( 'default_form_template' )
+ );
+ }
+ else {
+ $your_self->stash->view->template( $self->template );
+ }
}
$your_self->stash->view->title( 'Edit ' . $self->text_descr() )
@@ -259,21 +332,45 @@
my %params = $your_self->get_param_hash();
- # Redirect if 'Cancel'
+ # Handle form cancel action.
if ( $params{cancel} ) {
- my $redirect = $self->_find_redirect(
- {
- gantry_site => $your_self,
- data => $data,
- action => 'cancel',
- user_req => 'edit',
- }
- );
- return $your_self->relocate( $redirect );
+ # Return a response for ajax forms.
+ if ( $self->{ajax_form} ) {
+ my $response = $self->_handle_action(
+ {
+ gantry_site => $your_self,
+ data => $data,
+ user_req => 'edit',
+ action => 'cancel',
+ }
+ );
+
+ return $response;
+ }
+ # Redirect for regular forms.
+ else {
+ my $redirect = $self->_find_redirect(
+ {
+ gantry_site => $your_self,
+ data => $data,
+ user_req => 'edit',
+ action => 'cancel',
+ }
+ );
+
+ return $your_self->relocate( $redirect );
+ }
+ }
+
+ if ( $data ) {
+ $form_data = { %$data, user_req => 'edit' };
+ }
+ else {
+ $form_data->{user_req} = 'edit';
}
# get and hold the form description
- my $form = $self->form->( $your_self, $data );
+ my $form = $self->form->( $your_self, $form_data );
croak 'Your form callback gave me nothing' unless defined $form and
$form;
@@ -319,7 +416,17 @@
if ( $your_self->method eq 'POST' ) {
$your_self->stash->view->form->results( $results );
}
-
+
+ # If this is an ajax form...
+ if ( $self->{ajax_form} ) {
+ # Return json data.
+ return $self->_jsonify(
+ $your_self->stash->view->title(),
+ $form,
+ $data,
+ \%params
+ );
+ }
}
# Form looks good, make update
else {
@@ -343,18 +450,32 @@
}
$self->edit_action->( $your_self, \%params, $data );
-
- # Find redirect.
- $redirect = $self->_find_redirect(
- {
- gantry_site => $your_self,
- data => $data,
- action => $action,
- user_req => 'edit'
- }
- );
-
- return $your_self->relocate( $redirect );
+
+ if ( $self->{ajax_form} ) {
+ my $response = $self->_handle_action(
+ {
+ gantry_site => $your_self,
+ data => $data,
+ action => $action,
+ user_req => 'edit'
+ }
+ );
+
+ return $response;
+ }
+ else {
+ # Find redirect.
+ $redirect = $self->_find_redirect(
+ {
+ gantry_site => $your_self,
+ data => $data,
+ action => $action,
+ user_req => 'edit'
+ }
+ );
+
+ return $your_self->relocate( $redirect );
+ }
}
} # END: edit
@@ -364,39 +485,99 @@
sub delete {
my ( $self, $your_self, $yes, $data ) = @_;
- $your_self->stash->view->template( '
delete.tt' )
- unless $your_self->stash->view->template();
- $your_self->stash->view->title( 'Delete' )
- unless $your_self->stash->view->title;
-
+ if ( $self->{ajax_form} ) {
+ # Disable template processing
+ $your_self->template_disable( 1 );
+ }
+ else {
+ $your_self->stash->view->template( '
delete.tt' )
+ unless $your_self->stash->view->template();
+ }
+
+ $your_self->stash->view->title( 'Delete ' . $self->text_descr() )
+ unless $your_self->stash->view->title;
+
+ # Handle form cancel action.
if ( $your_self->params->{cancel} ) {
- my $redirect = $self->_find_redirect(
- {
- gantry_site => $your_self,
- data => $data,
- action => 'cancel',
- user_req => 'delete'
- }
- );
- return $your_self->relocate( $redirect );
+ # Return a response for ajax forms.
+ if ( $self->{ajax_form} ) {
+ my $response = $self->_handle_action(
+ {
+ gantry_site => $your_self,
+ data => $data,
+ user_req => 'delete',
+ action => 'cancel',
+ }
+ );
+
+ return $response;
+ }
+ # Redirect for regular forms.
+ else {
+ my $redirect = $self->_find_redirect(
+ {
+ gantry_site => $your_self,
+ data => $data,
+ user_req => 'delete',
+ action => 'cancel',
+ }
+ );
+
+ return $your_self->relocate( $redirect );
+ }
}
if ( ( defined $yes ) and ( $yes eq 'yes' ) ) {
$self->delete_action->( $your_self, $data );
- # Move along, it's already dead
- my $redirect = $self->_find_redirect(
- {
- gantry_site => $your_self,
- data => $data,
- action => 'submit',
- user_req => 'delete'
- }
- );
- return $your_self->relocate( $redirect );
+ if ( $self->{ajax_form} ) {
+ my $response = $self->_handle_action(
+ {
+ gantry_site => $your_self,
+ data => $data,
+ action => 'submit',
+ user_req => 'delete'
+ }
+ );
+
+ return $response;
+ }
+ else {
+ # Find redirect.
+ my $redirect = $self->_find_redirect(
+ {
+ gantry_site => $your_self,
+ data => $data,
+ action => 'submit',
+ user_req => 'delete'
+ }
+ );
+
+ return $your_self->relocate( $redirect );
+ }
}
else {
+ if ( $self->{ajax_form} ) {
+ # Create a delete form profile to return.
+ my $del_form = {
+ row => $data->{row},
+ message => 'Delete ' .
$self->text_descr() . '?',
+ submit_button_label => 'Continue with Delete',
+ nohead => 1,
+ action => $your_self->uri() . '/yes'
+ };
+
+ $your_self->stash->view->form( $del_form );
+
+ # Return json data.
+ return $self->_jsonify(
+ $your_self->stash->view->title(),
+ $del_form,
+ $data,
+ );
+ }
+
$your_self->stash->view->form->message (
'Delete ' . $self->text_descr() . '?'
);
@@ -424,6 +605,29 @@
else {
$retval = $your_self->location();
}
+
+ return $retval;
+}
+
+sub _handle_action {
+ my ( $self, $args ) = @_;
+ my $your_self = $args->{ gantry_site };
+ my $data = $args->{ data };
+ my $action = $args->{ action };
+ my $user_req = $args->{ user_req };
+ my $retval;
+ my $action_sub;
+
+ if ($action eq 'submit' or $action eq 'submit_add_another') {
+ $action_sub = $self->success_action;
+ }
+
+ if ( defined $action_sub ) {
+ $retval = $action_sub->( $your_self, $data, $action, $user_req );
+ }
+ else {
+ $retval = JSON::to_json( { response => $action } );
+ }
return $retval;
}
@@ -454,6 +658,37 @@
}
};
}
+
+#-----------------------------------------------------------
+# $self->_jsonify( $title, $form, $data, $params )
+#-----------------------------------------------------------
+sub _jsonify {
+ my ($self, $title, $form, $data, $params) = @_;
+ my $obj;
+ my $jdata;
+
+ $jdata = {%$data} if $data;
+
+ # Remove the row from data since its already part of the form and
+ # it can't be jsonified anyways.
+ delete $jdata->{row} if $jdata;
+
+ $obj = {
+ data => $jdata,
+ title => $title,
+ form => $form,
+ params => $params,
+ };
+
+ return JSON::to_json(
+ $obj,
+ {
+ allow_blessed => 1,
+ convert_blessed => 1,
+ allow_unknown => 1,
+ }
+ );
+}
1;
@@ -471,6 +706,8 @@
add_action => \&user_insert,
edit_action => \&user_update,
delete_action => \&user_delete,
+ ajax_form => 1,
+ success_action => \&form_success,
form => \&user_form,
validator => \&user_form_validator,
redirect => \&redirect_function,
@@ -535,6 +772,105 @@
if method is POST:
add form validation errors
(re)display form
+
+=head1 AJAX FORMS
+
+This module can also support ajax forms. If ajax_form is passed as a
parameter
+then the CRUD module will not redirect after form submissions. Instead it
will
+call the method pointed to by success_action in which you can take the
necessary
+action after successful form submission.
+
+You will need to utilize a number of support javascript files in order to
make
+use of ajax based forms. You should include the following files on the page
+containing the ajax form(s).
+
+ js/jquery-1.4.3.min.js
+ js/jquery.blockUI.js *
+ js/jquery.form.js
+ js/jquery.address.min.js
+ js/jquery.sprintf.js
+ js/jquery.url.min.js
+ js/ajaxResults.js **
+ js/ajaxForm.js
+
+ * Needed if you want to use blockUI based popup forms.
+ ** Needed if you want to render gantry results via ajax.
+
+The simpliest way to get up and running is to include the above files on a
page
+generated using sfbb/
results.tt. Then in your Controller specify a rel
option
+as part of your header / row options as follows:
+
+ my @header_options = (
+ {
+ text => 'Add',
+ link => "${real_location}add",
+ rel => "address:${real_location}add?gftype=bui&getype=bui",
+ type => 'create',
+ },
+ );
+
+The rel option is used by the jquery.address plugin to automatically add
the necessary
+event handlers to the anchor links. You can specify 2 different parameters
along with
+the rel option to control how forms and error messages are displayed.
+
+ gftype - can either be bui for a blocking popup form or inline for
a standard
+ inline form.
+ getype - can either be bui for blocking popup error message or
alert for
+ a standard browser alert window.
+
+In your methods that handle form add/edit/delete you will want to set
json_error
+to true by calling $self->json_error(1) so that any errors that occur
while processing
+the request are returned to the page in json format instead of Gantry's
standard
+html format.
+
+The ajax form functionality can be customized in a number of ways. If you
need to
+customize the look of the bui popup form you can do so by not specifying a
rel
+option for anchor links and instead setup the event handler manually where
you
+can specify the blockUI css at the same time. Your javascript file that
does
+this will need to be included after ajaxForm.js so that it has access to
the
+global variable where the blockUI css values are stored. Below is an
example
+of how to do this.
+
+ $j(document).ready(function() {
+ $j('a').address(function() {
+ var offset = $j("#results").offset();
+ var top = 140;
+ var left = 150;
+ var width = '425px';
+
+ if ($j(this).attr('href').match('edit')) {
+ width = '700px';
+ }
+
+ gantryAjaxFormBuiCss = {
+ top: top,
+ left: offset.left + left,
+ width: width,
+ border: '1px solid #000',
+ backgroundColor: '#ccc',
+ '-webkit-border-radius': '10px',
+ '-moz-border-radius': '10px',
+ opacity: '1',
+ color: '#000'
+ };
+
+ return $j(this).attr('href');
+ });
+ });
+
+By checking the href as above, you could customize the look of the popup
+form based on the link. gantryAjaxFormBuiCss supports all the css options
+of blockUI. You can also customize the blockUI error popup in a similar
+manner by setting css options in gantryAjaxErrorFormBuiCss.
+
+ajaxForm.js uses the jquery.form plugin to handle form submission. If you
need
+to customize the form handling you can do so by adding options to the
global
+gantryAjaxFormOptions variable. It supports the same options as the jquery
+form plugin. Here is an example for setting up a form validator callback:
+
+ gantryAjaxFormOptions.beforeSubmit = function(arr, form, option) {
+ // validate form data here.
+ }
=head1 CONFIGURATION
@@ -549,6 +885,10 @@
it defaults to
form.tt. If a template is specified during
object creation it will override the value specified here.
+=item ajax_form
+
+Modifies CRUD.pm behavior to support ajax based forms.
+
=back
=head1 METHODS
@@ -601,6 +941,18 @@
fails, then feel free to die). You don't need to change your location,
but you may.
+=item success_action (a code ref)
+
+Called with:
+
+ your self object
+ the data you passed to delete
+
+This method is called after a success ajax form submission. It can be
+used to return whatever response you want to a successful form action.
+Typically this might be returning your gantry results in json form
+so the page can be updated with your result table.
+
=item form (a code ref)
Called with:
=======================================
--- /trunk/lib/Gantry/Stash/View/Form.pm Tue Jul 25 13:34:59 2006
+++ /trunk/lib/Gantry/Stash/View/Form.pm Mon Apr 4 09:08:43 2011
@@ -37,6 +37,42 @@
$self->{message} = $p if defined $p;
return( $self->{message} );
}
+
+sub TO_JSON {
+ my $self = shift;
+ my $row;
+ my $j = { %$self };
+
+ # If we have an orm row then we need to convert it's data values into
a hash
+ # to be returned as part of the json data.
+ if ( defined $self->{row} ) {
+ my %cols = $self->{row}->get_columns;
+
+ # Remove orm row since it can't be jsonified plus we don't want to
return
+ # everything even if it could be.
+ delete $j->{row};
+
+ # Add column values for the fields in the form.
+ foreach my $field ( @{$self->{fields}} ) {
+ $j->{row}->{$field->{name}} = $cols{$field->{name}};
+ }
+ }
+
+ # If we have results we need to convert them.
+ if ( defined $self->{results} ) {
+ my $results = { %{ $self->{results} } };
+ my $msgs = $self->{results}->msgs;
+
+ # If there are msgs add them to the results.
+ if ($msgs) {
+ $results->{msgs} = $msgs;
+ }
+
+ $j->{results} = $results;
+ }
+
+ return $j;
+}
1;
@@ -76,6 +112,12 @@
Used by some templates for question text to present to the user.
+=item TO_JSON
+
+Handles conversion of blessed form object into a json data structure. This
is
+useful in combination with the JSON module's to_json method when the
+convert_blessed option is specified.
+
=back
=head1 SEE ALSO
=======================================
--- /trunk/lib/Gantry/Stash/View.pm Tue Jul 25 13:34:59 2006
+++ /trunk/lib/Gantry/Stash/View.pm Mon Apr 4 09:08:43 2011
@@ -75,6 +75,19 @@
return( $self->{__FORM__} );
}
+
+sub TO_JSON {
+ my $self = shift;
+ my $j;
+
+ # Create hashref to represent the view as json data.
+ $j->{template} = $self->{__TEMPLATE__};
+ $j->{data} = $self->{__DATA__};
+ $j->{title} = $self->{__TITLE__};
+ $j->{form} = $self->{__FORM__};
+
+ return $j;
+}
1;
=======================================
--- /trunk/lib/Gantry/Utils/TablePerms.pm Tue May 22 09:14:26 2007
+++ /trunk/lib/Gantry/Utils/TablePerms.pm Mon Apr 4 09:08:43 2011
@@ -131,9 +131,12 @@
row => $row,
}
);
- my $link;
+ my ( $link, $rel );
if ( $option->{ link } ) {
- $link = "$option->{ link }/$id";
+ my @la = split /\?/, $option->{ link };
+
+ $link = "$la[0]/$id";
+ $link .= "?$la[1]" if defined $la[1];
}
else {
my $method = lc $option->{ text };
@@ -141,9 +144,18 @@
$link = $self->gantry_site->location . "/$method/$id";
}
+
+ if ( $option->{ rel } ) {
+ my @ra = split /\?/, $option->{ rel };
+
+ $rel = "$ra[0]/$id";
+ $rel .= "?$ra[1]" if defined $ra[1];
+ }
+
push @real_options, {
text => $option->{ text },
link => $link,
+ rel => $rel,
};
};
}
=======================================
--- /trunk/lib/Gantry.pm Mon Jan 24 10:06:55 2011
+++ /trunk/lib/Gantry.pm Mon Apr 4 09:08:43 2011
@@ -6,6 +6,7 @@
use CGI::Simple;
use File::Spec;
use POSIX qw( strftime );
+use JSON ();
############################################################
# Variables #
@@ -1162,6 +1163,17 @@
}
} # end cleanup
+#-------------------------------------------------
+# $self->json_error( value )
+#-------------------------------------------------
+sub json_error {
+ my ( $self, $p ) = @_;
+
+ $self->{__JSON_ERROR__} = $p if ( defined $p );
+ return( $self->{__JSON_ERROR__} );
+
+} # end json_error
+
#-------------------------------------------------
# $self->custom_error( @errors )
#-------------------------------------------------
@@ -1171,6 +1183,14 @@
eval "use Data::Dumper";
my $die_msg = join( "\n", @err );
+
+ # Check if we need to return error in json format.
+ if ($self->json_error) {
+ $die_msg =~ s/\n/ /og;
+ $die_msg =~ s/\s+$//o;
+
+ return JSON::to_json({ error => $die_msg });
+ }
my $param_dump = Dumper( $self->params );
$param_dump =~ s/(?:^|\n)(\s+)/&trim( $1 )/ge;
@@ -1532,6 +1552,11 @@
Returns the engine cycle total.
+=item json_error
+
+Get/Set json error value. If true then any gantry errors will be
+returned in json format instead of html.
+
=item custom_error
Generates an error page. Feel free to override this to change the
=======================================
--- /trunk/t/auth/04_run.t Wed Feb 21 11:46:29 2007
+++ /trunk/t/auth/04_run.t Mon Apr 4 09:08:43 2011
@@ -73,7 +73,7 @@
"expected 200/302, received $status for $location" );
if ( $status !~ /^(302|200)$/ ) {
- #diag( $page );
+ diag( $page );
}
}
else {