dbd97cd6ce26f298cb61028829e514c1c79ebfd4
tdreszer
Thu Feb 9 14:14:16 2012 -0800
Andy Pohl tripped over a debug message when naming subtracks as {compisteName}_{subtrack}. This is easily fixed and should not be illegal. The debug message did what it was supposed to do.
diff --git src/hg/js/subCfg.js src/hg/js/subCfg.js
index 9709c0c..ecce356 100644
--- src/hg/js/subCfg.js
+++ src/hg/js/subCfg.js
@@ -1,883 +1,884 @@
// subCfg the subtrack Configureation module (scm) for hgTrackUi
//
// This module is for subtrack level config embedded dialogs in hgTrackUi.
// Subtrack config dialogs are embedded in the subtrack table and get populated when first
// opened. Composite and view level controls (parents) when updated override related
// subtrack controls (children). Subtrack controls, when updated overide parent controls
// for the one subtrack. Controls wil get class 'changed' added when changes are made.
// When the form is submitted, all controls not marked as "changed" will be unnamed and will
// therefore not make it into the cart.
// Definitions as used here:
// obj: an input or select style html control which may be marked as "changed"
// parentObj: composite or view level obj which has subtrack level childObjs associated
// childObj: subtrack level obj that has composite and or view level parentObjs
// cfg: subtrack level embedded dialog which can be opened or closed (hidden) and isn't
// populated till first opened. Can also be a viewCfg and maybe a compositeCfg
// populate: act of filling a subtrack cfg with controls
// fauxVis: fake control for subtrack visDD, which will be replaced with true vis when clicked.
// Issues:
// - SOLVED: checkboxes: working with name = boolshad.{name} FIXME: multishad? [no problem currently]
// - DECIDED: When parent vis makes subs hidden, should they go to unchecked? No, disabled!
// - DECIDED: Should user be able to click on disabled vis to check the CB? No, not important.
// - DECIDED: Make vis changes "reshape" composite! NO, I am against this as too disruptive. We may want to end reshaping in CGIs as well!
// - Verified all composites work (hg19 hg18 mm9 mm8 panTro3 galGal3 braFlo1 dm3 ce10 homPan20 sacCer3 hg19Patch5 tested so far)
// - Speed up massive composites! HAIB TFBS SYDH TFBS
// - subVis DOES NOT set compVis to full (when compVis set to hide, but subVis already populated) OK because this slips towords reshaping.
// NOTE:
// Current implementation relies upon '.' delimiter in name and no '_-' in name. Nothing breaks rule yet...
// Can remove "DEBUG" messages when fully QA'd. They are asserts.
var subCfg = { // subtrack config module.
//mySelf: null, // There is no need for a "mySelf" unless this object is being instantiated.
// There is one instance and these vars are page wide
compositeName: undefined,
canPack: true, // if composite vis is only hide,dense,full, then all children will also be restricted.
visIndependent: false,
viewTags: [],
markChange: function (eventObj, obj)
{ // Marks a control as having been changed by the user. Naming will send value to cart.
// Note this is often called directly as the onchange event function
if (obj == undefined || $.type(obj) === "string")
obj = this;
$(obj).addClass('changed');
// checkboxes have hidden boolshads which should be marked when unchecked
if(obj.type === "checkbox") {
var boolshad = normed($("input.cbShadow[name='boolshad\\." + obj.name+"']"));
if (boolshad != undefined) {
$(boolshad).addClass('changed');
}
}
},
clearChange: function (obj)
{ // Mark as unchanged
$(obj).removeClass('changed');
// checkboxes have hidden boolshads which should be cleared in tandem
if(obj.type === "checkbox") {
var boolshad = normed($("input.cbShadow[name='boolshad\\." + obj.name+"']"));
if (boolshad != undefined) {
$(boolshad).removeClass('changed');
}
}
},
hasChanged: function (obj)
{ // Is this object updated (value changed by a user)?
return $(obj).hasClass('changed');
},
compositeCfgFind: function ()
{ // returns the cfg container for the composite controls
// TODO: write, create a composite cfg div!
},
compositeObjFind: function (suffix)
{ // returns the composite level control for this suffix
//var compCfg = subCfg.compositeCfgFind(); // TODO: when there is a composite cfg div!
var compObj;
if (suffix != undefined) {
compObj = normed($("[name='"+subCfg.compositeName + "\\." + suffix+"']"));
if (compObj === undefined) {
compObj = normed($("[name='"+subCfg.compositeName + "_" + suffix+"']"));
}
} else {
compObj = normed($("[name='"+subCfg.compositeName+"']"));
}
return compObj;
},
viewTagFind: function (childObj)
{ // returns the name of the view that is a parent of this subtrack control
var cfg = normed($(childObj).parents('div.subCfg'));
if (cfg == undefined) {
// Child obj could be vis itself...
var subCb = normed($(childObj).closest('tr').find('input.subCB'));
if (subCb != undefined) {
var classList = $(subCb).attr("class").split(" ");
classList = aryRemove(classList,["changed","disabled"]);
return classList[classList.length - 1];
}
// could be vis outside of cfg div
warn("DEBUG: Can't find containing div.subCfg of child '"+childObj.name+"'.");
return undefined;
}
var classList = $( cfg ).attr("class").split(" ");
classList = aryRemove(classList,["subCfg","filled"]);
if (classList.length == 0) {
warn("DEBUG: Subtrack cfg div does not have view class for child '"+childObj.name+"'.");
return undefined;
} else if (classList.length > 1) {
warn("DEBUG: Subtrack cfg div for '"+childObj.name+"' has unexpected class: "+classList);
return undefined;
}
if (classList[0] == 'noView') // valid case
return undefined;
return classList[0];
},
viewCfgFind: function (viewTag)
{ // returns the cfg container for a given view
var viewCfg = normed($('tr#tr_cfg_'+viewTag));
if (viewCfg == undefined) {
warn('DEBUG: Could not find viewCfg for '+viewTag);
}
return viewCfg;
},
viewObjFind: function (viewTag,suffix)
{ // returns the control belonging to this view and suffix
var viewObj;
if (suffix != undefined) {
var viewCfg = subCfg.viewCfgFind(viewTag);
viewObj = normed($(viewCfg).find("[name$='\\."+suffix+"']"));
if (viewObj == undefined)
viewObj = normed($(viewCfg).find("[name$='_"+suffix+"']"));
} else
viewObj = normed($("select.viewDD."+viewTag));
return viewObj;
},
childObjsFind: function (viewTag,suffix)
{ // returns an array of objs for this view and suffix
// Assumes composite wide if viewTag is not provided
// Assumes vis if suffix is not provided
if (viewTag != undefined) {
var childCfgs = $('div.subCfg.filled.'+viewTag);
} else {
var childCfgs = $('div.subCfg.filled');
}
if (childCfgs == undefined)
return [];
var childObjs = [];
if (suffix != undefined)
childObjs = $(childCfgs).find('select,input').filter("[name$='\\."+suffix+"']");
else
childObjs = $(childCfgs).find('select.visDD');
if (childObjs == undefined)
return [];
return childObjs;
},
objSuffixGet: function (obj)
{ // returns the identifying suffix of a control. obj can be parent or child
//var nameParts = $(obj).attr('id').split('.');
var nameParts = obj.name.split('.');
if (nameParts == undefined || nameParts.length == 0) {
warn("DEBUG: Can't resolve name for '"+obj.name+"'.");
return undefined;
}
if (nameParts.length < 2)
return undefined;
nameParts.shift();
if (subCfg.viewTags.length > 0 && nameParts.length > 1) // FIXME: I expect more problems with this!
nameParts.shift();
return nameParts.join('.');
},
childCfgFind: function (childObj)
{ // returns the cfg wrapper for a child vis object
var childCfg = normed($(childObj).parents('div.subCfg.filled'));
if (childCfg == undefined)
warn("DEBUG: Can't find childCfg for "+childObj.name);
return childCfg;
},
subCbFind: function (childObj)
{ // returns the subCB for a child vis object
// Look directly first
var subCb = normed($(childObj).closest('tr').find('input.subCB'));
if (subCb != undefined)
return subCb;
warn("DEBUG: Failed to find subCb for "+childObj.name);
var childCfg = subCfg.childCfgFind(childObj);
if (childCfg == undefined)
return undefined;
var tr = $(childCfg).parents('tr').first();
var subtrack = childCfg.id.substring(8); // 'div_cfg_'.length
var subCb = normed($(tr).find("input[name='"+subtrack+"_sel']"));
if (subCb == undefined)
warn("DEBUG: Can't find subCB for subtrack: "+subtrack);
return subCb;
},
parentsFind: function (childObj)
{ // returns array of composite and/or view level parent controls
var myParents = [];
var suffix = subCfg.objSuffixGet(childObj);
//var notRadio = (childObj.type.indexOf("radio") != 0);
var notRadio = (childObj.type !== "radio");
// find view name
var viewTag = subCfg.viewTagFind(childObj);
if (viewTag != undefined) {
var viewObj = subCfg.viewObjFind(viewTag,suffix);
if (viewObj != undefined) {
if (notRadio)
myParents[0] = viewObj;
else {
$(viewObj).each(function (i) { // radios will have more than one
if(childObj.value == this.value) {
myParents[0] = this;
return false; // breaks each, but not parentsFind
}
});
}
}
}
var compObj = subCfg.compositeObjFind(suffix);
if (compObj != undefined) {
if (notRadio)
myParents[myParents.length] = compObj;
else {
$(compObj).each(function (i) { // radios will have more than one
if(childObj.value == this.value) {
myParents[myParents.length] = this;
return false;
}
});
}
}
return myParents;
},
childrenFind: function (parentObj)
{ // returns array of all currently populated child controls related to this parent control
// parentObj could be composite level or view level
// parent object could be for vis which has special rules
var isComposite = false;
var isVis = false;
var suffix = subCfg.objSuffixGet(parentObj);
isVis = (suffix != undefined && suffix == 'vis'); // vis inside of subCfg
var viewTag = undefined;
if (isVis) { // This is a view control
isComposite = (suffix == undefined);
suffix = undefined;
if (!isComposite) {
var classList = $( parentObj ).attr("class").split(" ");
classList = aryRemove(classList,["viewDD","normalText","changed"]);
if (classList.length != 1) {
warn("DEBUG: Unexpected view vis class list:"+classList);
return [];
}
viewTag = classList[0];
}
} else { // normal obj
var viewCfg = normed($(parentObj).parents("tr[id^='tr_cfg_']"));
isComposite = (viewCfg == undefined); // is composite
if (!isComposite) {
viewTag = viewCfg.id.substring(7); // 'tr_cfg_'.length
}
}
if (isComposite) {
// There may be views
if (subCfg.viewTags.length > 0) {
var allChildren = [];
for (var ix = 0;ix < subCfg.viewTags.length;ix++) {
viewTag = subCfg.viewTags[ix];
// Get any view objs first
var viewObj = subCfg.viewObjFind(viewTag,suffix);
if (viewObj != undefined)
allChildren[allChildren.length] = viewObj;
// Now get children
var viewChildren = subCfg.childObjsFind(viewTag,suffix);
if (viewChildren.length > 0) {
if (allChildren.length == 0)
allChildren = viewChildren;
else
allChildren = jQuery.merge( allChildren, viewChildren );
}
}
return allChildren;
} else { // if no views then just get them all
return subCfg.childObjsFind(undefined,suffix);
}
} else {
return subCfg.childObjsFind(viewTag,suffix);
}
},
visChildrenFind: function (parentObj)
{ // returns array of all currently faux and populated vis child controls (which are not in subCfg div)
// parentObj could be composite level or view level
var subVis = $('.subVisDD'); // select:vis or faux:div
if ($(parentObj).hasClass('visDD')) // composite. views have .viewDD and sub .subVisDD
return subVis;
var classList = $( parentObj ).attr("class").split(" ");
classList = aryRemove(classList,["viewDD","normalText","changed"]);
if (classList.length != 1) {
warn("DEBUG: Unexpected view vis class list:"+classList);
return [];
}
return $(subVis).filter('.' + classList[0]);
},
checkOneSubtrack: function (subCb,check,enable)
{ // Handle a single check of a single subCb
// called by changing subVis to/from 'hide'
subCb.checked = check;
if (enable)
fauxDisable(subCb,false,"");
else
fauxDisable(subCb,true, "View is hidden");
subCfg.markChange(null,subCb);
subCfg.enableCfg(subCb,check);
matSubCbClick(subCb); // needed to mark matCBs, shadow and show/hide
},
propagateSetting: function (parentObj)
{ // propagate composite/view level setting to subtrack children
var children = subCfg.childrenFind(parentObj);
if(parentObj.type === "checkbox") {
var parentChecked = parentObj.checked;
$(children).each(function (i) {
if (this.type != 'hidden')
this.checked = parentObj.checked;
subCfg.clearChange(this);
});
//} else if(parentObj.type.indexOf("radio") == 0) {
} else if(parentObj.type === "radio") {
var parentVal = $(parentObj).val();
$(children).each(function (i) {
this.checked = ($(this).val() == parentVal);
subCfg.clearChange(this);
});
} else {// selects and inputs are easy
var parentVal = $(parentObj).val();
var updateDdcl = ($(parentObj).hasClass('filterBy'));// || $(parentObj).hasClass('filterComp'));
$(children).each(function (i) { // Should never be filterComp
$(this).val(parentVal);
subCfg.clearChange(this);
if (updateDdcl)
ddcl.onComplete(this);
});
}
},
propagateViewVis: function (viewObj,compositeVis)
{ // propagate vis from a view limiting with compositeVis
var limitedVis = Math.min(compositeVis,viewObj.selectedIndex);
var visText = 'hide';
if (limitedVis == 1)
visText = 'dense';
else if (limitedVis == 2) {
if (subCfg.canPack)
visText = 'squish';
else
visText = 'full';
} else if (limitedVis == 3)
visText = 'pack';
else if (limitedVis == 4)
visText = 'full';
var children = subCfg.visChildrenFind(viewObj);
$(children).each(function (i) {
if ($(this).hasClass('fauxInput')) {
$(this).text(visText);
} else {
$(this).attr('selectedIndex',limitedVis);
subCfg.clearChange(this);
}
});
},
propagateVis: function (parentObj,viewTag)
{ // propagate vis settings to subtrack children
if (viewTag == undefined) {
// Walk through views and set with this
var parentVis = parentObj.selectedIndex;
if (subCfg.viewTags.length > 0) {
for (var ix=0;ix<subCfg.viewTags.length;ix++) {
var viewObj = subCfg.viewObjFind(subCfg.viewTags[ix]);//,undefined);
if (viewObj != undefined)
subCfg.propagateViewVis(viewObj,parentVis);
}
} else { // No view so, simple
var visText = 'hide';
if (parentVis == 1)
visText = 'dense';
else if (parentVis == 2) {
if (subCfg.canPack)
visText = 'squish';
else
visText = 'full';
} else if (parentVis == 3)
visText = 'pack';
else if (parentVis == 4)
visText = 'full';
var children = subCfg.visChildrenFind(parentObj);
$(children).each(function (i) {
if ($(this).hasClass('fauxInput')) {
$(this).text(visText);
} else {
$(this).attr('selectedIndex',parentVis);
subCfg.clearChange(this);
}
});
}
} else {
// First get composite vis to limit with
var compObj = subCfg.compositeObjFind(undefined);
if (compObj == undefined) {
warn('DEBUG: Could not find composite vis object!');
return false;
}
subCfg.propagateViewVis(parentObj,compObj.selectedIndex);
}
},
inheritSetting: function (childObj,force)
{ // update value if parents values override child values.
var myParents = subCfg.parentsFind(childObj);
if (myParents == undefined || myParents.length < 1) {
//warn('DEBUG: No parents were found for childObj: '+childObj.name); // Not really a problem.
return true;
}
var isVis = (undefined == subCfg.objSuffixGet(childObj));
if (isVis) {
var subCb = subCfg.subCbFind(childObj);
if (subCb != undefined) {
var limitedVis = 9;
if (myParents.length == 1 && (force || subCfg.hasChanged(myParents[0])))
limitedVis = myParents[0].selectedIndex;
else if (myParents.length == 2) {
if (force || subCfg.hasChanged(myParents[0]) || subCfg.hasChanged(myParents[1]))
limitedVis = Math.min(myParents[0].selectedIndex,myParents[1].selectedIndex);
}
if (limitedVis < 9)
$(childObj).attr('selectedIndex',limitedVis);
}
} else {
var count = 0;
if(childObj.type === "checkbox") {
$(myParents).each(function (i) {
if (force || subCfg.hasChanged(this)) {
childObj.checked = this.checked;
count++;
}
});
//} else if(childObj.type.indexOf("radio") == 0) {
} else if(childObj.type === "radio") {
$(myParents).each(function (i) {
if (force || subCfg.hasChanged(this)) {
childObj.checked = this.checked;
// parentObj is already "tuned" to the correct radio, so this works
count++;
}
});
} else {// selects and inputs are easy
$(myParents).each(function (i) {
if (force || subCfg.hasChanged(this)) {
$(childObj).val($(this).val());
count++;
}
});
}
if (count > 1) // if hasChanged() is working, there should never be more than one
warn('DEBUG: Both composite and view are seen as updated! Named update is not working.');
}
},
currentCfg: undefined, // keep track of cfg while ajaxing, man
currentSub: undefined, // keep track of subtrack while ajaxing, dude
cfgFill: function (content, status)
{ // Finishes the population of a subtrack cfg. Called by ajax return.
var cfg = subCfg.currentCfg;
subCfg.currentCfg = undefined;
var cleanHtml = content;
cleanHtml = stripJsFiles(cleanHtml,true); // DEBUG msg with true
cleanHtml = stripCssFiles(cleanHtml,true); // DEBUG msg with true
cleanHtml = stripJsEmbedded(cleanHtml,true);// DEBUG msg with true
if (subCfg.visIndependent) {
var ix = cleanHtml.indexOf('</SELECT>');
if (ix > 0)
cleanHtml = cleanHtml.substring(ix+'</SELECT>'.length);
while(cleanHtml.length > 0) {
ix = cleanHtml.search("<");
cleanHtml = cleanHtml.substring(ix);
ix = cleanHtml.search(/\<BR\>/i);
if (ix != 0)
break; // Not found or not at start.
else
cleanHtml = cleanHtml.substring(4); // skip past <BR> and continue
}
} else {
var ix = cleanHtml.indexOf('<B>Display mode: </B>');
if (ix > 0)
cleanHtml = cleanHtml.substring(ix+'<B>Display mode: </B>'.length); // Excludes vis!
}
//cleanHtml = cleanHtml.substring(ix);
ix = cleanHtml.indexOf('</FORM>'); // start of form already chipped off
if (ix > 0)
cleanHtml = cleanHtml.substring(0,ix - 1);
//cleanHtml = "<div class='blueBox' style='background-color:#FFF9D2; padding:0.2em 1em 1em; float:left;'><CENTER><B>Subtrack Configuration</B></CENTER><BR>" + cleanHtml + "</div>"
//cleanHtml = "<div class='blueBox' style='background-color:#FFF9D2; padding:0.2em 1em 1em; float:left;'><B>Subtrack visibility:</B> " + cleanHtml + "</div>"
cleanHtml = "<div class='blueBox' style='background-color:#FFF9D2; padding:0.5em 1em 1em;'>" + cleanHtml + "</div>"
$(cfg).html(cleanHtml);
$(cfg).addClass('filled');
var boxWithin = $(cfg).find('.blueBox');
if (boxWithin.length > 1)
$(boxWithin[1]).removeClass('blueBox');
//$(cfg).html("<div style='font-size:.9em;'>" + cleanHtml + "</div>");
var subObjs = $(cfg).find('input,select').filter("[name]");
if (subObjs.length == 0) {
warn('DEBUG: Did not find controls for cfg: ' + cfg.id);
return;
}
$(subObjs).each(function (i) {
if (this.name != undefined) { // The filter("[name]") above didn't do it!
if (this.type != 'hidden') {
subCfg.inheritSetting(this,false); // updates any values that have been changed on this page
var suffix = subCfg.objSuffixGet(this);
if (suffix != undefined)
$(this).change( subCfg.markChange );
else
warn("DEBUG: couldn't find suffix for subtrack control: "+this.name);
}
}
});
// finally show
$(cfg).show();
// Tricks to get this in the size and position I want
$(cfg).css({ position: 'absolute'});
var myWidth = $(cfg).width();
var shiftLeft = -1;
if (subCfg.visIndependent) {
shiftLeft *= ($(cfg).position().left - 125);
var subVis = normed($('div#' + subCfg.currentSub+'_faux'));
if (subVis != undefined)
subCfg.replaceWithVis(subVis,subCfg.currentSub,false);
}
else
shiftLeft *= ($(cfg).position().left - 40);
$(cfg).css({ width: myWidth+'px',position: 'relative', left: shiftLeft + 'px' });
// Setting up filterBys must follow show because sizing requires visibility
$(cfg).find('.filterBy').each( function(i) { // Should never be filterComp
this.id = this.name.replace(/\./g,'_-'); // Must have id unique to page!
ddcl.setup(this, 'noneIsAll');
});
// Adjust cfg box size?
// Especially needed for filterBys, but generic in case some other overrun occurs
var curRight = $(cfg).offset().left + $(cfg).width();
var calcRight = curRight;
$(cfg).find(':visible').each( function(i) { // All visible, including labels, etc.
var childRight = $(this).offset().left + $(this).width();
if (calcRight < childRight)
calcRight = childRight;
});
if (curRight < calcRight) {
var cfgWidth = calcRight - $(cfg).offset().left + 16; // clip offset but add some for border
$(cfg).css({ width: cfgWidth + 'px' });
// Now containing tables may need adjustment
var tables = $(cfg).parents('table');
var maxWidth = 0;
$(tables).each(function(i) {
var myWidth = $(this).width();
if (maxWidth < myWidth)
maxWidth = myWidth;
else if (maxWidth > myWidth)
$(this).css('width',maxWidth + 'px');
});
}
},
cfgPopulate: function (cfg,subtrack)
{ // Populates a subtrack cfg dialog via ajax and update from composite/view parents
subCfg.currentCfg = cfg;
subCfg.currentSub = subtrack;
$.ajax({
type: "GET",
url: "../cgi-bin/hgTrackUi?ajax=1&g="+subtrack+"&hgsid="+getHgsid()+"&db="+getDb(),
dataType: "html",
trueSuccess: subCfg.cfgFill,
success: catchErrorOrDispatch,
error: errorHandler,
cmd: "cfg",
cache: false
});
},
replaceWithVis: function (obj,subtrack,open)
{ // Replaces the current fauxVis object with a true visibility selector
if ($(obj).hasClass('disabled'))
return;
var classList = $( obj ).attr("class").split(" ");
classList = aryRemove(classList,["disabled"]);
var view = classList[classList.length - 1]; // This relies on view being the last class!!!
var selectHtml = "<SELECT name='"+subtrack+"' class='normalText subVisDD "+view+"'";
selectHtml += " style='width:70px;'>";
var selected = $(obj).text();
var visibilities = ['hide','dense','squish','pack','full'];
if (subCfg.canPack == false)
visibilities = ['hide','dense','full'];
$(visibilities).each( function (ix) {
selectHtml += "<OPTION"+(visibilities[ix] == selected ? " SELECTED":"")+">";
selectHtml += visibilities[ix]+"</OPTION>";
});
selectHtml += "</SELECT>";
$(obj).replaceWith(selectHtml);
var newObj = $("select[name='"+subtrack+"']");
if (open) {
$(newObj).css({'zIndex':'2','vertical-align':'top'});
$(newObj).attr('size',visibilities.length);
$(newObj).one('blur',function (e) {
$(this).attr('size',1);
$(this).unbind('click');
});
$(newObj).one('click',function (e) {
$(this).attr('size',1);
$(this).unbind('blur');
});
$(newObj).focus();
}
$(newObj).change(function (e) {
if ($(this).attr('size') > 1) {
$(this).attr('size',1);
$(this).unbind('blur');
$(this).unbind('click');
}
if (this.selectedIndex == 0) { // setting to hide so uncheck and disable.
// Easiest is to uncheck subCB and reset vis
// so that the reverse action makes sense
var subCb = normed($("input[name='" + this.name + "_sel']"));
if (subCb != undefined) {
subCfg.checkOneSubtrack(subCb,false,true);
subCfg.inheritSetting(this,true);
} else {
warn('DEBUG: Cant find subCB for ' + this.name);
}
} else {
subCfg.markChange(e,this);
// If made visible, be sure to make composite visible
// But do NOT turn composite from hide to full, since it will turn on other subs
// Just trigger a supertrack reshaping
if (this.selectedIndex > 0) {
//exposeAll();
var visDD = normed($("select.visDD"));
if (visDD != undefined) {
if ($(visDD).hasClass('superChild'))
visTriggersHiddenSelect(visDD);
}
}
}
});
},
enableCfg: function (subCb,setTo)
{ // Enables or disables subVis and wrench
var tr = normed($(subCb).closest('tr'));
if (tr == undefined) {
warn("DEBUG: subCfg.enableCfg() could not find TR for CB: "+subCb.name);
return false;
}
var subFaux = normed($(tr).find('div.subVisDD'));
if (subFaux != undefined) {
if (setTo == true)
$(subFaux).removeClass('disabled');
else
$(subFaux).addClass('disabled');
} else {
var subVis = normed($(tr).find('select.subVisDD'));
if (subVis != undefined) {
$(subVis).attr('disabled',!setTo);
}
}
var wrench = normed($(tr).find('span.clickable')); // TODO tighten this
if (wrench != undefined) {
if (setTo == true)
$(wrench).removeClass('disabled');
else {
$(wrench).addClass('disabled');
var cfg = normed($(tr).find('div.subCfg'));
if (cfg != undefined)
$(cfg).hide();
}
}
},
cfgToggle: function (wrench,subtrack)
{ // Opens/closes subtrack cfg dialog, populating if empty
var cfg = normed($("div#div_cfg_"+subtrack));
if (cfg == undefined) {
warn("DEBUG: Can't find div_cfg_"+subtrack);
return false;
}
if ($(cfg).css('display') == 'none') {
if ($(wrench).hasClass('disabled'))
return;
// Don't allow if this composite is not enabled!
// find the cb
var tr = $(cfg).parents('tr').first();
var subCb = normed($(tr).find("input[name='"+subtrack+"_sel']"));
if (subCb == undefined) {
warn("DEBUG: Can't find subCB for "+subtrack);
return false;
}
//if (subCb.disabled == true) // || subCb.checked == false)
if (isFauxDisabled(subCb,true))
return false;
if(metadataIsVisible(subtrack))
metadataShowHide(subtrack,"","");
if ($(cfg).hasClass('filled'))
$(cfg).show();
else
waitOnFunction( subCfg.cfgPopulate, cfg, subtrack );
} else
$(cfg).hide();
return false; // called by link!
},
viewInit: function (viewTag)
{ // sets up view controls for propagation
var tr = normed($('tr#tr_cfg_'+viewTag));
if (tr != undefined) {
// iterate through all matching controls and setup for propgation and change flagging
var viewObjs = $(tr).find('input,select');
if (viewObjs.length > 0) {
$(viewObjs).each(function (i) {
if (this.type != 'hidden') {
$(this).bind('change',function (e) {
subCfg.markChange(e,this);
subCfg.propagateSetting(this);
});
}
});
}
}
// Now vis control
var viewVis = normed($("select.viewDD."+viewTag));
if (viewVis == undefined) {
warn('DEBUG: Did not find visibility control for view: ' + viewTag);
return;
}
$(viewVis).bind('change',function (e) {
subCfg.markChange(e,viewVis);
subCfg.propagateVis(viewVis,viewTag);
});
},
initialize: function ()
{ // sets up all composite controls and then all view controls
// onchange gets set to mark controls as 'changed'. Unchanged controls will
// be disabled on 'submit'. Disabled controls will not get to the cart!
var compVis = $('.visDD');
if (compVis == undefined || compVis.length < 1) {
warn('DEBUG: Did not find visibility control for composite.');
return;
}
if (compVis.length > 1) {
warn('DEBUG: Multiple visibility controls for composite???');
return;
}
if ($(compVis).children('option').length < 5)
subCfg.canPack = false; // Note that if composite vis has no pack then no child should have pack
subCfg.compositeName = $(compVis).attr('name');
subCfg.visIndependent = ($('.subVisDD').length > 0); // Can subtracks have their own vis?
// Set up vis propagation and change flagging
compVis = compVis[0];
$(compVis).bind('change',function (e) {
subCfg.markChange(e,compVis);
subCfg.propagateVis(compVis,undefined);
});
// SubCBs will may enable/diable vis/wrench and will be flagged on change
var subCbs = $('input.subCB');
$(subCbs).change( function (e) {
subCfg.enableCfg(this, (this.checked && !isFauxDisabled(this, true)));
subCfg.markChange(e,this);
});
// iterate through views
var viewVis = $('select.viewDD');
$(viewVis).each(function (i) {
var classList = $( this ).attr("class").split(" ");
classList = aryRemove(classList,["viewDD","normalText","changed"]);
if (classList.length == 0)
warn('DEBUG: View classlist is missing view class.');
else if (classList.length > 1)
warn('DEBUG: View classlist contains unexpected classes:' + classList);
else {
subCfg.viewTags[i] = classList[0];
subCfg.viewInit(subCfg.viewTags[i]);
}
});
// Tricky for composite level controls. Could wrap cfg controls in new div.
// DO THIS AFTER Views
// NOTE: excluding sortOrder and showCfg which are special cases we don't care about in subCfg
- var compObjs = $('select,input').filter("[name^='"+subCfg.compositeName+"\\.'],[name^='"+subCfg.compositeName+"_']").not(".viewDD");
+ // Excluding views and subCBs because a {composite}_{subtrack} naming scheme may be used
+ var compObjs = $('select,input').filter("[name^='"+subCfg.compositeName+"\\.'],[name^='"+subCfg.compositeName+"_']").not(".viewDD,.subCB");
if (compObjs.length > 0) {
$(compObjs).each(function (i) {
if (this.type != 'hidden') {
// DEBUG -------------
if (this.id != undefined
&& this.id.length > 0
&& $(this).hasClass('filterBy') == false
&& $(this).hasClass('filterComp') == false)
- warn('DEBUG: Not expected control with name ['+this.name + '], and id #'+this.id);
- // DEBUG -------------
+ warn('DEBUG: Unexpected control with name ['+this.name + '], and id #'+this.id);
+ // DEBUG ------------- Helps find unexpected problems.
$(this).change(function (e) {
subCfg.markChange(e,this);
subCfg.propagateSetting(this);
});
}
});
}
// Because of fauxDisabled subCBs, it is necessary to truly disable them before submitting.
$("FORM").submit(function (i) {
$('input.subCB.changed.disabled').attr('disabled',true); // shadows will go to cart as they should
// Unchanged controls will be disabled to avoid sending to the cart
$('select,input').filter("[name]").not(".allOrOnly").not('.changed').each( function (i) {
if (this.type != 'hidden' || $(this).hasClass('trPos')
|| $(this).hasClass('cbShadow') || $(this).hasClass('sortOrder')) {
// hiddens except priority and boolshad are all sent to the cart
// disable instead of unname because unname fills cart with a lot of garbage (Linux/FF)!
this.disabled = true;
}
});
});
}
};