From fd0da5abc3d548fdb9edde1b88d897b652745288 Mon Sep 17 00:00:00 2001 From: alessandro Date: Thu, 30 Jan 2014 14:24:05 +0100 Subject: [PATCH] Backport of cfg-viewer.py from CMSSW_7_1_0_pre1. --- FWCore/Utilities/scripts/cfg-viewer.py | 2399 +++++++++++++++--------- 1 file changed, 1502 insertions(+), 897 deletions(-) diff --git a/FWCore/Utilities/scripts/cfg-viewer.py b/FWCore/Utilities/scripts/cfg-viewer.py index 6f146a4d4aa18..b96b989141381 100755 --- a/FWCore/Utilities/scripts/cfg-viewer.py +++ b/FWCore/Utilities/scripts/cfg-viewer.py @@ -1,939 +1,1544 @@ #!/usr/bin/env python # -*- coding: latin-1 -*- -from optparse import OptionParser -import imp import re -import sys -import shutil -import os +import collections import FWCore.ParameterSet.Config as cms - -modsNames=[] -newModsNames,oldMods,allMods=[],[],[] - -class generateBrowser: - def __init__(self,htmlFile, cfgFile): - self.html = htmlFile - self.theDir='' - self.pathName = "paths.html" - self.js = "search.js" - self.thecss = "style.css" - - rest= html.rsplit('/',1) - # Find where the html file is to be stored. - # store everything else there, move other stuff there. - if(len(rest)>1): - self.theDir=rest[0]+'/' - if(not os.path.isdir(self.theDir)): - os.mkdir(self.theDir) - self.javascript("%s%s"%(self.theDir,self.js)) - self.css("%s%s"%(self.theDir,self.thecss)) - self.pathLi=""" -
  • %(nameID)s:
  • - """ - self.cfg = imp.load_source("cfg", cfgFile) - # do the psets (in other file, provide link to it.) - psetTypes = open("%sparamTypes.js"%(self.theDir),'w') - psetTypes.close() - print "Starting print out of psets." - self.doPsets() - print "Finished finding psets. Now onto paths..." - self.doPaths() - print "Paths done" - - def doPaths(self): - modHTMLName= "%sparamTypes.js"%(self.theDir) - modToPathName = "%smodToPath.js" %(self.theDir) - tempFile ="%stemp.js"%(self.theDir) - f={modHTMLName:"params",modToPathName:"modules"} - o={modHTMLName:"a",modToPathName:"w"} - theS="var %s={" - for key in f.keys(): - curFile = open(key,o[key]) - curFile.write(theS%(f[key])) - curFile.close() - first = True - liToBeWritten, frmPathHolder="", ""; - className, theS,frmPathStr ="path","",'%s%s:["%s"]' - newModsStr, oldModsStr='%s\n%s:["%s"]', '%s"%s",%s' - dataFile= open(modHTMLName,'a') - v = visitor(dataFile) - paths = self.cfg.process.paths - global oldMods - global allMods - global newModsNames - for item in paths.keys(): - oldMods=[] # module names which have been seen before. - # needed so we can add this path name to the dictionary in modToPath.js - allMods =[]# set of current path modules names including duplciates. - newModsNames=[] # set of current paths module name without duplicates. - # could get oldMods from all Mods if we take away all newModsNames - liToBeWritten +=format(self.pathLi,nameID=item,className=className) - paths[item].visit(v) - frmPathHolder +=frmPathStr%(theS,item,"\",\"".join(allMods)) - fromMod = open(modToPathName, 'r') - fromModTemp = open(tempFile, 'w') - for line in fromMod: - tLine= re.sub('\[.*?\]', "",line) - result = re.split(':|,', tLine[tLine.find('{')+1:]) - namesFound = [x for i, x in enumerate(result)if not i%2] - # the new names we have is going to be smaller, - # so we'll loop round that - for each in oldMods: - if(each in namesFound): - oldMods.remove(each) - index = line.find(each)+len(each)+2 # as will have :[ after it - line = oldModsStr %(line[:index],item,line[index:]) - fromModTemp.write(line) - fromMod.close() - for each in newModsNames: - fromModTemp.write(newModsStr%(theS,each,item)) - theS="," - fromModTemp.close() - os.rename(tempFile,modToPathName) - if(first): - theS="," - first=False - out = open("%s%s"%(self.theDir,self.pathName), 'w') - self.printStart(self.js,self.thecss, """disabled="True" """, out) - out.write(" See Psets \n\n\n"%(self.html.rsplit('/',1)[-1],liToBeWritten)) - out.close() - dataFile.write("};\nfunction getAllParams(){\n"\ - "var newD ={};\n var keys = Object.keys(params);\n"\ - "for(var i=0; i See Paths\n"%(self.pathName,writeOut)) - out.close() - - psetTypes = open("%sparamTypes.js"%(self.theDir),'w') - psetTypes.write("psetParams=%s\nfunction getAllpsetParams(){\n"\ - "return psetParams;}\n"\ - " function getpsetParams(modName){\n"\ - " return psetParams[modName];}\n"\ - "function getInnerpsetParams(parentsNames){\n"\ - "var currentList = psetParams[parentsNames[0]];\n"\ - "for(var i=1; i < parentsNames.length;i++){\n"\ - " for(var p=0; p < currentList.length;p++){\n"\ - " if(currentList[p][0]==parentsNames[i]){\n"\ - " var found = currentList[p][1];\n"\ - " break;\n }\n}\n currentList = found;\n}\n"\ - " return currentList;}\n"%(theDict)) - - # Start of html files. - def printStart(self,js, css, dis, out): - scripts =""" - - """ - classType="pset" - buttons=""" - - """ - if(len(dis)>0): - classType="path" - buttons=""" - - - - - - """ - scripts= """ - - - - """ - out.write( """ - - - - - cfg-browser - - %(scripts)s - - - - - - -
    - - - -
    -


    - - Hide All -

    - - - -
    Show module File. -
    - - """%{'js':js,'option':buttons, 'css':css, 'dis':dis, - 'scripts':scripts, 'class':classType}) - - def javascript(self,thejs): - jsFile = open(thejs, 'w') - jsFile.write( """ -$(document).ready(function(){ - $(document).on('click', '#search', function(e){ - numFound = 0; - var par = $(this).parent(); - var id = $(par).find('#searchType').attr('id'); - var option = $('#'+id+' option:selected').text(); - var val = $(par).find('#searchWord').val() - var reg = new RegExp("("+val+")", "gi"); - switch(option){ - case "Path": - reset('li.path', e, true); - numFound = topLevelMatch(keys(),reg,false); // will stay the same - - case "Module": - if(typeof modKeys != 'function' && false){ - //if modKeys is not defined means we're using pset html. - //maybe change this so instead we define top layer li with class top - reset('li.module', e, true); - //numFound = topLevelMatch - numFound = topLevelMatch( $('li.module'),reg,true); - } - else{ - // for now pretend that its in html. - //searchReplaceHTML(reg, "module"); - // if not in the html - //Okay can either, get allmatched modules and add them - // to all html parents - // or go round paths and get all matched modules adding to tghe path - var strings = allMods(reg); - var Li = $(document.createElement('li')).attr( - "class","module expand"); - console.log("hereiam before"); - searchReplaceNonHTML(strings,Li, reg) - } - - case "File Name": - //get all modules names, get files for all modules - // once we have a list of all modules we want - // add those modules to - - case "Parameter": - // gives the params which match the reg. - numFound = lowerLevels(reg,doInnerParams, e) - - case "Type": - reset('li.path',e,true); - // similar to params except we're looking at - // the types and not the params names. - // so need to get all the params, loop over the keys - var matches = matchValue(reg); - console.log("matches are "+ matches) - - case "Value": - numFound = lowerLevels(reg,doInnerValue, e) - } - $('#searchNumber').html(numFound+" found."); - $('#searchReset').show(); - }); - -//do Params, values. -function lowerLevels(reg,funcCall, e){ - reset('li.path', e, true); - var numFound=0; - if($("span[id='pageType']").attr("data-type")=="pset"){ - var matches = getAllpsetParams(); - } - else var matches = getAllParams(); - - var keys = Object.keys(matches); - for(var i=0; i < keys.length; i++){ - var theKey = keys[i]; - var params = matches[theKey]; - var theMod = moduleLI.clone().attr("data-name",theKey).text(theKey); - // need to make the ul - tempNumber =0; - var theUL = funcCall(params,reg); - if(tempNumber ==0)continue; - theMod.append(theUL); - // for now just do parents - var pathsAddTo = getPaths(theKey); - var mul =0; - for(var k=0; k < pathsAddTo.length;k++){ - // all paths to be added to. - var theP = pathsAddTo[k]; - // find the parent. - $('li.path[name='+theP+']').each(function(){ - // for each one add the theMod. - $(this).children().empty(); - $(this).append(theMod.clone()); - mul +=1; - }); - } - numFound += (tempNumber*mul) - } - return numFound; -} +import FWCore.ParameterSet.SequenceTypes as seq -function doInnerValue(modules,reg){ - var theUL = UL.clone(); - // okay we have a list where we want to check the - // inner list is an inner list. - for(var i=0; i < modules.length; i++){ - var innerList= modules[i]; - var theName = innerList[0]; - var next = innerList[1]; - // next could be inner or could be what we want. - if(typeof(next)=="object"){ - // we have inner params, recurse! - var oldNum = tempNumber - var newUL = doInnerValue(next, reg); // will return a ul. - if(tempNumber == oldNum){ - var li= LIExpand.clone().attr("data-name", theName).html(theName); - } - else { - var li= LIExpanded.clone().attr("data-name", theName).html(theName); - li.append(newUL); - } - } - else{ - // else do normal and make the - // rename the value - var newValue = next.replace(reg, "$1"); - if(newValue != next){ - tempNumber +=next.match(reg).length; - } - var li= paramLI.clone().attr("data-name",theName).html(theName); - var theClass="value"; - li.append(span.clone().attr("class", "value").html(": "+newValue)); - innerList.slice(2).forEach(function(i){ - li.append(span.clone().attr("class", "type").text(" ("+i+")")); - }); +class unscheduled: + def __init__(self,cfgFile,html,quiet,helperDir,fullDir): + self._html = html + #self._serverName = os.path.join(os.path.split(html)[0],"EditingServer.py") + self._quiet = quiet + self._theDir= fullDir + self._helperDir = helperDir + self._mother,self._daughter ={},{} + self._reg = re.compile("['>]") + self._data,self._types,self._genericTypes={},{},{} + self._dictP ="DictParent" + self._modSeqP = "ModuleSeqParent" + self._prodConsP= "ProdConsumParent" + self._parents = { + "DictParent":{"creator":"dictCreate","simple": True}, + "ModuleSeqParent":{"creator":"modSeqCreate","simple": False}, + "ProdConsumParent":{"creator":"prodConCreate","simple": False} } - theUL.append(li); - } - return theUL; - } + for name,x in self._parents.iteritems(): + x["pfile"] = self._filenames(name) + x["cfile"] = self._filenames(x["creator"]) + self._type = "%stypes.js"%(fullDir) + self._allJSFiles =["types.js"] + self._config = ConfigDataAccessor.ConfigDataAccessor() + self._config.open(cfgFile) + self._computed = self._proceed(cfgFile) -function doInnerParams(params,reg){ - var theUL = UL.clone(); - // okay we have a list where we want to check the - // inner list is an inner list. - for(var i=0; i < params.length; i++){ - var param = params[i];// it's name. - var theName = param[0]; - var newName = theName.replace(reg, "$1"); - if(newName != theName){ - tempNumber +=theName.match(reg).length; - } - var next = param[1]; - if(typeof(next)=="object"){ - // we have inner params, recurse! - //var cloLI= LIExpand.clone().attr("name", theName).text(theName); - //var ul = UL.clone(); - var old = tempNumber; - var newUL = doInnerParams(next, reg); // will return a ul. - if(old == tempNumber){ - var li= LIExpand.clone().attr("data-name", theName).html(newName); - } - else { - var li= LIExpanded.clone().attr("data-name", theName).html(newName); - li.append(newUL); - } - } - else{ - // else do normal and make the - var li= paramLI.clone().attr("data-name",theName).html(newName); - var theClass="value"; - for(var w=1; w < param.length;w++){ - // do types etc. - if(w==1) - li.append(span.clone().attr("class", "value").text(": "+param[w])); - else - li.append(span.clone().attr("class", "type").text( - " ("+param[w]+")")); - } - } - theUL.append(li); - } - return theUL; - } - var LI= $(document.createElement('li')); - var moduleLI= LI.clone().attr("class","module expand"); - var paramLI= LI.clone().attr("class","param expanded"); - var UL = $(document.createElement('ul')); - var span = $(document.createElement('span')); - var LIExpand = LI.clone().attr("class","expand paramInner"); - var LIExpanded = LI.clone().attr("class","expanded paramInner"); -// All params send here. -//[[normaloparam, value,type] -//[inner[innervalues, value,type]][norm, value, type]] -// we will get [normaloparam, value,type] etc -var numFound =0; -var tempNumber =0; - /* - String format should have where they want the string to go as name. - For module just now. // - */// stringformat would be what we want it to go in, - function searchReplaceNonHTML(strings, theLi, regex){ - // we have the things we want, the string should just be the - // what we want to be shwn i.e. an LI, which we clone. - var UL = $(document.createElement('ul')); - for(var i=0; i $1")); - var paths = getPaths(thisOne); - for (var p=0; p < paths.length; p++){ - // need to find the path on the page and add the module to it. - $('li.path[name='+paths[p]+']').each(function(){ - // for each add this LI - if($(this).children('ul').length ==0){ - $(this).append(UL.clone().append(LI.clone())); - } - else{ - $(this).children('ul').append(LI.clone()); - // so all paths dont point to the same LI,maybe can change this? - } - $(this).attr("class","expanded path"); - }); - } - } - } - /* - Search when what we're looking for is in HTML but not topLevel element. - To be global replace, find should be regexp object with g. - */ - function searchReplaceHTML(find,identifier){ - var found =0; - var foundParents=[]; - var notFoundLI=[]; - $("li ."+identifier).each(function(){ - var howMany=0; - if(howmany = $(this).attr("data-name").match(find)){ - // we found you - found +=howMany - $(this).html() = $(this).html().replace(find,"$1"); - // now find parents - // if parents not already showen show them - $(this).parents('ul').each(function(){ - if(foundParents.indexOf(this) ==-1){ - $(this).show(); - foundParents.append(this); - } - else{ - // already done these parents - return false;// (i.e. break out loop);// the parents loop. - } - }); - } - else{ - notFoundLI.append(this); - // not a match, can just try and find a ul parent, - //if there is one, then we need to know whether to - // hide it.TODO or do nothing. - } - }); - // now we have list of parents we want to hide all other parents - $(notFoundLI).each(function(){ - $(this).parents('ul').each(function(){ - if(foundParents.indexOf(this) ==-1){ - $(this).hide(); - } - else{ - // already done these parents - return false;// (i.e. break out loop);// the parents loop. - } - }); - }); - return found; - } - /* - Resets search ouput. - */ - $(document).on('click', '#searchReset', function(e){ - $('#searchNumber').html(""); - if($(this).attr('class') == "pathReset"){ - reset('li.path',e,true); - } - else{ - reset('li.module',e,true); - } - $(this).hide(); - }); - /* - Hides children of top level. TODO: Done - works - */ - $(document).on('click', '#hide', function(e){ - //for hiding we just get top level and remove children. - if($(this).css('cursor')!='default'){ - $('#searchNumber').html(""); - if($(this).attr('class') == "pathReset"){ - var selec ='li.path'; - } - else var selec ='li.module'; - $(selec).each(function(){ - if(removeChildren(this, e))toggleExpand(this, e); - }); - $(this).css('color','#CCCCCC'); - $(this).css('cursor','default'); - } - }); - /* - Retrieves and expands path elements. - works - */ - $(document).on('click', '.path.expand',function(event){ - var UL = addModules(getModules($(this).attr('data-name'))); - $(this).append(UL); - $('#hide').css('color','') - $('#hide').css('cursor','') - }); - /* - Adds modules to a list and returns list. - */ - function addModules(results){ - var UL = $(document.createElement("ul")); - var LI = $(document.createElement('li')).attr("class","module expand"); - for(var i=0; i < results.length; i++){ - var theName = results[i]; - var val = theName+"("+getType(theName)+")" - if(document.getElementById("ShowFiles").checked) - val+=" ("+getFile(theName)+")" - UL.append(LI.clone().attr("data-name", theName).text(val)); - } - return UL; - } + def _proceed(self, fileName): + #self._filename= "" + topObjs = self._config.topLevelObjects() + if(len(topObjs)): + self._getData(topObjs) + ty = "genericTypes" + with open(self._type, 'w') as f: + f.write("var %s=%s"%(ty,genericTypes)) + self._createObjects() + self._writeDictParent(ty) + self._writeModSeqParent() + self._writeProdConsum() + fN = fileName.split("./")[-1].split(".")[0] + JS = ["%s%s"%(self._helperDir,x)for x in self._allJSFiles] + html(self._html,JS,self._data, self._theDir, self._helperDir, + self._config.process().name_(), fN) + + return True + else: + print "---Nothing found for file %s."\ + " No computation done.---"%(fileName) + return False - /* - Retrieve and expands module elements. - //changed to deal with new data format, - //(data now seperate from html specification) - works - */ - $(document).on('click','.module.expand', function(event){ - addParams(this); - event.stopPropagation(); - }); - - /* - Add params to the object. Object can be of any type - (normally module or param). - It's name needs to be in the data to find its parameters. - works - */ - function addParams(obj, results){ - var LIBasic = $(document.createElement('li')).attr("class","param"); - var LIExpand = LIBasic.clone().attr("class","expand paramInner"); - var span = $(document.createElement("span")); - var UL = $(document.createElement("ul")); - // getParams returns list of list. - // Format:[[name,value,type,trackedornot]].CHANGED!! - // new format - // :[[name, value,type,trackedornot],[namePset,[name,value,type]]] - // If 2nd element is list then its a pset. - var objName = $(obj).attr('data-name'); - if(!results){ - if($("span[id='pageType']").attr("data-type")=="pset"){ - var results = getpsetParams(objName); - } - else { - var results = getParams(objName); - var type = getType(objName); - if(type == "Sequence"){ - // inside will be names of modules - //- so do the same as if this was a path obj - var ul = addModules(results); - $(obj).append(ul); - return - } - } - } - for(var i =0; i < results.length; i++){ - var all = results[i].slice(); - var theName = all.shift(); - if(typeof(all[0]) == "object"){ - var cloLI= LIExpand.clone().attr("data-name", theName).text(theName); - //for(var p=0; p < all[0].length;p++){ - // add all children. - //} - } - else{ - // Not a Pset. - var cloLI = LIBasic.clone().attr("data-name", theName).text(theName); - var value = all.shift() - // formating so lots of strings look nicer - if(value.indexOf(",")>-1) - value = "
      "+value.replace(/,/g, "
    • ")+"
    " - cloLI.append(span.clone().attr("class","value").html(": "+value)) - for(var p=0; p < all.length; p++){ - cloLI.append(span.clone().attr("class","type").text( - " ("+all[p]+")")) - } - } - UL.append(cloLI); - } - $(obj).append(UL); - $('#hide').css('color','') - $('#hide').css('cursor','') - } - /* - Hides/Shows children from class param. - //changed to deal with new data format - works - */ -$(document).on('click', '.paramInner.expand, .paramInner.expanded', - function(event){ - if($(this).children('ul').length ==0){ - // find parents - var theClass ="" - var obj = this; - var parents =[$(this).attr("data-name")] - while(theClass.indexOf("module")==-1){ - obj = $(obj).parent(); - if(obj.prop("tagName")=="UL") continue; - var parName = obj.attr("data-name"); - parents.unshift(parName); - theClass = obj.attr("class"); - } - if($("span[id='pageType']").attr("data-type")=="pset"){ - var result = getInnerpsetParams(parents); - } - else var result = getInnerParams(parents); - addParams(this, result); - } - else{ - $(this).children('ul').toggle(); + def _getData(self,objs): + # i will loop around objs and keep adding things which are configFolders + calc =[] + for each in objs: + name = self._config.label(each) + kids = self._config.children(each) + if(not kids): + if(not self._quiet):print name, "is empty." + continue + # Taking liberty of assuming all are of same type. + ty = type(kids[0]) + if(ty is ConfigDataAccessor.ConfigFolder): + objs.extend(kids) + else: + if(not self._quiet):print "computing %s.."%(name) + if(isinstance(kids[0], seq._ModuleSequenceType)): + # e.g.it's a path, sequence or endpath + self._doSequenceTypes(kids,name) + else: + # e.g. it's a pset etc. + self._doNonSequenceType(kids,name) + calc.append(name) + # now i will print out producers/consumers. + if(self._quiet):print "calculated: %s."%(", ".join(calc)) + self._producersConsumers() + + # Get the data for items which are SequenceTypes + def _doSequenceTypes(self,paths,namep): + theDataFile,fullDataFile = self._calcFilenames(namep) + topLevel,fullTopLevel = self._calcFilenames("top-"+namep) + json = [topLevel,theDataFile] + cap = namep.capitalize() + bl={} + types = False + with open(fullDataFile,'w') as data: + data.write("{") + v = visitor(data, self._config) + for item in paths: + if(not types): + spec = self._checkType(item) + self._saveData(spec,self._parents[self._modSeqP]["creator"],json) + types = True + name = self._config.label(item) + # Dont think we need to check for this here. + self._mothersDaughters(name,item) + key = self._config.label(item) + item.visit(v) + bl[key]= getParamSeqDict(v._finalExit(), + self._config.fullFilename(item), self._config.type(item), "") + data.write("}") + with open(fullTopLevel, 'w') as other: + other.write(JSONFormat(bl)) + + # Check type of item and return the specofic type + def _checkType(self,item): + gen, spec = re.sub(self._reg, "", + str(item.__class__)).split(".")[-2:] + doTypes(spec,gen) + return spec + + # find the mothers and daughters, storing them + def _mothersDaughters(self,name, item): + mo =self._config.motherRelations(item) + dau = self._config.daughterRelations(item) + if(mo): + self._mother[name] = [self._config.label(i) for i in mo] + if(dau): + self._daughter[name] = [self._config.label(i) for i in dau] + + # Find data for objs which are not SequenceTypes + def _doNonSequenceType(self,objs, globalType): + everything={} + always= types = False + theDataFile, fullDataFile = self._calcFilenames(globalType) + # For modules types can be diff + # so we always want to call the doTypes method + if(globalType =="modules"): + self._saveData(globalType.capitalize(), + self._parents[self._dictP]["creator"], + [theDataFile]) + always = types = True + for item in objs: + if(always or not types): + spec = self._checkType(item) + if(not types): + self._saveData(spec,self._parents[self._dictP]["creator"], + [theDataFile]) + types = True + name = self._config.label(item) + self._mothersDaughters(name, item) + if(isinstance(item,cms._Parameterizable)): + out = getParameters(item.parameters_()) + elif(isinstance(item,cms._ValidatingListBase)): + out = listBase(item) + if(isinstance(item,cms._TypedParameterizable)): + oType = item.type_() + else: + oType ="" + everything[name] = getParamSeqDict(out, + self._config.fullFilename(item), + self._config.type(item), oType) + with open(fullDataFile,'w') as dataFile: + dataFile.write(JSONFormat(everything)) + + # Return json data file names + def _calcFilenames(self,name): + return self._filenames(name,"data-%s.json") + + # Return filenames + def _filenames(self,name,option=""): + if(option): basicName = option%(name) + else: basicName = "%s.js"%(name) + return (basicName, "%s%s"%(self._theDir,basicName)) + + # write out mothers and daughters (producers/consumers). + def _producersConsumers(self): + if(not self._mother and not self._daughter): + return + for name,theDict in {"producer":self._mother, + "consumer":self._daughter}.iteritems(): + thedataFile , fulldataFile = self._calcFilenames(name) + self._saveData(name.capitalize(), + self._parents[self._prodConsP]["creator"], + [thedataFile,self._calcFilenames("modules")[0]]) + with open(fulldataFile,'w') as moth: + moth.write(JSONFormat(theDict)) + def _saveData(self,name,base,jsonfiles): + jsonfiles = " ".join(["%s%s"%(self._helperDir,x)for x in jsonfiles]) + temp={} + temp["data-base"] = base + temp["data-files"] = jsonfiles + self._data[name] = temp + + # Create objs and print out .js files for + # each type of items we have. + def _createObjects(self): + base = "obj= Object.create(new %s(%s));" + format=""" + function %s(%s){ + var obj; + %s + return obj; } - event.stopPropagation(); - }); - // Needed to stop the propagation of event when it should not be expanded. - $(document).on('click', '.param',function(event){ - if($(this).find('ul').length >0){ - $(this).find('ul').toggle(); - } - event.stopPropagation(); - }); - /* - Removes children from expanded paths or modules. - */ - $(document).on('click', '.path.expanded, .module.expanded',function(event){ - removeChildren(this,event); - }); - - // Toggles class names. - $(document).on('click','.expand, .expanded', function(event){ - toggleExpand(this, event); - }); - /* - Does matching for top level list elements. - Returns number of matches. - */ - function topLevelMatch(list, reg, haveLIs){ - var numFound =0; - for(var p=0; p < list.length; p++){ - if(haveLIs){ - var li = $(list[p]); - var item = li.attr('data-name'); - } - else{ - var item = list[p]; - var li= $('li[name='+item+']'); - } - if(num=item.match(reg)){ - numFound +=num.length; - li.html(li.html().replace(reg, "$1")); - } - else{ - li.hide(); + """ + name = "data" + for pname,x in self._parents.iteritems(): + simple = base%(pname,name) + filename,fullfilename= x["cfile"] + self._allJSFiles.append(filename) + if(x["simple"]): + paramName="modules" + with open(fullfilename, 'w') as setUp: + setUp.write(format%(x["creator"],paramName,self._load( + name,paramName,simple))) + continue + secName = "topL" + paramName=["modules","topLevel"] + complexOne = base%(pname,"%s,%s"%(name, secName)) + with open(fullfilename, 'w') as setUp: + setUp.write(format%(x["creator"],", ".join(paramName), + self._load(name,paramName[0], + self._load(secName, paramName[1],complexOne)))) + + # return the .js code for loading json files in a string + def _load(self,name,param,inner): + return""" + loadJSON(%s).done(function(%s){\n%s\n}); + """%(param,name,inner) + + # The parent class for non SequenceTypes + def _writeDictParent(self, typeName): + exVar ='this.%(key)sKey= "%(key)s";' + exFunc =""" +/** + * Gives the %(key)s + * @param {String} the key to the dictionary. + * @returns {String || Integer} result from dictionary if found else 0. + */ +%(name)s.prototype.get%(key)s = function(key){ + return this.getFeature(key,this.%(key)sKey); +} + """ + search = """%(name)s.prototype.search%(key)s = function(reg,term,replce){ + return this.generalSearch(reg,term,replce,this.%(key)sKey); +} """ + extra= """ + /** + /** +* Uses the list of parents names to go further into +* the lists in the dictionry, and give the last parents children. +* @param {Array} the names of parents to look through. +* First parent should be a key to the dictionary. +* @param {Integer} the index where the elusive parameter is. Needed incase +* we have a list with muultiple parameters of the same name. +* +* @returns {Array} the resulting children from the last parent. +*/ +DictParent.prototype.getInnerParams = function(parents, index){ + var currentList = this.data[parents[0]][this.%(key)sKey]; + var targetList=[] + var siblingsOfTarget=[] + for(var i=1; i < parents.length;i++){ + for(var p=0; p < currentList.length;p++){ + if(currentList[p][0]==parents[i]){ + targetList = currentList[p] + siblingsOfTarget=currentList + var found = targetList[1]; + break; } } - return numFound; + currentList = found; } - /* - Removes highlights from selector, removes also children - if rmChildren == true. - */ - function reset(selector, e, rmChildren){ - var rm = new RegExp('|', 'g'); - $(selector).each(function(i){ - var html = $(this).html(); - if(html.match(rm)){ - $(this).html(html.replace(rm, '')); - } - else{ - $(this).show(); - } - if(rmChildren)if(removeChildren(this, e))toggleExpand(this, e);}); - } - /* - Removes children from parent. - */ - function removeChildren(parent, event){ - var c = $(parent).children('ul'); - if(c.length >0){ - $(c).remove(); - event.stopPropagation(); - return true; + if(p != index)targetList=siblingsOfTarget[index] + return targetList; +} + """ + functs="" + variables ="" + name = self._dictP + data = self._parents[name] + fileName, fullfileName= data["pfile"] + for feature in dictFeatures: + d = {"key": feature, "name": name} + variables +=exVar%d + functs +=exFunc%d + if(feature == "Parameters"): + functs +=extra%d + else: + functs += search%d + self._allJSFiles.append(fileName) + with open(fullfileName, 'w') as parent: + parent.write(""" +/* + Base Object for dictionaries. + To use, create a dictParent obj, + then use Object.create to create a new obj + then you can change some variables/add functions + and have the inherited functions. +*/ +function %(name)s(data){ + this.data=data; + %(theVars)s +} +/** + * Finds the desired feature from a dictionary. +* @param {String} the key to the dictionary. +* @param {String} the feature we want from the dictionary. +* @returns {String || Integer} result from dictionary if found else 0. +*/ +%(name)s.prototype.getFeature = function(key, feature){ + var temp = this.data[key]; + if(temp) return temp[feature]; + else return 0; +} +DictParent.prototype.getData = function(){ + return [this.data]; +} +%(getterFunctions)s + +/** + * Gives the keys from desired dictionary. +* @returns {Array} all keys from the dictionary. +*/ +%(name)s.prototype.getKeys = function(){ + return Object.keys(this.data); +} +%(name)s.prototype.generalSearch = function(reg,term,repl,feature, d){ + d = d || this.data; + var matches ={} + for (var key in d){ + var x= d[key][feature] + if(x.indexOf(term)>-1){ + matches[key] = x.replace(reg,repl) } - return false; } - /* - Helper function toggles classes. - */ - function toggleExpand(me,event){ - $(me).toggleClass("expanded expand"); - event.stopPropagation(); - } -}); - """) - jsFile.close() - - def css(self,thecss): - cssFile= open(thecss, 'w') - cssFile.write( """ + return matches; +} -em { - background-color: rgb(255,255,0); - font-style: normal; +/** + * Gives the generic type for a given type. + * @param {String} type + * @returns {String} the generic type + */ +function getGenericType(type){ + return %(gen)s[type]; } -.module{ - color: #0000CC + """%{"theVars":variables,"getterFunctions":functs, + "gen": typeName, "name":name}) + + # Write out the class for SequenceTypes + def _writeModSeqParent(self): + f = """ +/** + * Gives the direct children + * @param {String} a path name + * @returns {Array} list of names of the the children. + */ +%(name)s.prototype.getModules = function(name){ + return this.topLevelData[name][this.ParametersKey]; } -.param { - color: #9999CC; - cursor:default; +%(name)s.prototype.getTopFile = function(key){ + return this.topLevelData[key][this.FileKey]; } -.paramInner { - color: #9999FF; - cursor:default; +%(name)s.prototype.getData = function(){ + return [this.topLevelData, this.data]; } -.value{ - color:#0000FF; +%(name)s.prototype.searchType = function(reg,term,replce){ + return this.generalSearch(reg,term,replce,this.TypeKey, this.topLevelData); } -.type{ - color: #00CCFF; +%(name)s.prototype.searchFile = function(reg,term,replce){ + return this.generalSearch(reg,term,replce,this.FileKey, this.topLevelData); } +""" + self._complexBase(self._modSeqP, f) -ul { - list-style-type:none; - padding-left:0.6em; + # Write out the class for producers and consumers. + def _writeProdConsum(self): + f= """ +/** + * Gives the direct children + * @param {String} a path name + * @returns {Array} list of names of the the children. + */ +%(name)s.prototype.getModules = function(name){ + return this.topLevelData[name]; +} +%(name)s.prototype.getTopFile = function(key){ + return this.getFile(key); } - .expand:before{ - content:'›'; - float: left; - margin-right: 10px; +%(name)s.prototype.getData = function(){ + return [this.topLevelData, this.data]; } - .expanded:before, .param:before{ - content:'ˇ'; - float: left; - margin-right: 10px; +// Producer and consumer have different structure to rest. +// Dont have file and type with them.. +// to get file and type we need to take each name, +//look up the moduledata and find matches. +%(name)s.prototype.generalSearch = function(reg,term,repl, feature){ + var matches ={} + for (var key in this.topLevelData){ + var x = this.data[key][feature] + if(x.indexOf(term)>-1){ + matches[key] = x.replace(reg,repl) + } + } + return matches; } -.expand, .expanded, .param{ - cursor:pointer; +%(name)s.prototype.typeSearch = function(reg,term,replce){ + return this.generalSearch(reg,term,replce,this.TypeKey); } - - """) - cssFile.close() +%(name)s.prototype.fileSearch = function(reg,term,replce){ + return this.generalSearch(reg,term,replce,this.FileKey); +} + """ + self._complexBase(self._prodConsP, f) -""" - Do Module Objects e.g. producers etc -""" + def _complexBase(self,parentName, extra): + name = parentName + data = self._parents[name] + fileName, fullfilename= data["pfile"] + self._allJSFiles.append(fileName) + all = """ +/* + Base object for thing of the type: + It also inherits from DictParent. +*/ +function %(name)s(data,topLevel, nameList,indexList){ + this.data = data; + this.topLevelData=topLevel;// e.g. pathNames to module names + this.fixedNameList = nameList; // e.g.names of paths +} +%(name)s.prototype = new %(dict)s(this.data); -def doModules(modObj, dataFile, seq, seqs, currentName, innerSeq): - name = modObj.label_() - typ = re.sub("<|>|'", "", str(type(modObj))).split(".")[-1] - if(seq==0):allMods.append(name) - elif(not innerSeq and currentName not in allMods): - allMods.append(currentName) - if(name not in modsNames): - theList = do(modObj.parameters_(), []) - modsNames.append(name) - newModsNames.append(name) - filename = modObj._filename.split("/")[-1] - theS ="" - if(len(modsNames) > 1): theS="," - theS+="%s:%s" - d = getParamSeqDict(theList, typ, filename) - dataFile.write(theS%(name, d)) - if(seq >0): - seqs[currentName].append(name) - +%(name)s.prototype.getKeys = function(){ + return Object.keys(this.topLevelData) +} + """+ extra + with open(fullfilename, 'w') as parent: + parent.write(all%{"name": name, "dict": self._dictP}) + +# Helper function which gets parameter details. +def getParameters(parameters): + all =[] + if(not parameters): + return [] + for (name,valType) in parameters.iteritems(): + theT= (valType.configTypeName() if( + hasattr(valType,"configTypeName")) else "").split(" ",1)[-1] + temp = re.sub("<|>|'", "", str(type(valType))) + generic, spec = temp.split(".")[-2:] + doTypes(spec,generic) + theList=[name] + if(isinstance(valType,cms._Parameterizable)): + theList.append(getParameters(valType.parameters_())) + elif(isinstance(valType,cms._ValidatingListBase)): + theList.append(listBase(valType)) + else: + if(isinstance(valType,cms._SimpleParameterTypeBase)): + value = valType.configValue() + else: + try: + value = valType.pythonValue() + except: + value = valType + theList.append(value) + if(theT != "double" and theT !="int" and type(valType)!= str): + if(not valType.isTracked()): + theList.append("untracked") + theList.append(theT) + all.append(theList) + return all + +def listBase(VList): + # we have a list of things.. + #loop around the list get parameters of inners. + #Since ValidatingListBases "*usually* have the same types + #throughout, just test first --is this a rule? + # Find out and if needed move these ifs to the loop. + if(not VList):return "" + first = VList[0] + if(isinstance(first,cms._Parameterizable)or + isinstance(first,cms._ValidatingListBase)): + anotherVList=False + if(isinstance(first,cms._ValidatingListBase)): + anotherVList=True + outerList=[] + for member in VList: + if(member.hasLabel_()): + name = member.label() + else: + name = member.configTypeName() + innerList=[name] + if(not anotherVList): + innerList.append(getParameters(member.parameters_())) + else: + innerList.append(listBase(member)) + temp = re.sub("<|>|'", "", str(type(member))) + generic, spec = temp.split(".")[-2:] + doTypes(spec,generic) + innerList.append(spec) + outerList.append(innerList) + return outerList + elif(isinstance(first,cms._SimpleParameterTypeBase)): + return ",".join(i.configValue() for i in VList) + elif(isinstance(first,cms._ParameterTypeBase)): + return ",".join(i.pythonValue() for i in VList) else: - oldMods.append(name) + #Most things should at least be _ParameterTypeBase, adding this jic + try: + outcome = ",".join(str(i) for i in VList) + return outcome + except: + return "Unknown types" -def format(s, **kwds): - return s % kwds +dictFeatures=["Parameters", "Type", "File", "oType"] +# Used to enforce dictionary in datafiles. +def getParamSeqDict(params, fil, typ, oType): + d={} + d[dictFeatures[0]] = params + d[dictFeatures[1]] = typ + d[dictFeatures[2]] = fil + d[dictFeatures[3]] = oType + return d + class visitor: - def __init__(self, df): - self.df = df - self.seq = 0 - self.currentName ="" - self.oldNames =[] - self.done =[] - self.seqs={} - self.innerSeq = False + def __init__(self, df, cfg): + self._df = df + self._underPath = [] # direct children of paths + #(includes children of modules) + self._modulesToPaths={} # map from modules to index of path - + self._seq = 0 + self._pathLength=0 + self._currentName ="" + self._oldNames =[] + self._done =[] + self._seqs={} + self._typeNumbers = {} + self._innerSeq = False + self._reg= re.compile("<|>|'") + self.config = cfg + + def _finalExit(self): + self._pathLength+=1 + temp = self._underPath + self._underPath =[] + return temp + + # Only keep in if we manage to move doModules into this class + def _getType(self,val): + return re.sub(self._reg, "", str(type(val))).split(".")[-2:] + + """ + Do Module Objects e.g. producers etc + """ + def _doModules(self,modObj, dataFile, seq, seqs, currentName, innerSeq): + #name = modObj.label_() + name = self.config.label(modObj) + # If this is not an inner sequence then we add so it can go to paths + if(seq==0): + self._underPath.append(name) + else: + seqs[currentName].append([name]) + # If we've seen this name before, no need to compute values again. + # we need to put this mod/seq name under the path name in the dict + if(name not in self._modulesToPaths.keys()): + self._modulesToPaths[name] =[self._pathLength] + filename = modObj._filename.split("/")[-1] + generic,specific = self._getType(modObj) + doTypes(specific,generic) + d = getParamSeqDict(getParameters(modObj.parameters_()), + filename, specific, modObj.type_()) + theS='"%s":%s' + if(len(self._modulesToPaths.keys()) > 1): theS=","+theS + dataFile.write(theS%(name, JSONFormat(d))) + else: + #oldMods.append(name) + self._modulesToPaths[name].append(self._pathLength) def enter(self, value): if(isinstance(value,cms._Module)): - doModules(value, self.df, self.seq, - self.seqs, self.currentName, self.innerSeq) - if(isinstance(value,cms.Sequence)): - if(len(self.currentName) >0):self.oldNames.insert(0, self.currentName) - if(self.seq >0): - # this is an inner sequence - self.innerSeq = True; - self.seqs[self.currentName].append(value.label()) - self.currentName = value.label() - self.seqs[self.currentName] = [] - self.seq +=1 + self._doModules(value, self._df, self._seq, + self._seqs, self._currentName, self._innerSeq) + elif(isinstance(value,cms._Sequenceable)): + generic,specific = self._getType(value) + doTypes(specific, generic) + if(isinstance(value, cms._ModuleSequenceType)): + if(len(self._currentName) >0): + self._oldNames.insert(0, self._currentName) + name = self.config.label(value) + #name = value.label_() + if(self._seq >0): + # this is an inner sequence + self._innerSeq = True; + self._seqs[self._currentName].append([name]) + else: + self._underPath.append(name) + self._seqs[name] = [] + self._currentName = name + self._seq +=1 + else: + # just sequenceable.. + name = value.__str__() + if(self._currentName): + self._seqs[self._currentName].append([name, specific]) + else: + self._underPath.append(value.__str__()) + if(name not in self._done): + d = getParamSeqDict([], "", specific, "") + self._df.write(',"%s":%s'%(name,JSONFormat(d))) + self._done.append(name) def leave(self, value): - if(isinstance(value,cms.Sequence)): - name = value.label() - if(name in self.oldNames):self.oldNames.remove(name) - if(self.currentName == name and len(self.oldNames) >0): - self.currentName = self.oldNames.pop(0) - if(name not in self.done): - d = getParamSeqDict(self.seqs.pop(name), - re.sub("<|>|'", "", str(type(value))).split(".")[-1], "") - self.df.write(",%s:%s"%(name,d)) - self.done.append(name) - self.seq -=1 - if(self.seq==0): self.innerSeq = False; - -# Used to enforce dictionary in datfile have same format. -def getParamSeqDict(params, typ, fil): - d={} - d["parameters"] = params - d["type"] = typ - d["file"] =fil - return d + if(isinstance(value,cms._Module)): + return + elif(isinstance(value,cms._Sequenceable)): + # now need to determine difference between + #ones which have lists and ones which dont + if(isinstance(value, cms._ModuleSequenceType)): + #name = value.label() + name = self.config.label(value) + if(name in self._oldNames):self._oldNames.remove(name) + if(self._currentName == name): + if(self._oldNames): + self._currentName = self._oldNames.pop(0) + else: + self._currentName="" + if(name not in self._done): + generic,specific = self._getType(value) + d = getParamSeqDict(self._seqs.pop(name), "", specific, "") + self._df.write(',"%s":%s'%(name,JSONFormat(d))) + self._done.append(name) + self._seq -=1 + if(self._seq==0): self._innerSeq = False; + +class html: + def __init__(self,name,js,items,theDir, helperDir, pN,pFN): + jqName = "%scfgJS.js"%(theDir) + jqLocal = "%scfgJS.js"%(helperDir) + css = "%sstyle.css"%(theDir) + cssL = "%sstyle.css"%(helperDir) + js.insert(0,jqLocal) + self._jqueryFile(jqName, pN,pFN) + self._printHtml(name,self._scripts(js),self._css(css, cssL), + self._items(items), self._searchitems(items)) + + def _scripts(self, js): + x = """ +""" + return "\n".join([x%(i) for i in js]) + + def _items(self, items): + l= """ +""" + s= [l%({"n":x,"f":y["data-files"],"d":y["data-base"]}) + for x,y in items.iteritems()] + return " ".join(s) + + def _searchitems(self,items): + b = """ """ + return "\n ".join([b%({"name": x, "d":y["data-base"]}) + for x,y in items.iteritems()]) + + def _printHtml(self,name,scrip,css,items, search): + with open(name,'w') as htmlFile: + htmlFile.write("""\n\n + + cfg-browser\n \n %(s)s\n %(css)s\n \n +
    + \n \n
    + Normal Mode +
    hide
    \n
    + \n


    \n
    +
    Pick\n
    +
    \n \n

    + +
    \n
    \n
    +
    Pick\n
    +
    + + \n +

    + + + Don't show highlights\n
    +
    \n
    \n
    \n
    + + Show file names\n

    \n +
    \n
    \n
    +
    \n
    \n
    +
    \n Back to Top +

    \n Hide All\n

    +
    \n \n\n"""%{ + "s":scrip,"css":css,"items":items, "search":search}) + + def _css(self, css, cssLocal): + with open(css, 'w') as cssfile: + cssfile.write(""" +*{\n font-family:"Lucida Grande", Tahoma, Arial, Verdana, sans-serif;\n} +.topBox{\n opacity:0.9;\n background-color:#dfdfdf;\n}\n.topSpec{ + position:fixed;\n top:0;\n left:0;\n width:100%;\n height:2.5em; + border-radius:.9em;\n}\n.hideTopBox, .showTopBox{\n position:absolute; + top:2.5em;\n right:2%;\n width:auto;\n height:auto;\n padding: 0.2em; + font-weight:bold;\n cursor:pointer;\n border-radius:.3em;\n}\n.negative{ + position:absolute;\n right:0;\n text-decoration:none; + font-weight:bold;\n color:#565656;\n}\n#mode{\n position:absolute; + right:50%; \n color:#808080;\n font-size:12pt;\n}\n#editMode,#normalMode{ + position:absolute;\n left:.3em;\n top:.5em;\n}\n#save{ + position:absolute;\n top:.5em;\n}\n.helpLinks{\n position:absolute; + right:1.3em;\n width:6.2em;\n text-align:right;\n} +/* divs for the Pick and Search boxes.*/\n.outerBox{\n width:100%; + overflow:hidden;\n}\n.boxTitle{\n float:left;\n margin-left:.6em; + color:#A9A9A9;\n}\n.dottedBorder{\n width:25em;\n height:4em; + border:.1em dashed #A9A9A9;\n padding:.6em;\n}\n/* -- */ +/* Right scroll box. */\n.rightScroll{\n position:fixed;\n bottom:50%; + right:0; \n width:6.2em;\n text-align:right;\n border:.1em solid #A9A9A9; + opacity:0.4;\n background-color:#F0FFF0;\n}\n#hide{\n cursor:default; + opacity:0.2;\n}\nli{\n padding-left:.8em;\n}\nul{\n list-style-type:none; + padding-left:.1em;\n}\n/* Icons before list items. */\n.expand:before{ + content:'›';\n}\n.expanded:before{\n content:'ˇ';\n} +.expand:before,.expanded:before{\n float:left;\n margin-right:.6em;\n} +.expand,.expanded{\n cursor:pointer;\n}\n/* colours of each. */ +.Path,.EndPath{\n color:#192B33;\n}\n.Modules{ \n color:#800080;\n} +.SequenceTypes{\n color:#0191C8\n}\n.paramInner,.Types{\n color:#4B4B81;\n} +.param{\n color:#9999CC;\n margin-left:.8em;\n cursor:default; \n}\n.value{ + color:#0000FF;\n}\n.type{\n color:#00CCFF;\n} +/* Header for what's showing */\n#current{\n color:#808080;\n font-size:12pt; + text-decoration:underline; \n}\n/* help settings */\n#help{ + position:absolute;\n display:none;\n background:#ccc;\n border:.1em solid; + width:19em;\n right:15em;\n top:1.2em;\n}\nh5{\n font-style:normal; + text-decoration:underline; \n margin:0;\n font-size:9pt;\n}\nh6{ + margin:0;\n color:#666666;\n}\n#attachParams{\n color:#192B33;\n}\nem{ + color:#FFA500;\n}\n.cellEdit{\n border:.1em dotted #A9A9A9;\n cursor: text; +}\n""") + return """"""%(cssLocal) + + def _jqueryFile(self,name, pN,pFN): + with open(name, 'w')as jq: + jq.write(""" +\n$(document).ready(function(){ \n//Object used to get all details +var processName="%s";\nvar processFileName ="%s"; +var CURRENT_OBJ;\nvar searchShowing= false;\nvar showParams = false +var alreadyShowing = false\nvar topClass = "Top"\nvar searching = false +var expandDisable = false;\nvar hideVisible=false //nothing is expanded. +// ---\n/*\n Functions used to abstract away name of function calls + on the object (CURRENT_OBJ). + (i.e. so function names can easily be changed.)\n*/ +function baseParams(inputs){\n return CURRENT_OBJ.getParameters(inputs);\n} +function baseInnerParams(inputs, index){ + return CURRENT_OBJ.getInnerParams(inputs, index);\n} +function baseType(inputs){\n return CURRENT_OBJ.getType(inputs);\n} +function baseFile(inputs){\n return CURRENT_OBJ.getFile(inputs);\n} +function baseTopFile(inputs){\n return CURRENT_OBJ.getTopFile(inputs);\n} +// --- Show some inital data operations ---\n/*\n Show something new!\n*/ +$(document).on('click', '#docSubmit', function(e){ + var $elem = $('#showType :selected') + //get the function we want and the lists\n setCURRENT_OBJ($elem)\n + addData($elem.attr("value"), CURRENT_OBJ.getKeys());\n searchShowing= false; +});\n/*\n Add data to the html.\n*/ +function addData(docType, data, dataNames){ + $("#editMode").removeAttr("disabled"); \n var dataNames = dataNames || data; + if(alreadyShowing){\n //need to click cancel if its active. + goNormal($("#normalMode"));\n if(!searching)$("#searchCount").html("") + invisibleHide()\n paramOptions(false) + $(document.getElementsByTagName('body')).children('ul').remove();\n } + $("#current").html(docType)\n var gen = getGenericType(docType) + var ty = docType\n if(gen != undefined){\n var gL = gen.toLowerCase() + if(gL=="modules"||gL=="types") var ty= gen;\n } + var $LI = $(document.createElement('li') + ).addClass("expand").addClass(ty).addClass(topClass); + docType= docType.toLowerCase()\n var showTypes = false\n showParams = true + switch(docType){\n case "producer":\n case "consumer": + showParams = false\n paramOptions(true) + $LI.addClass("Modules")\n showTypes = true\n break; + case "modules":\n $LI.addClass("Modules")\n showTypes = true + //showParams = true\n break;\n } + var $UL = addTopData(data,$LI,showTypes,dataNames)\n alreadyShowing = true; + $UL.appendTo('#attachParams');\n}\n/* + Used to add the top level data to html.\n*/ +function addTopData(data,$LI,types,dataName){ + var dataName = dataName || data; + var $UL = $(document.createElement('ul'));\n var doNormalFile = false; + var files = document.getElementById("ShowFiles").checked\n if(files){ + try{\n baseTopFile(dataName[0])\n }\n catch(e){ + doNormalFile = true;\n }\n }\n for(var i=0; i < data.length;i++){ + var n = dataName[i]\n var t = data[i]; + if(types)t += " ("+baseType(n)+")"\n if(files){ + if(doNormalFile)var file = baseFile(n) + else var file = baseTopFile(n)\n t += " ("+file+")"} + $UL.append($LI.clone().attr("data-name",n).html(t));\n }\n return $UL;\n} +// --- end of inital showing data operations ---\n +// --- search operations ---\n +//$(document).on('click', "[name='searchTerm1']", function(e){ +//$(document).on('click', "#searchType option", function(e){ +$(document).on('click', '#searchType', function(e){\n $("#addSearch").empty() + var tname= $(this).text().toLowerCase();\n var sel= jQuery('', {\n type:"submit", + value:"Save",\n id:"save"\n }).css({\n left:l\n})); + $(this).attr("id", "normalMode")\n makeEditable(searchShowing); + searchShowing = false;\n});\n/* + Adds in div elements to make cells editable.\n*/ +function makeEditable(rmSearch){\n // add editable div to everything showing. + var todo = jQuery.makeArray($(".Top"));\n while(todo.length){ + var e = $(todo.pop())\n if(rmSearch) + e.html(e.html().replace(/(|<\/em>)/g, "")) + // we have the item.. lets get children + var kids = jQuery.makeArray(e.children()); + // add divs to all children.\n while(kids.length){ + var k = $(kids.pop())\n var tag = k.prop("tagName")\n + if(tag == "SPAN"){\n if(k.prop("class")!="type") + k.html('
    '+k.html()+'
    ') + continue\n }\n if(tag =="LI"){ + // add the div but dont get children + $(k.contents()[0]).wrap('
    '); + }\n // check if have any children + var moreKids = jQuery.makeArray(k.children()); + if(moreKids.length){\n kids = kids.concat(moreKids)\n } + }\n // now do current one + $(e.contents()[0]).wrap('
    ');\n } +}\n/*\n A cell which is editable has been clicked.\n*/ +$(document).on('click', '.cellEdit', function(e){ + // we're in edit so things have a div parent over the text. + // so get parent to get the thing we want. + var $itemChanged = $(this).parent() + // now go up until we find greatest parent(item with class==topClass) + var classes = $itemChanged.attr("class")\n var $parent = $itemChanged + while(classes.indexOf(topClass)==-1){\n $parent = $parent.parent(); + classes = $parent.attr("class") || "";\n } + var parentName = $parent.attr("data-name"); + // doesnt matter if parent and child are the same. + var parents = Object.keys(parChildNames) + if(parents.indexOf(parentName)>-1){\n // already been edited. + var kids = parChildNames[parentName] + if(kids.indexOf($itemChanged.attr("data-name"))==-1){ + kids.push($itemChanged)\n }\n }\n else{ + parChildNames[parentName]=[$itemChanged]\n }\n $potential.push($parent) +});\n//--- end of edit operations ---\n// --- start of save operations ---\n/* + Save any changes.\n*/\n$(document).on('click', '#save', function(e){ + var allData = CURRENT_OBJ.getData();\n var oldData = allData[0] + goNormal($("#normalMode"));\n if(allData.length >1){ + var top = allData[0];\n var rest = allData[1]; + var changed = save(deepCopy(top),deepCopy(rest))\n }\n else{ + var changed = save(deepCopy(allData[0]));\n } + if(Object.keys(changed).length ==0){ + window.alert("Nothing was changed.");\n $potential=[] + parChildNames={}\n return \n } + //$('#svg_export_form > input[name=svg]').val("jhgjhg"); + changed["processName"]= processName + changed["processFileName"]= processFileName\n $("#posty").empty() + var form = jQuery('
    ', {\n id:"edited_write",\n method:"POST", + async: "false",\n enctype: "multipart/form-data", + style:"display:none;visibility:hidden",\n })\n jQuery('', { + type:"hidden",\n name:"changed",\n value:JSON.stringify(changed), + }).appendTo(form)\n form.appendTo("#posty")\n $('#edited_write').submit(); + $potential=[]\n parChildNames={}\n});\n/* + Go to normal viewing mode. Discard any changes.\n*/ +$(document).on('click', '#normalMode', function(e){ + //remove all cell edit Divs\n goNormal($(this));\n //$potential =[] + //parChildNames={}\n});\n/*\n Couldn't find built-in deep clone or copy.\n*/ +function deepCopy(obj){\n if(obj instanceof Array){\n var copy=[] + obj.forEach(function(x,i,a){copy[i]= deepCopy(x)})\n return copy\n } + else if(obj instanceof Object){\n var copy ={}\n for (key in obj){ + copy[key] = deepCopy(obj[key])\n }\n return copy\n }\n return obj +}\n\n/*\n Returns a dict of everything that has changed.\n*/ +function save(data, restData){\n var allChanged={}\n var done=[] + for(var i in $potential){\n var parent = $potential[i]; + // we have the parent. + var oldParentName = $(parent).attr("data-name"); + //bit iffy, can have same parent name multiple times? todo + if(done.indexOf(oldParentName)>-1) continue\n done.push(oldParentName) + if(typeof restData =='undefined'){ + var allDict = deepCopy(data[oldParentName]) + var allOldData = allDict["Parameters"] + var childChanged = parChildNames[oldParentName] + var oldToNew= chil(childChanged,parent, true) + if(oldToNew.length ==0) continue + var newpar = blah(oldToNew, oldParentName, allOldData, parent, false) + tempDict = allDict\n tempDict["Parameters"] = allOldData + allChanged[newpar] = tempDict\n if(oldToNew.length>0){ + window.alert("Something went wrong, I did not find all changes."); + }\n }\n else{ + // we have one data for the parents and one for rest + var allDict = deepCopy(data[oldParentName]) + var allKids = allDict["Parameters"]\n var tem ={} + var childChanged = parChildNames[oldParentName]; + var oldToNew = chil(childChanged,parent, false); + //if(Object.keys(oldToNew).length ==0) continue + if(oldToNew.length ==0) continue\n for (var y in allKids){ + var n = allKids[y]\n var allOld2 = deepCopy(restData[n]) + var allOldData = allOld2["Parameters"] + // blah chanhes allOldData + var newpar = blah(oldToNew, n, allOldData, parent, true) + allOld2["Parameters"]= allOldData\n tem[newpar] = allOld2 + }\n var newParentName = $(parent).contents()[0].nodeValue + //allChanged[newParentName]= tem\n tempDict = allDict + tempDict["Parameters"] = tem\n allChanged[newParentName] = tempDict + continue\n }\n }\n return allChanged\n}\n/* + These three functions are used for getting data from + a structure such as [{},{},{}]\n*/\nfunction getValue(list, key){\n var re=[] + for(x in list){\n di = list[x]\n k = Object.keys(di)[0] + if(k==key)re.push(di[k])\n }\n return re\n}\nfunction getKeys(list){ + var keys = []\n for (x in list)\n keys.push(Object.keys(list[x])[0]) + return keys\n}\nfunction deleteValue(list, k,d){\n var inde =-1 + var found = false\n for(var x in list){\n var di = list[x] + var key = Object.keys(di)[0]\n if(key==k && di[key]==d){ + found = true\n inde = x\n break\n }\n } + if(found)list.splice(inde,1)\n}\n/* + allOldData will be changed with the new data.\n*/ +function blah(oldToNew, oldParentName, allOldData, parent){ + var newpar = oldParentName\n var keys = getKeys(oldToNew) + if(keys.indexOf(oldParentName)>-1){\n // parent is in + var tDatas = getValue(oldToNew,oldParentName); + for (var x in tDatas){\n var tData = tDatas[x] + if(tData["i"]==0 && tData["p"].length ==0){ + var newpar = tData["new"];\n // this isnt finding tData + deleteValue(oldToNew, oldParentName,tData);\n }\n }\n } + // okay so here we have everything for this parent. + // now need to loop through the old data and changed for new. + if(oldToNew.length >0){ + loopData(allOldData,oldToNew,[oldParentName], [0]);\n } + return newpar\n}\n//need to remember that current format is +//[name, parameters,type,optionalType]\n/*\n Loop around the data, \n*/ +function loopData(thelist, items, parents, pIndex){\n for(var x in thelist){ + var y = thelist[x]\n if(y instanceof Array){ + // okay if array, we have full line + if(typeof y[0] == "string" && y[1] instanceof Array){ + // this is what we want.\n var theName = y[0] + var rest = y[1]\n var types = [y[2]]\n if(y.length == 4) + types.push(y[3])\n // okay, name of this is theName == parent + // the index of this is x\n parents.unshift(theName) + pIndex.unshift(x)\n loopData(rest, items, parents, pIndex); + parents.shift()\n pIndex.shift() + rightOne(thelist,x,theName,items,parents,pIndex) + for(var index in types){\n var item = types[index] + rightOne(thelist,x,item,items,parents,pIndex)\n } + continue\n } + if(y[0] instanceof Array && y[1] instanceof Array){ + // y1 is a parameter\n // y2 is a parameter + for(var e in y){\n loopData(y[e],items,parents,pIndex); + }\n continue;\n }\n // we are here, + //so we have something that does not have parameters in a list + var theName = y[0]\n for(var index in y){\n if(index >0){ + parents.unshift(theName) \n pIndex.unshift(x)\n } + var item = y[index] + rightOne(thelist,x,item,items,parents,pIndex)\n if(index >0){ + parents.shift()\n pIndex.shift()\n }\n } + continue;\n }\n else { + rightOne(thelist,x,y,items,parents,pIndex)\n }\n }\n}\n/* + Helper function. We have a match, now change old values for new values.\n*/ +function rightOne(thelist,x,y,items,parents,pIndex){ + if(getKeys(items).indexOf(y)>-1){ + // we know that we have a match, but are indexes the same? + // index will be in the same list so we can use x + var dis = getValue(items, y)\n for (inde in dis){ + var di= dis[inde]\n if(x == di["i"]){ + if(arrayCompare(parents, pIndex,di["p"],di["pIndex"] )){ + //okay we can be sure we are changing the right thing. + if(thelist[x] instanceof Array){ + for(var ind in thelist[x]){\n var z = thelist[x][ind] + if(y == z){\n thelist[x][ind] = di["new"] + break;\n } \n }\n } + else{\n thelist[x] = di["new"]\n } + deleteValue(items,y,di)\n }\n }\n }\n }\n}\n/* + Returns true if arrays a1 is identical to a2 and + a1Index is identical to a2Index.\n*/ +function arrayCompare(a1, a1Index, a2, a2Index) { + if (a1.length != a2.length)return false; + for (var i = 0; i < a1.length; i++) { + if (a1[i] != a2[i] || a1Index[i] != a2Index[i]) { + return false;\n }\n }\n return true;\n}\n/* + Take in the children that might have been changed. + If something has been changed, adds to a dictionary + dictionary format is [data-name]={ + "new": newvalue, "i":data-index, "p":[parentNames], + "pIndex": [indicies of parents]} + TODO, need a new format, what if children have + the same data-name and both are changed?\n*/ +function chil (childChanged, parent, addParent){\n var oldToNew=[] + for (var x in childChanged){\n var child = childChanged[x] + // we need to check if the child has been changed. + var oldval = child.attr("data-name"); + var isSpan = child.prop("tagName") == "SPAN"\n var newval = isSpan ? + child.contents().text(): child.contents()[0].nodeValue; + //remove any enclosing brackets + newval = newval.trim().replace(/\(.*\)$/, ""); + oldval = oldval.trim().replace(/\(.*\)$/, ""); + if(oldval==newval)continue\n else{ + //child has been changed.\n //we want to keep 4 pieces of data. + //1. old name, new name\n //2. data-index + //3. list of direct parents.\n //4. indexes of all parents. + var inner ={}\n inner["new"] = newval; + //depends if it was a span or not. Span means we use parents. + inner["i"]= (isSpan? child.parent().attr("data-index"): + child.attr("data-index")) || 0\n var allP = child.parents() + var pNames =[]\n var pIndex =[] + for(var y=0; y < allP.length; y++){\n var p = $(allP[y]) + var tag = p.prop("tagName") + if(p.attr("data-name") == parent.attr("data-name")){ + if(addParent){\n pNames.push(parent.attr("data-name")) + pIndex.push(parent.attr("data-index") || 0);\n } + break;\n }\n else if(tag == "LI"){ + pNames.push(p.attr("data-name")); + pIndex.push(p.attr("data-index") || 0);\n }\n } + inner["p"] = pNames\n inner["pIndex"] = pIndex\n var t={} + t[oldval]= inner\n oldToNew.push(t)\n } + } // end of childchanged loop\n return oldToNew\n} +// --- end of save operations --- +// --- Expand and show more data operations ---\n/* + Used when in edit mode to stop any items being added to the webpage. + More items added after edit mode- they wont be editable, and when you + click to edit something it loads its children.\n*/ +$(document).on('click','.expand, .expanded', function(event){ + if(expandDisable){\n event.stopImmediatePropagation();\n }\n});\n/* + Retrieves and expands elements whose objects have multiple lists + (i.e. onese who's data-base !=simpleData)\n*/ +$(document).on('click', '.Consumer.expand,.Producer.expand,' ++'.Path.expand,.EndPath.expand ',function(event){ + var allModules = CURRENT_OBJ.getModules($(this).attr('data-name')); + var UL = addParams(this,allModules)\n $(this).append(UL); + event.stopPropagation();\n});\n/*\n Adds parameters onto objects.\n*/ +$(document).on('click','.Modules.expand,.SequenceTypes,.Types.expand' +, function(event){\n if(showParams){\n addParams(this);\n } + event.stopPropagation();\n});\n/*\n Hides/Shows children from class param. +*/ \n$(document).on('click', '.paramInner.expand, .paramInner.expanded', + function(event){\n if($(this).children('ul').length ==0){ + // find parents\n var parents = findParents(this) + var result = baseInnerParams(parents,parseInt( + $(this).attr("data-index")) )[1] + addParams(this, result);\n }\n else{ + //children already added, so just hide/show. + $(this).children('ul').toggle();\n }\n event.stopPropagation(); + });\n/*\n Find the parents of a child.\n*/\nfunction findParents(child){ + var parents =[$(child).attr("data-name")] + var theParent = $(child).attr("data-parent") + while(theParent !=undefined){ \n var child = $(child).parent(); + if(child.prop("tagName")=="UL") continue; + parents.unshift(child.attr("data-name")); + theParent = child.attr("data-parent");\n }\n return parents\n}\n/* + Helper function: returns filename appended onto val.\n*/ +function getFile(theName){\n var f = baseFile(theName) + if(f)return theName+=type(f)\n return theName\n}\n/* + Add params to the object. Object can be of any type + (normally module or param). + Will be used by modules adding parameters, psets adding parameters.\n*/ + var $LIBasic = $(document.createElement('li')).attr("class","param"); + var $LIExpand = $LIBasic.clone().attr("class","expand");\n +function addParams(obj, params){ + var fileChecked = document.getElementById("ShowFiles").checked + var $span = $(document.createElement("span")); + var $typeSpan = $span.clone().addClass("type"); + var $valSpan = $span.clone().addClass("value"); + var $UL = $(document.createElement("ul")); + var $objName = $(obj).attr('data-name');\n\n if(!params) + params = baseParams($objName)\n for(var i =0; i < params.length; i++){ + var all = params[i].slice() // make copy of it + var isList= typeof(all)=="object" + var theName = isList ? all.shift(): all + var typ= !isList || !all.length ? baseType(theName): all.pop() + var gen = getGenericType(typ) + var spt = $typeSpan.clone().attr("data-name",typ).text(type(typ)) + if(fileChecked) text = getFile(theName) + if(isList && typeof(all[0]) == "object"){\n // PSets + var cloLI = doLI(false,theName,i,"paramInner",spt) + cloLI.attr("data-parent", $objName)\n } + else if(baseParams(theName)){\n // Modules or sequences + var cloLI = doLI(false,theName,i,gen,spt)\n }\n else{ + // Basic type, has no children\n var cloLI= doLI(true,theName,i) + var value =""\n if(all.length)\n var value = all.shift() + // formating so lots of strings look nicer\n var valDataName = value + if(value.indexOf(",")>-1){ + value = "
    • "+value.replace(/,/g, ",
    • ")+"
    " + }\n var add = type(typ) + cloLI.append($valSpan.clone().attr("data-name",valDataName).html(value)) + cloLI.append($typeSpan.clone().attr("data-name",add).text(add)) + for(var p=0; p < all.length; p++){\n var n = type(all[p]) + cloLI.append($typeSpan.clone().attr("data-name",n).text(n))\n } + } \n $UL.append(cloLI);\n }\n $(obj).append($UL);\n}\n +function type(theName){\n return " ("+theName+")"\n}\n/* + Helper function: Adds data to a LI.\n*/ +function doLI(basic,dataN,dataI,classes,html){ + if(basic) var $LI = $LIBasic.clone()\n else var $LI = $LIExpand.clone() + $LI.attr("data-name", dataN).attr("data-index", dataI).text(dataN); + if(classes)$LI.addClass(classes)\n if(html)$LI.append(html)\n return $LI +}\n/*\n Box to show params has been clicked.\n*/ +$(document).on('click', '#ShowParams', function(e){ + if($(this).is (':checked')){\n showParams = true\n }\n else{ + $(this).next().hide()\n showParams = false\n }\n});\n/* + Removes children from top level list elements.\n*/ +$(document).on('click', '#hide', function(e){ + //make sure not called when not needed. + if($(this).css('cursor')!='default'){ + var selec = $(".expanded."+topClass).children("ul").hide() + toggleExpand($(".expanded."+topClass ),e)\n invisibleHide()\n }\n}); +// --- end of expand and show more data operations --- +// --- general helper operations and functions ---\n\n/* + Return to normal viewing mode.\n*/\nfunction goNormal(it){ + expandDisable = false; + $(".cellEdit").replaceWith(function() { return $(this).contents();}); + $("#save").remove()\n $("#mode")[0].textContent = "Normal Mode" + it.attr("value", "Edit");\n it.attr("id", "editMode")\n}\n/* + Set what the CURRENT_OBJ is.\n*/\nfunction setCURRENT_OBJ($element){ + var thefunction = $element.attr("data-base"); + var list = $element.attr("data-files").split(" ");\n if(list.length >1){ + CURRENT_OBJ = window[thefunction](list[1], list[0])\n } \n else{ + CURRENT_OBJ = window[thefunction](list[0])\n }\n}\n/* + Add option in html to show/hide parameters.\n*/\nfunction paramOptions(bool){ + if(!bool){\n $("#attachParams").empty()\n return\n } + var lb= jQuery('