Changeset 64729b in indico
- Timestamp:
- 03/17/10 20:31:23 (3 years ago)
- Branches:
- master, burotel, hello-world-walkthrough, ipv6, new-webex, prov-dual-interface, v0.97-series, v0.98-series, v0.98.2, v0.98.3, v0.98b1, v0.98b2, v0.99, 051b2622c51afb171a1dedb46a0df4fbb0cbd02e, d9941f8582b36b24821a11ea5ba16fda6a457fb1
- Children:
- 7dd15f, f3d0f4
- Parents:
- 382574
- git-author:
- Pedro Ferreira <jose.pedro.ferreira@…> (03/05/10 17:24:34)
- git-committer:
- Pedro Ferreira <jose.pedro.ferreira@…> (03/17/10 20:31:23)
- Location:
- indico
- Files:
-
- 1 added
- 17 edited
-
MaKaC/common/output.py (modified) (7 diffs)
-
MaKaC/webinterface/materialFactories.py (modified) (3 diffs)
-
MaKaC/webinterface/rh/conferenceBase.py (modified) (5 diffs)
-
MaKaC/webinterface/stylesheets/include/common.xsl (modified) (1 diff)
-
MaKaC/webinterface/tpls/AdminPlugins.tpl (modified) (1 diff)
-
MaKaC/webinterface/tpls/ShowExistingMaterial.tpl (modified) (1 diff)
-
MaKaC/webinterface/tpls/js/vars.js.tpl (modified) (1 diff)
-
MaKaC/webinterface/wcomponents.py (modified) (2 diffs)
-
htdocs/css/Default.css (modified) (4 diffs)
-
htdocs/images/balloon_popup_arrows_yellow.png (added)
-
htdocs/js/indico/Core/Data.js (modified) (1 diff)
-
htdocs/js/indico/Core/Dialogs/Popup.js (modified) (5 diffs)
-
htdocs/js/indico/Core/Widgets/Base.js (modified) (7 diffs)
-
htdocs/js/indico/Core/Widgets/Inline.js (modified) (11 diffs)
-
htdocs/js/indico/Legacy/Dialogs.js (modified) (1 diff)
-
htdocs/js/indico/Legacy/Util.js (modified) (2 diffs)
-
htdocs/js/indico/MaterialEditor/Editor.js (modified) (33 diffs)
-
htdocs/js/indico/Timetable/Base.js (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
indico/MaKaC/common/output.py
r382574 r64729b 111 111 self.webFactory = WebFactoryRegistry() 112 112 113 # TODO: Put this out of here, and unify with WShowExistingMaterial._generateMaterialList 114 # (when we have a better class hierarchy) 115 def _generateMaterialList(self, obj): 116 """ 117 Generates a list containing all the materials, with the 118 corresponding Ids for those that already exist 119 """ 120 121 from MaKaC.webinterface.rh.conferenceBase import RHSubmitMaterialBase 122 if isinstance(obj, conference.Category): 123 _allowedMats = RHSubmitMaterialBase._allowedMatsCategory 124 else: 125 _allowedMats = RHSubmitMaterialBase._allowedMatsEvent[obj.getConference().getType()] 126 127 matDict = dict((title.lower(), title) for title in _allowedMats) 128 129 for material in obj.getMaterialList(): 130 title = material.getTitle().lower() 131 matDict[title] = material.getId() 132 133 return sorted(list((matId, title.title()) for title, matId in matDict.iteritems())) 134 135 113 136 def getOutput(self, conf, stylesheet, vars=None, includeSession=1,includeContribution=1,includeMaterial=1,showSession="all",showDate="all",showContribution="all"): 114 137 # get xml conference … … 188 211 else: 189 212 out.writeTag("category","") 213 214 out.writeTag("parentProtection", simplejson.dumps(conf.getAccessController().isProtected())) 215 out.writeTag("materialList", simplejson.dumps(self._generateMaterialList(conf))) 190 216 191 217 if conf.canModify( self.__aw ) and vars and modificons: … … 216 242 217 243 out.writeTag("customMaterialList", simplejson.dumps(customMaterials)) 218 244 219 245 if conf.getOrgText() != "": 220 246 out.writeTag("organiser", conf.getOrgText()) … … 452 478 out.openTag("session") 453 479 out.writeTag("ID",session.getId()) 480 454 481 if session.getCode() not in ["no code", ""]: 455 482 out.writeTag("code",session.getCode()) … … 535 562 out.openTag("session") 536 563 out.writeTag("ID",session.getId()) 564 565 out.writeTag("parentProtection", simplejson.dumps(session.getAccessController().isProtected())) 566 out.writeTag("materialList", simplejson.dumps(self._generateMaterialList(session))) 567 568 537 569 slotCode = session.getSortedSlotList().index(slot) + 1 538 570 if session.getCode() not in ["no code", ""]: … … 609 641 out.openTag("contribution") 610 642 out.writeTag("ID",cont.getId()) 643 644 out.writeTag("parentProtection", simplejson.dumps(cont.getAccessController().isProtected())) 645 out.writeTag("materialList", simplejson.dumps(self._generateMaterialList(cont))) 646 611 647 if cont.getBoardNumber() != "": 612 648 out.writeTag("board",cont.getBoardNumber()) … … 708 744 out.openTag("subcontribution") 709 745 out.writeTag("ID",subCont.getId()) 746 747 out.writeTag("parentProtection", simplejson.dumps(subCont.getContribution().getAccessController().isProtected())) 748 out.writeTag("materialList", simplejson.dumps(self._generateMaterialList(subCont))) 749 710 750 if subCont.canModify( self.__aw ) and vars and modificons: 711 751 out.writeTag("modifyLink",vars["subContribModifyURLGen"](subCont)) -
indico/MaKaC/webinterface/materialFactories.py
r0d29a2 r64729b 333 333 and creates new one if needed. """ 334 334 335 # inheritance from MaterialFactory is actually not needed 336 337 def __init__(self, name): 338 self.name = name 339 335 def __init__(self, matId): 336 self.name = matId 337 340 338 def get( self, owner ): 341 339 """returns the material""" 342 340 343 341 for mat in owner.getMaterialList(): 344 if mat.getTitle() == self.name:342 if mat.getTitle().lower() == self.name.lower(): 345 343 return mat 346 347 return None348 349 def getTitle(self):350 return self.name351 352 def getId(self):353 return self.id354 344 355 345 def remove( self, owner ): … … 358 348 359 349 def canAdd( self, target ): 360 #only one slide can be added to a contribution361 350 return True 362 351 363 352 def canDelete( self, target ): 364 #only a slide which is already set in a contribution can be deleted365 353 return len(target.getMaterialList) > 0 366 354 367 355 def getModificationURL( self, mat ): 368 """returns the URL for accessing to the modification view of the 369 material""" 370 return urlHandlers.UHMaterialModification.getURL( mat ) 371 372 def create( self, target):356 """returns the URL for accessing to the modification view of the 357 material""" 358 return urlHandlers.UHMaterialModification.getURL( mat ) 359 360 def create(self, target): 373 361 m = conference.Material() 374 m.setTitle(self.name )362 m.setTitle(self.name.title()) 375 363 target.addMaterial( m ) 376 364 return m 365 377 366 378 367 @classmethod … … 380 369 return cls(name) 381 370 371 382 372 class MaterialFactoryRegistry: 383 """Keeps a list of material factories. When a new material type wants to be 373 """Keeps a list of material factories. When a new material type wants to be 384 374 added one just needs to implement the corresponding factory and add the 385 375 entry in the "_registry" attribute of this class 386 376 """ 387 _registry = {} 377 _registry = {} 388 378 389 379 @classmethod 390 def getById( cls, id ):391 return cls._registry.get( id.lower().strip(), DefaultMaterialFactory.getInstance(id))380 def getById( cls, matId ): 381 return cls._registry.get(matId, DefaultMaterialFactory.getInstance(matId)) 392 382 393 383 @classmethod 394 384 def getList( cls ): 395 385 return cls._registry.values() 386 387 @classmethod 388 def getIdList( cls ): 389 return cls._registry.keys() 396 390 397 391 @classmethod -
indico/MaKaC/webinterface/rh/conferenceBase.py
r382574 r64729b 207 207 _allowedMatsCategory = [ "paper", "slides", "poster", "minutes", "agenda", "video", "pictures", "text", "more information", "document", "list of actions", "drawings", "proceedings", "live broadcast" ] 208 208 209 _allowedMatsEvent = { 210 'simple_event': [ "paper", "slides", "poster", "minutes", "agenda", "pictures", "text", "more information", "document", "list of actions", "drawings", "proceedings", "live broadcast", "video", "streaming video", "downloadable video" ], 211 'meeting': [ "paper", "slides", "poster", "minutes", "agenda", "video", "pictures", "text", "more information", "document", "list of actions", "drawings", "proceedings", "live broadcast" ], 212 'conference' : ["paper", "slides", "poster", "minutes"] 213 } 214 209 215 def __init__(self, target, rh = None): 210 216 self._target=target … … 247 253 self._userList = json.decode(params.get("userList", "")) 248 254 249 250 255 if self._uploadType == "file": 251 256 if type(params["file"]) != str and params["file"].filename.strip() != "": … … 253 258 fDict["filePath"]=self._saveFileToTemp(params["file"].file) 254 259 255 # TODO: Check this!256 260 if self._callerRH != None: 257 261 self._callerRH._tempFilesToDelete.append(fDict["filePath"]) … … 286 290 287 291 def _getMaterial(self): 288 289 """ Returns the Material object to which the ressource is being submitted290 292 """ 291 292 mf = self._target.getMaterialRegistry().getById(self._materialId) 293 294 material = mf.get(self._target) 295 if material is None: 296 material = mf.create(self._target) 297 298 return material 293 Returns the Material object to which the resource is being added 294 """ 295 296 material = None 297 registry = self._target.getMaterialRegistry() 298 299 if isinstance(self._target, Category): 300 namedMats = RHSubmitMaterialBase._allowedMatsCategory 301 else: 302 namedMats = RHSubmitMaterialBase._allowedMatsEvent[self._target.getConference().getType()] 303 304 material = self._target.getMaterialById(self._materialId) 305 306 if material: 307 return material, False 308 # there's a defined id (not new type) 309 elif self._materialId: 310 # get a material factory for it 311 mf = registry.getById(self._materialId) 312 # get a material from the material factory 313 material = mf.get(self._target) 314 315 # if the factory returns an empty material (doesn't exist) 316 if material == None: 317 # create one 318 material = mf.create(self._target) 319 newlyCreated = True 320 else: 321 newlyCreated = False 322 323 return material, newlyCreated 324 else: 325 # else, something has gone wrong 326 raise Exception("""A material ID must be specified.""") 327 328 def _addMaterialType(self, text, user): 329 330 from MaKaC.common.PickleJar import DictPickler 331 332 Logger.get('requestHandler').debug('Adding %s - request %s ' % (self._uploadType, id(self._callerRH._req))) 333 334 mat, newlyCreated = self._getMaterial() 335 336 # if the material still doesn't exist, create it 337 if newlyCreated: 338 protectedAtResourceLevel = False 339 else: 340 protectedAtResourceLevel = True 341 342 if self._uploadType in ['file','link']: 343 if self._uploadType == "file": 344 345 resource = LocalFile() 346 resource.setFileName(self._file["fileName"]) 347 resource.setName(resource.getFileName()) 348 resource.setFilePath(self._file["filePath"]) 349 resource.setDescription(self._description) 350 351 if not type(self._target) is Category: 352 self._target.getConference().getLogHandler().logAction({"subject":"Added file %s%s" % (self._file["fileName"],text)},"Files",user) 353 # in case of db conflict we do not want to send the file to conversion again, nor re-store the file 354 355 elif self._uploadType == "link": 356 357 resource = Link() 358 resource.setURL(self._link["url"]) 359 resource.setName(resource.getURL()) 360 resource.setDescription(self._description) 361 362 if not type(self._target) is Category: 363 self._target.getConference().getLogHandler().logAction({"subject":"Added link %s%s" % (resource.getURL(),text)},"Files",user) 364 365 status = "OK" 366 info = resource 367 else: 368 status = "ERROR" 369 info = "Unknown upload type" 370 return mat, status, info 371 372 mat.addResource(resource, forcedFileId=self._repositoryId) 373 374 #apply conversion 375 if self._topdf and fileConverter.CDSConvFileConverter.hasAvailableConversionsFor(os.path.splitext(resource.getFileName())[1].strip().lower()): 376 Logger.get('conv').debug('Queueing %s for conversion' % resource.getFilePath()) 377 378 fileConverter.CDSConvFileConverter.convert(resource.getFilePath(), "pdf", mat) 379 380 self._topdf = False 381 382 # store the repo id, for files 383 if isinstance(resource, LocalFile): 384 self._repositoryId = resource.getRepositoryId() 385 386 if protectedAtResourceLevel: 387 protectedObject = resource 388 else: 389 protectedObject = mat 390 mat.setHidden(self._visibility) 391 mat.setAccessKey(self._password) 392 393 protectedObject.setProtection(self._statusSelection) 394 395 from MaKaC.user import AvatarHolder, GroupHolder 396 397 for userElement in self._userList: 398 if 'isGroup' in userElement and userElement['isGroup']: 399 avatar = GroupHolder().getById(userElement['id']) 400 else: 401 avatar = AvatarHolder().getById(userElement['id']) 402 protectedObject.grantAccess(avatar) 403 404 return mat, status, DictPickler.pickle(info) 299 405 300 406 def _process(self, rh, params): 301 407 302 408 # We will need to pickle the data back into JSON 303 from MaKaC.common.PickleJar import DictPickler304 409 305 410 errorList=[] … … 325 430 326 431 errorList=self._getErrorList() 327 fDict = self._file328 link = self._link329 432 resource = None 330 433 331 Logger.get('requestHandler').debug('Adding %s - request %s ' % (self._uploadType, id(self._callerRH._req))) 332 if self._uploadType == "file": 333 if len(errorList)==0: 334 mat = self._getMaterial() 335 336 if mat == None: 337 errorList.append("Unknown material"); 338 else: 339 mat.setProtection(self._statusSelection) 340 mat.setHidden(self._visibility) 341 mat.setAccessKey(self._password) 342 from MaKaC.user import AvatarHolder 343 ah = AvatarHolder() 344 for userElement in self._userList: 345 userAvatar = ah.getById(userElement['id']) 346 mat.grantAccess(userAvatar) 347 348 resource = LocalFile() 349 resource.setFileName(fDict["fileName"]) 350 resource.setName(resource.getFileName()) 351 resource.setFilePath(fDict["filePath"]) 352 resource.setDescription(self._description) 353 mat.addResource(resource, forcedFileId=self._repositoryId) 354 355 #apply conversion 356 if self._topdf and fileConverter.CDSConvFileConverter.hasAvailableConversionsFor(os.path.splitext(resource.getFileName())[1].strip().lower()): 357 fileConverter.CDSConvFileConverter.convert(resource.getFilePath(), "pdf", mat) 358 if not type(self._target) is Category: 359 self._target.getConference().getLogHandler().logAction({"subject":"Added file %s%s" % (fDict["fileName"],text)},"Files",user) 360 # in case of db conflict we do not want to send the file to conversion again, nor re-store the file 361 self._topdf = False 362 self._repositoryId = resource.getRepositoryId() 363 364 if len(errorList) > 0: 365 status = "ERROR" 366 info = errorList 367 else: 368 status = "OK" 369 info = DictPickler.pickle(resource) 434 if len(errorList) > 0: 435 status = "ERROR" 436 info = errorList 437 else: 438 mat, status, info = self._addMaterialType(text, user) 439 440 if status == "OK": 370 441 info['material'] = mat.getId(); 371 372 elif self._uploadType == "link":373 if len(errorList)==0:374 mat = self._getMaterial()375 if mat == None:376 mat = Material()377 mat.setTitle(link["matType"])378 self._target.addMaterial( mat )379 else:380 mat.setProtection(self._statusSelection)381 mat.setHidden(self._visibility)382 mat.setAccessKey(self._password)383 from MaKaC.user import AvatarHolder384 ah = AvatarHolder()385 for userElement in self._userList:386 userAvatar = ah.getById(userElement['id'])387 mat.grantAccess(userAvatar)388 389 resource = Link()390 resource.setURL(link["url"])391 resource.setName(resource.getURL())392 resource.setDescription(self._description)393 mat.addResource(resource)394 if not type(self._target) is Category:395 self._target.getConference().getLogHandler().logAction({"subject":"Added link %s%s" % (resource.getURL(),text)},"Files",user)396 397 status = "OK"398 info = DictPickler.pickle(resource)399 info['material'] = mat.getId();400 else:401 status = "ERROR"402 info = errorList403 404 else:405 status = "ERROR"406 info = "Unknown upload type"407 442 408 443 # hackish, because of mime types. Konqueror, for instance, would assume text if there were no tags, -
indico/MaKaC/webinterface/stylesheets/include/common.xsl
r382574 r64729b 128 128 '<xsl:value-of select="$contId"/>', 129 129 '<xsl:value-of select="$subContId"/>', 130 Indico.Data.MaterialTypes.meeting, 130 <xsl:value-of select="$item/parentProtection"/>, 131 <xsl:value-of select="$item/materialList"/>, 131 132 <xsl:value-of select="$uploadURL"/>, 132 133 true, -
indico/MaKaC/webinterface/tpls/AdminPlugins.tpl
r9033fd r64729b 101 101 102 102 <script type="text/javascript"> 103 var tab Control = new TabWidget([103 var tabList = [ 104 104 <%= ",\n".join(['["' + plugin.getName() + '" , $E("' + plugin.getName() + 'OptionsDiv")]' for plugin in pluginList])%> 105 ], null, null, <%= InitialPlugin %>); 105 ] 106 var tabControl = new TabWidget(tabList, null, null, tabList[<%= InitialPlugin %>][0]); 106 107 $E('pluginTabs').set(tabControl.draw()); 107 108 -
indico/MaKaC/webinterface/tpls/ShowExistingMaterial.tpl
r382574 r64729b 79 79 <% end %> 80 80 81 var matList = Indico.Data.MaterialTypes[targetType]; 82 var customMatList = $L(); 81 var matList = <%= DictPickler.pickle(materialList) %> 83 82 84 each(<%= jsonEncode(DictPickler.pickle(self._target.getMaterialList())) %>, function(material){ 85 if (!contains(matList, material.title)){ 86 customMatList.append(material.title); 87 } 88 }); 89 90 var mlist = new MaterialListWidget(args, matList, customMatList, uploadAction); 83 var mlist = new MaterialListWidget(args, matList, uploadAction); 91 84 92 85 $E('materialListPlace').set(mlist.draw()); -
indico/MaKaC/webinterface/tpls/js/vars.js.tpl
r159c54 r64729b 119 119 120 120 Data: { 121 MaterialTypes: { meeting : <%= RHSubmitMaterialBase._allowedMatsForMeetings%>,122 simple_event: <%= RHSubmitMaterialBase._allowedMatsForSE%>,123 conference: <%= RHSubmitMaterialBase._allowedMatsConference%>,124 category: <%= RHSubmitMaterialBase._allowedMatsCategory%>},121 MaterialTypes: { meeting : <%= simplejson.dumps(list((k,k.title()) for k in RHSubmitMaterialBase._allowedMatsForMeetings)) %>, 122 simple_event: <%= simplejson.dumps(list((k,k.title()) for k in RHSubmitMaterialBase._allowedMatsForSE)) %>, 123 conference: <%= simplejson.dumps(list((k,k.title()) for k in RHSubmitMaterialBase._allowedMatsConference)) %>, 124 category: <%= simplejson.dumps(list((k,k.title()) for k in RHSubmitMaterialBase._allowedMatsCategory)) %>}, 125 125 WeekDays: <%= [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ] %>, 126 126 DefaultLocation: '<%= str(Location.getDefaultLocation().friendlyName) %>', -
indico/MaKaC/webinterface/wcomponents.py
rb5b87e r64729b 42 42 from MaKaC.common import Config 43 43 from MaKaC.webinterface.common.person_titles import TitlesRegistry 44 from MaKaC.conference import Conference 44 from MaKaC.conference import Conference, Category 45 45 46 46 from MaKaC.webinterface.common.timezones import TimezoneRegistry, DisplayTimezoneRegistry … … 5541 5541 self._target=target 5542 5542 5543 from MaKaC.webinterface.rh.conferenceBase import RHSubmitMaterialBase 5544 if isinstance(target, Category): 5545 self._allowedMats = RHSubmitMaterialBase._allowedMatsCategory 5546 else: 5547 self._allowedMats = RHSubmitMaterialBase._allowedMatsEvent[self._target.getConference().getType()] 5548 5549 # TODO: Put this out of here, and unify with outputGenerator._generateMaterialList 5550 # (when we have a better class hierarchy) 5551 def _generateMaterialList(self): 5552 """ 5553 Generates a list containing all the materials, with the 5554 corresponding Ids for those that already exist 5555 """ 5556 5557 matDict = dict((title.lower(), title) for title in self._allowedMats) 5558 5559 for material in self._target.getMaterialList(): 5560 title = material.getTitle().lower() 5561 matDict[title] = material.getId() 5562 5563 return sorted(list((matId, title.title()) for title, matId in matDict.iteritems())) 5543 5564 5544 5565 def getVars(self): 5545 5566 vars=WTemplated.getVars(self) 5567 5568 vars["materialList"] = self._generateMaterialList() 5546 5569 5547 5570 vars["materialModifHandler"] = vars.get("materialModifHandler", None) -
indico/htdocs/css/Default.css
r1b3372 r64729b 4504 4504 height: 15px; 4505 4505 } 4506 div.exclusivePopup .buttonBar { 4507 text-align: center; 4508 background: #F8F8F8; 4509 border: 0px; 4510 -moz-border-radius-bottomleft: 10px; 4511 -webkit-border-bottom-left-radius:10px; 4512 -moz-border-radius-bottomright: 10px; 4513 -webkit-border-bottom-right-radius:10px; 4514 behavior: url(border-radius.htc); 4515 border-top: 1px solid #CCC; 4516 min-height: 40px; 4517 padding-top: 10px; 4518 } 4519 4506 4520 4507 4521 div.balloonPopup { … … 4521 4535 background-repeat: no-repeat; 4522 4536 background-position: 0 -19px; 4523 } 4537 opacity: 0.95; 4538 } 4539 4540 div.yellowBalloon { 4541 color: #000; 4542 border: 1px solid black; 4543 background-color: #ffed92; 4544 opacity: 0.95; 4545 } 4546 4547 div.yellowArrow { 4548 background: transparent url('../images/balloon_popup_arrows_yellow.png') scroll no-repeat 0 -19px; 4549 } 4550 4524 4551 4525 4552 div.balloonPopupCloseButton { … … 5162 5189 } 5163 5190 5191 ul.nobulletsListWrapping 5192 { 5193 position: relative; 5194 margin:0px; 5195 margin-top: 10px; 5196 padding-left: 0px; 5197 color: #777; 5198 } 5199 5200 ul.nobulletsListWrapping li 5201 { 5202 margin-top: 5px; 5203 overflow: visible; 5204 list-style-type: none; 5205 } 5206 5164 5207 div.FavoritePeopleListDiv { 5165 5208 margin-bottom: 10px; … … 5686 5729 border-right: 1px dotted #999; 5687 5730 } 5731 5732 label.normal { 5733 font-weight: normal; 5734 } 5735 5736 label.emphasis { 5737 font-weight: normal; 5738 font-style: italic; 5739 } 5740 5741 .smallGrey { 5742 margin-top: 2px; 5743 font-size: 9px; 5744 color: #777; 5745 } 5746 5747 tr.selectedItem td { 5748 color: #000; 5749 } -
indico/htdocs/js/indico/Core/Data.js
r62a512 r64729b 186 186 // check if the emails given are valid and if valid separators are used 187 187 return exists(emails.toLowerCase().match(/^(?:[ ,;]*)(?:[a-z0-9!#$%&\'*+\/=?\^_`{|}~\-]+(?:\.[a-z0-9!#$%&\'*+\/=?\^_`{|}~\-]+)*@(?:[a-z0-9](?:[a-z0-9\-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9\-]*[a-z0-9])?)(?:[ ,;]+(?:[a-z0-9!#$%&\'*+\/=?\^_`{|}~\-]+(?:\.[a-z0-9!#$%&\'*+\/=?\^_`{|}~\-]+)*@(?:[a-z0-9](?:[a-z0-9\-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9\-]*[a-z0-9])?))*(?:[ ,;]*)$/)); 188 }, 189 isURL: function(address) { 190 // thanks to Jan Goyvaerts 191 return exists(address.match(/^http\:\/\/(.+)$/)); 192 } 193 194 195 }; 196 197 Protection = { 198 199 ParentRestrictionMessages: { 200 '1': $T("(currently restricted to some users, but can change)"), 201 '-1': $T("(currently open to everyone, but can change)") }, 202 203 resolveProtection: function(resourceProtection, parentProtection) { 204 if (resourceProtection === 0) { 205 return parentProtection; 206 } else { 207 return resourceProtection; 208 } 188 209 } 189 210 }; -
indico/htdocs/js/indico/Core/Dialogs/Popup.js
r156de9 r64729b 281 281 ); 282 282 283 /* ExclusivePopup with a grey bar where buttons can be put */ 284 type("ButtonBarExclusivePopup", ["ExclusivePopup"], 285 { 286 draw: function(content, style) { 287 288 var menu = Html.div("buttonBar", this._drawButtons()); 289 290 var canvas = this.ExclusivePopup.prototype.draw.call(this, content, style); 291 this.container.append(menu); 292 293 return canvas; 294 } 295 }, 296 function(title, closeButtonHandler, printable, showPrintButton) { 297 this.ExclusivePopup(title, closeButtonHandler, printable, showPrintButton); 298 }); 299 283 300 type("BalloonPopup", ["PopupDialog"], { 284 301 draw: function(x, y) { … … 286 303 287 304 this.closeButton = Html.div({className: 'balloonPopupCloseButton'}); 288 this.balloonContent = Html.div({className: 'balloonPopup'}, this.closeButton, this.content);289 this.arrowDiv = Html.div({className: 'balloonPopupArrow', style: {width: this.arrowWidth, height: this.arrowHeight}});305 this.balloonContent = Html.div({className: this.balloonClass}, this.hasCloseButton ? this.closeButton : '', this.content); 306 this.arrowDiv = Html.div({className: this.arrowClass, style: {width: this.arrowWidth, height: this.arrowHeight}}); 290 307 this.mainDiv = Html.div({}, this.balloonContent, this.arrowDiv); 291 308 … … 299 316 300 317 this.arrowDiv.dom.style.left = pixels(0); 301 this.closeButton.observeClick(function() {self.close();}); 318 319 if (this.hasCloseButton) { 320 this.closeButton.observeClick(function() {self.close();}); 321 } 302 322 303 323 return toReturn; … … 387 407 } 388 408 }, 389 function(content, triggerElement, closeHandler, nonCloseElements ) {409 function(content, triggerElement, closeHandler, nonCloseElements, balloonClass, arrowClass) { 390 410 this.PopupDialog(content, triggerElement, closeHandler, nonCloseElements); 411 412 this.hasCloseButton = exists(closeHandler); 413 414 this.balloonClass = balloonClass || 'balloonPopup'; 415 this.arrowClass = arrowClass || 'balloonPopupArrow'; 391 416 392 417 // Constants … … 396 421 } 397 422 ); 423 424 /** 425 * Utility function to display a simple notification popup. 426 * @param {XElement} pointElement The element that triggers the event (onClick on it will be ignored) 427 * @param {XElement} content Anything you want to put inside. 428 */ 429 type("NotificationBalloonPopup", ["BalloonPopup"], 430 { 431 }, 432 function(pointElement, content) { 433 this.pointElement = pointElement; 434 435 var canvas = Html.div({style: 436 {padding: '5px'}}, content); 437 438 this.BalloonPopup(canvas, 439 pointElement, 440 null, 441 null, 442 'balloonPopup yellowBalloon', 443 'balloonPopupArrow yellowArrow'); 444 }); 445 398 446 399 447 /** -
indico/htdocs/js/indico/Core/Widgets/Base.js
r06ec19 r64729b 109 109 ); 110 110 111 type("TabWidget", [" Chooser", "IWidget"],{111 type("TabWidget", ["IWidget"],{ 112 112 _titleTemplate: function(text) { 113 113 return text; 114 114 }, 115 115 116 enableTab: function(index) { 117 this.tabs[index].dom.style.display = 'inline'; 118 }, 119 120 disableTab: function(index) { 121 this.tabs[index].dom.style.display = 'none'; 122 }, 123 116 124 enable: function() { 117 125 this.disableOverlay.dom.style.display = 'none'; … … 120 128 disable: function() { 121 129 this.disableOverlay.dom.style.display = 'block'; 130 }, 131 132 _drawContent: function() { 133 134 var self = this; 135 136 try { 137 138 each(this.optionDict, 139 function(value, key) { 140 if (key == self.selected.get()) { 141 value.dom.style.display = 'block'; 142 } else { 143 value.dom.style.display = 'none'; 144 } 145 }); 146 147 } catch(e) { 148 if (e == "stopDrawing") { 149 // Otherwise stop drawing 150 } 151 } 122 152 }, 123 153 … … 210 240 // this piece of code is sensitive to exceptions 211 241 // coming from the drawing functions (for LookupTabWidget) 212 try { 213 if(dataRetrievalFunc) { 214 dataRetrievalFunc.call(this); 215 } 216 217 // if everything goes OK, replace the canvas 218 this.canvas.set(Widget.block(this)); 219 220 } catch(e) { 221 if (e == "stopDrawing") { 222 // Otherwise stop drawing 223 } 224 } 242 if(dataRetrievalFunc) { 243 dataRetrievalFunc.call(this); 244 } else { 245 each(this.optionDict, 246 function(value, key) { 247 self.canvas.append(value); 248 }); 249 } 250 251 this._drawContent(); 225 252 226 253 var wrapperStyle = this.width?{width: pixels(this.width)}:{}; … … 424 451 425 452 if (!exists(initialSelection)) { 426 initialSelection = 0;453 initialSelection = options[0][0]; 427 454 } 428 455 … … 435 462 436 463 self.options.append(key); 437 if (value.getParent()) {438 value.getParent().dom.removeChild(value.dom);439 value.setStyle('display','');440 }441 464 }); 442 465 443 this.selected = new WatchValue(this.options.item(initialSelection)); 466 this.optionDict = {}; 467 each(options, function(item) { 468 self.optionDict[item[0]] = item[1]; 469 }); 470 471 this.selected = new WatchValue(); 444 472 445 473 this.selected.observe(function(value) { 446 self. set(value);474 self._drawContent(); 447 475 }); 448 476 449 var optionDict = {}; 450 each(options, function(item) { 451 optionDict[item[0]] = item[1]; 452 }); 453 454 this.Chooser(optionDict); 455 this.set(this.selected.get()); 477 this.selected.set(initialSelection); 456 478 457 479 this.initializeDisableOverlay(); … … 461 483 type("LookupTabWidget", ["TabWidget"], 462 484 { 485 _drawContent: function() { 486 var self = this; 487 488 try { 489 this.canvas.set(this.optionDict[self.selected.get()]()); 490 491 } catch(e) { 492 if (e == "stopDrawing") { 493 // Otherwise stop drawing 494 } 495 } 496 }, 497 463 498 draw: function() { 464 499 return this.TabWidget.prototype.draw.call( 465 500 this, 466 501 function() { 467 this. set(this.selected.get());502 this.canvas.set(Html.div({})); 468 503 }); 469 504 } 470 505 }, 506 471 507 function(options, width, height, initialSelection, extraButtons, canvas) { 472 473 var self = this; 474 this.width = width; 475 this.height = height; 476 this.tabs = []; 477 this.leftTabIndex = 0; 478 this.rightTabIndex = 0; 479 this.scrollArrows = {}; 480 this.scrollArrowStates = {}; 481 this.extraButtons = any(extraButtons, []); 482 this.canvas = canvas || Html.div('canvas'); 483 484 this.initializeDisableOverlay(); 485 486 if (!exists(initialSelection)) { 487 initialSelection = 0; 488 } 489 this.options = $L(translate(options, 490 function(value) { 491 return value[0]; 492 })); 493 494 this.selected = new WatchValue(this.options.item(initialSelection)); 495 496 this.selected.observe(function(value) { 497 self.set(value); 498 }); 499 500 var optionDict = {}; 501 each(options, function(item) { 502 optionDict[item[0]] = item[1]; 503 }); 504 505 this.Chooser(new Lookup(optionDict)); 506 508 this.TabWidget(options, width, height, initialSelection, extraButtons, canvas); 507 509 } 510 508 511 ); 509 512 … … 742 745 } 743 746 }, 744 function( ) {745 this.canvas = Html.div( );747 function(styleData) { 748 this.canvas = Html.div({style: styleData}||{}); 746 749 } 747 750 ); -
indico/htdocs/js/indico/Core/Widgets/Inline.js
r382574 r64729b 150 150 151 151 152 type("RadioFieldWidget", ["InlineWidget" ],152 type("RadioFieldWidget", ["InlineWidget", "WatchAccessor"], 153 153 { 154 154 draw: function() { 155 155 var self = this; 156 156 157 return $B(Html.ul(this.cssClassRadios), 158 this.orderedItems, 159 function(item) { 160 var radio = self.radioDict[item.key]; 161 radio.observeClick(function() { 162 self.select(item.key); 163 }); 164 self.options.accessor(item.key).observe( 165 function(value) { 166 radio.set(value); 167 }); 168 169 var itemContent = item.get(); 170 171 if (itemContent.IWidget) { 172 itemContent = itemContent.draw(); 173 } 174 175 // create li item, add visibility info too 176 var liItem = Html.li(self.visibility.get(item.key)?{}:'disabledRadio', keys(self.radioDict).length > 1?radio:'', itemContent); 177 radio.dom.disabled = !self.visibility.get(item.key); 178 179 180 // observe future changes in visibility 181 self.visibility.accessor(item.key).observe( 182 function(value) { 183 if (!value) { 184 liItem.dom.className = 'disabledRadio'; 185 radio.dom.disabled = true; 186 } else { 187 liItem.dom.className = 'enabledRadio'; 188 radio.dom.disabled = false; 189 } 190 if (!value && radio.get()) { 191 self.selectLast(); 192 } 193 }); 194 195 196 return liItem; 197 }); 157 return $B( 158 Html.table( 159 this.cssClassRadios, 160 Html.tbody({}) 161 ), 162 this.orderedItems, 163 function(item) { 164 var radio = self.radioDict[item.key]; 165 radio.observeClick(function() { 166 self.select(item.key); 167 }); 168 self.options.accessor(item.key).observe( 169 function(value) { 170 radio.set(value); 171 if (value) { 172 liItem.dom.className = 'selectedItem'; 173 } else { 174 liItem.dom.className = ''; 175 } 176 }); 177 178 var itemContent = item.get(); 179 180 if (itemContent.IWidget) { 181 itemContent = itemContent.draw(); 182 } else { 183 itemContent = Html.span({style:{verticalAlign: 'middle'}}, itemContent); 184 } 185 186 // create li item, add visibility info too 187 var liItem = Html.tr( 188 self.visibility.get(item.key) ? {} : 'disabledRadio', 189 keys(self.radioDict).length > 1 ? Html.td({}, radio):'', 190 Html.td( {}, itemContent )); 191 radio.dom.disabled = !self.visibility.get(item.key); 192 193 if (self.options.get(item.key)) { 194 liItem.dom.className = 'selectedItem'; 195 } 196 197 198 // observe future changes in visibility 199 self.visibility.accessor(item.key).observe( 200 function(value) { 201 if (!value) { 202 liItem.dom.className = 'disabledRadio'; 203 radio.dom.disabled = true; 204 } else { 205 liItem.dom.className = 'enabledRadio'; 206 radio.dom.disabled = false; 207 } 208 if (!value && radio.get()) { 209 self.selectLast(); 210 } 211 }); 212 213 214 return liItem; 215 }); 198 216 }, 199 217 … … 203 221 204 222 onSelect: function(state) { 223 }, 224 225 set: function(state) { 226 this.select(state); 227 }, 228 229 get: function() { 230 var selKey = null; 231 232 each(this.options, function(value, key){ 233 if (value) { 234 selKey = key; 235 } 236 }); 237 238 return selKey; 239 }, 240 241 enable: function() { 242 each(this.radioDict, 243 function(value, key) { 244 value.dom.disabled = false; 245 }); 246 }, 247 248 disable: function() { 249 each(this.radioDict, 250 function(value, key) { 251 value.dom.disabled = true; 252 }); 253 }, 254 255 observe: function(callback) { 256 this.options.observe(function(value, key){ 257 if (value) { 258 callback(key); 259 } 260 }); 205 261 }, 206 262 … … 220 276 // set every other option to false 221 277 self.options.each(function(value, key) { 278 222 279 if (value) { 223 280 self.options.set(key, false); … … 231 288 232 289 }); 290 233 291 self.options.set(state, true); 234 292 … … 260 318 }, 261 319 262 function(items, order,cssClassRadios) {263 this.items = items;320 function(items, cssClassRadios) { 321 this.items = {}; 264 322 this.radioDict = {}; 265 323 this.options = new WatchObject(); … … 272 330 var name = Html.generateId(); 273 331 274 // consider ordering of elements, if specified 275 if (order) { 276 this.orderedItems = $L(); 277 each(order, 278 function(key) { 279 self.orderedItems.append(new WatchPair(key, items[key])); 280 281 // add some extra stuff, since we're in the loop 282 self.visibility.set(key, true); 283 self.options.set(key, false); 284 self.radioDict[key] = Html.radio({'name': name}); 285 }); 286 287 } else { 288 this.orderedItems = $L(items); 289 } 332 this.orderedItems = $L(); 333 each(items, 334 function(item) { 335 var key = item[0]; 336 self.items[key] = item[1]; 337 self.orderedItems.append(new WatchPair(key, item[1])); 338 339 // add some extra stuff, since we're in the loop 340 self.visibility.set(key, true); 341 self.options.set(key, false); 342 self.radioDict[key] = Html.radio({'name': name, 343 style: {verticalAlign: 'middle'}}); 344 }); 290 345 291 346 this.state = new Chooser(map(items, … … 956 1011 return Html.div({}, bind.element(self.select, $L(self.types), 957 1012 function(value) { 958 return Html.option({'value': value }, value);1013 return Html.option({'value': value[0]}, value[1]); 959 1014 }), 960 1015 " ", … … 963 1018 Widget.link(command(function() { 964 1019 chooser.set('write'); 1020 self.text.dom.focus(); 965 1021 }, $T("other")))); 966 1022 }, … … 977 1033 Widget.link(command(function() { 978 1034 chooser.set('select'); 1035 self.select.dom.focus(); 979 1036 }, $T("select from list")))); 980 1037 } … … 988 1045 var self = this; 989 1046 return self.selected; 1047 }, 1048 1049 set: function(value) { 1050 if(this.selected){ 1051 this.select.set(value); 1052 } else { 1053 this.text.set(value); 1054 } 1055 1056 each(this.observers, 1057 function(observer) { 1058 observer(value); 1059 }); 990 1060 }, 991 1061 … … 1000 1070 }, 1001 1071 1072 observe: function(callback) { 1073 var self = this; 1074 this.observers.push(callback); 1075 1076 this.select.observe( 1077 function(value) { 1078 if (self.selected) { 1079 callback(value); 1080 } 1081 }); 1082 1083 this.text.observe( 1084 function(value) { 1085 if (!self.selected) { 1086 callback(value); 1087 } 1088 }); 1089 1090 }, 1091 1002 1092 getSelectBox: function() { 1003 1093 return this.select; 1004 1094 } 1005 1095 }, 1006 function(parameterManager, types){ 1007 //var self = this; 1008 this.select = Html.select({name: 'materialId', id:Html.generateId()}); 1009 this.text = Html.edit({name: 'materialId', id:Html.generateId()}); 1010 this.pm = parameterManager; 1011 this.types = types; 1012 } 1013 ); 1096 function(parameterManager, types, params){ 1097 params = params || {}; 1098 1099 this.select = Html.select(params); 1100 params.id = Html.generateId(); 1101 this.text = Html.edit(params); 1102 1103 this.selected = true; 1104 this.pm = parameterManager; 1105 this.types = types; 1106 1107 this.observers = []; 1108 } 1109 ); 1014 1110 1015 1111 type("InlineEditWidget", ["InlineRemoteWidget"], -
indico/htdocs/js/indico/Legacy/Dialogs.js
r721175 r64729b 121 121 $B(info.accessor('conveners'), convListWidget.getUsers()); 122 122 123 var sesType = new RadioFieldWidget({'standard':$T('Standard'),'poster':$T('Poster')},['standard','poster'],'nobulletsListInline'); 123 var sesType = new RadioFieldWidget([['standard', $T('Standard')],['poster',$T('Poster')]],'nobulletsListInline'); 124 $B(info.accessor('sessionType'), sesType); 125 124 126 sesType.select('standard'); 125 $B(info.accessor('sessionType'), sesType.state);126 127 127 128 //Create the list of the days in which the conference is being held -
indico/htdocs/js/indico/Legacy/Util.js
r0f3143 r64729b 491 491 error = Html.span({}, "List contains invalid e-mail address or invalid separator"); 492 492 } 493 else if (dataType == 'url' && !(allowEmpty && trim(component.get()) === '') && !Util.Validation.isURL(component.get())) { 494 error = Html.span({}, "Invalid URL"); 495 } 493 496 else if (dataType == 'ip' && !(allowEmpty && trim(component.get()) === '') && !Util.Validation.isIPAddress(component.get())) { 494 497 error = Html.span({}, "That doesn't seem like a valid IP Address. Example of valid IP Address: 132.156.31.38"); … … 505 508 hasErrors = true; 506 509 507 var oList = [];510 var oList; 508 511 509 512 if (component.dom.type != 'radio') { -
indico/htdocs/js/indico/MaterialEditor/Editor.js
r382574 r64729b 1 2 type("AddMaterialDialog", ["ExclusivePopup"], { 3 _preload: [ 4 function(hook){ 5 var self = this; 6 var users = indicoSource('material.listAllowedUsers', self.args); 7 8 users.state.observe(function(state) { 9 if (state == SourceState.Loaded) { 10 self.allowedUsers = users.get(); 11 hook.set(true); 12 } 13 }); 14 } 15 ], 1 type("AddMaterialDialog", ["ButtonBarExclusivePopup"], { 2 3 _drawButtons: function() { 4 5 var self = this; 6 7 var buttonDiv = Html.div({}, 8 Widget.button(command(function() { 9 self._upload(); 10 }, "Create Resource"))); 11 12 return buttonDiv; 13 }, 16 14 17 15 _iFrameLoaded : function(iframeId) { … … 44 42 }, 45 43 46 _makeProtectionRequest: function(value){ 47 var self = this; 48 49 self.args['matId'] = value; 50 var protection = indicoSource('material.getProtection', self.args); 51 52 protection.state.observe(function(state) { 53 self.protectionLabel.set('statusSelection', protection); 54 }) 55 }, 56 57 _drawFileUpload: function() { 58 var self = this; 59 60 var pm = new IndicoUtil.parameterManager(); 61 62 var uploadType = Html.input('hidden', {name: 'uploadType'}); 63 var convert = Html.checkbox({}, true); 64 var selectorFile = new TypeSelector(pm, self.types); 65 var selectorF = selectorFile.draw(); 44 /* 45 * Draws a pane that switches between a URL input and a file upload dialog. 46 * 47 * pm - A parameter manager 48 * locationSelector - the locationSelector that will 'control' the pane 49 */ 50 _drawResourcePathPane: function(locationSelector) { 51 66 52 var file = Html.input('file', {name: 'file'}); 67 var description = Html.textarea({name: 'description'}); 68 var statusSelection = Html.input('hidden', {name: 'statusSelection'}); 69 var visibility = Html.input('hidden', {name: 'visibility'}); 70 var password = Html.input('hidden', {name: 'password'}); 71 var userList = Html.input('hidden', {name: 'userList'}); 72 73 uploadType.set('file'); 74 75 // FIX: presentation issue 76 convert.dom.name = 'topdf'; 77 78 //pm.add(selectorF, 'text', false); 79 pm.add(file, 'text', false); 80 pm.add(description, 'text', true); 81 82 //make request and save it 83 this._makeProtectionRequest(self.args.materialIdsList.get(selectorFile.getSelectBox().get())); 84 85 selectorFile.getSelectBox().observe(function(value){ 86 //make request and save it 87 self._makeProtectionRequest(self.args.materialIdsList.get(value)); 88 } 89 ) 53 var url = Html.edit({name: 'url'}); 54 var toPDFCheckbox = Html.checkbox({name: 'topdf', style: {verticalAlign: 'middle'}}, true); 55 56 var self = this; 57 58 var resourcePathPane = new Chooser( 59 new Lookup({ 60 'local': function() { 61 self.pm.remove(url); 62 return Html.div({}, 63 self.pm.add(file, 'text'), 64 Html.div({style:{marginTop: '5px'}}, 65 toPDFCheckbox, 66 Html.label({style: {verticalAlign: 'middle'}, className: 'emphasis'} 67 , $T("Convert to PDF (when applicable)"))) 68 ); 69 }, 70 'remote': function() { 71 self.pm.remove(file); 72 url.set('http://'); 73 url.dom.focus(); 74 return Html.div({}, 75 Html.label('popUpLabel', $T("URL")), 76 self.pm.add(url, 'url'), 77 Html.div("smallGrey", "Example: http://www.example.com/YourPDFFile.pdf")); 78 } 79 })); 80 81 // whenever the user selects a different location, 82 // change between an http link field and an upload box. 83 // This could be done simply with: 84 // $B(resourcePathPane, locationSelector); 85 // but we need to change the focus too, so let's use an observer 86 87 locationSelector.observe(function(value) { 88 // switch to the appropriate panel 89 resourcePathPane.set(value); 90 91 // set the focus 92 if (value == 'local') { 93 file.dom.focus(); 94 } else { 95 url.dom.focus(); 96 } 97 }); 98 99 // change the upload type that will be sent in the request 100 // (bind it with the selection box) 101 $B(this.uploadType, 102 locationSelector, 103 { 104 toSource: function(value) { 105 // unused; 106 }, 107 toTarget: function(value) { 108 return value=='local'?'file':'link'; 109 } 110 }); 111 112 // default is 'local' (local file) 113 locationSelector.set('local'); 114 115 return resourcePathPane; 116 117 }, 118 119 _parentText: function(args) { 120 var text = null; 121 122 if (args.subContId) { 123 text = $T("Same people as parent Subcontribution"); 124 } else if (args.contribId) { 125 text = $T("Same people as parent Contribution"); 126 } else if (args.sessionId) { 127 text = $T("Same people as parent Session"); 128 } else if (args.confId) { 129 text = $T("Same people as parent Conference"); 130 } else if (args.categId) { 131 text = $T("Same people as parent Category"); 132 } 133 134 text = Html.span({}, text, " ", 135 Html.span({style: {fontStyle: 'italic'}}," ", 136 Protection.ParentRestrictionMessages[args.parentProtected?1:-1])); 137 138 return text; 139 }, 140 141 _drawProtectionPane: function(value) { 142 143 var text = null; 144 var entry = this.list.get(value); 145 var selector = null; 146 147 // if the material is already in the tree, protection inheritance must 148 // be resolved 149 if (exists(entry)) { 150 151 this.creationMode = 'resource'; 152 153 text = Html.span({}, $T("You're adding a resource to the existing material type"), " ", Html.span({style:{fontWeight: 'bold'}}, entry.get('title')), ". ", $T("Please specify who will be able to access it.")); 154 155 // if the material is set to inherit from the parent, display it properly 156 // and set the inherited protection accordingly 157 var protection = Protection.resolveProtection( 158 entry.get('protection'), 159 entry.get('protectedOwner')?1:-1); 160 161 var inheritanceText = Html.span({style: {fontStyle: 'italic'}}, 162 Protection.ParentRestrictionMessages[protection]); 163 164 165 selector = new RadioFieldWidget([ 166 ['inherit', Html.span({}, $T("Same people as the parent material type ")+"\""+entry.get('title')+"\" ", inheritanceText)], 167 ['private', $T("Only me and the users I specify")], 168 ['public', $T("Everyone")] 169 ], 'nobulletsListWrapping'); 170 171 172 } else { 173 174 this.creationMode = 'material'; 175 176 text = $T("You're about to create a new material type. Please select who can access it."); 177 178 selector = new RadioFieldWidget([ 179 ['inherit', this._parentText(this.args)], 180 ['private', $T("Only me and the users I specify")], 181 ['public', $T("Everyone")] 182 ], 'nobulletsListWrapping'); 183 } 184 185 this.protectionSelector = selector; 186 187 var self = this; 188 189 this.protectionSelector.observe(function(state) { 190 191 self.userList.userList.clear(); 192 self.visibility.set(0); 193 self.password.set(''); 194 195 // if 'private' is chosen or 'inherit' was chosen 196 // and the parent resource is protected 197 if (state == 'private') { 198 self.tabWidget.enableTab(1); 199 200 // depending on whether we're creating a new 201 // material or just a result, we will enable/disable 202 // visibility and access key 203 if (self.creationMode == 'material') { 204 self.visibility.enable(); 205 self.password.enable(); 206 } else { 207 self.visibility.disable(); 208 self.password.disable(); 209 } 210 211 // draw a little notification saying that 212 // the added tab can be used 213 self.notification = new NotificationBalloonPopup( 214 selector.radioDict[state], 215 Html.div({style:{width: '120px'}}, $T("You can specify users using this tab"))); 216 217 var pos = self.tabWidget.tabs[1].getAbsolutePosition(); 218 219 // open it, pointing to tab 220 self.notification.open(pos.x + self.tabWidget.tabs[1].dom.offsetWidth/2, pos.y); 221 222 } else { 223 self.tabWidget.disableTab(1); 224 } 225 226 // set the appropriate data structure behind the scenes 227 self.protectionStatus.set('statusSelection', 228 {'private': 1, 229 'inherit': 0, 230 'public': -1}[state]); 231 }); 232 233 // set protection default to 'inherit' 234 if (this.tabWidget) { 235 this.protectionSelector.set('inherit'); 236 } 237 238 return Html.div({style:{marginTop: '10px', 239 height: '150px' 240 }}, 241 Html.div({style: {textAlign: 'center', fontStyle: 'italic', color: '#881122'}}, 242 $T(text)), 243 Html.div({style: {marginTop: '10px'}}, 244 selector ? selector.draw() : '')); 245 }, 246 247 _drawUpload: function() { 248 249 var self = this; 250 251 this.pm = new IndicoUtil.parameterManager(); 252 var typeSelector = new TypeSelector(this.pm, this.types, {style:{width: '150px'}}); 253 var description = Html.textarea({name: 'description', style:{width:'220px', height: '60px'}}); 254 255 // local file vs. url 256 var locationSelector = new RadioFieldWidget([['local',$T('Local file')],['remote',$T('External resource (hyperlink)')]]); 257 258 // draw the resource pane 259 var resourcePathPane = this._drawResourcePathPane(locationSelector); 260 // protection page 261 var protectionPane = $B( 262 Html.div({}), 263 typeSelector, 264 function(value) { 265 return self._drawProtectionPane(value); 266 }); 267 268 // make typeSelector available to the object 269 this.typeSelector = typeSelector; 90 270 91 271 return Html.div({}, 92 272 IndicoUtil.createFormFromMap( 93 273 [ 94 [$T('Type'), selectorF], 95 [$T('File'), file], 96 [$T('Description'), description], 97 [$T('Convert to PDF'), convert] 274 [ 275 $T('Location'), 276 Html.div({}, 277 locationSelector.draw(), 278 Html.div({style:{paddingTop: '15px', 279 paddingBottom: '10px', 280 minHeight: '50px'}}, 281 Widget.block(resourcePathPane))) 282 ], 283 [ 284 $T('Description'), 285 description 286 ], 287 [ 288 $T('Material type'), 289 typeSelector.draw() 290 ] 291 98 292 ]), 99 uploadType, 100 statusSelection, 101 visibility, 102 password, 103 userList, 104 Html.div({style: {'textAlign': 'center'}}, 105 Widget.button(command( 106 function() { 107 if (pm.check()) { 108 self.killProgress = IndicoUI.Dialogs.Util.progress($T('Uploading...')); 109 self.uploading = true; 110 111 userList.set(Json.write(self.userList.getUsers())); 112 statusSelection.set(self.protectionLabel.get('statusSelection').get()); 113 visibility.set(self.protectionLabel.get('visibility')); 114 password.set(self.protectionLabel.get('password')); 115 self.form.dom.submit(); 116 117 //if we are adding a custom type and it's not in the list already, then we add it 118 if(!selectorFile.isSelect() && !contains(self.types, selectorFile.get())){ 119 self.customTypes.append(selectorFile.get()); 120 } 121 } 122 }, $T("Upload"))))); 123 }, 124 125 _drawLinkUpload: function() { 126 var self = this; 127 128 var pm = new IndicoUtil.parameterManager(); 129 130 var uploadType = Html.input('hidden', {name: 'uploadType'}); 131 var selectorLink = new TypeSelector(pm, self.types); 132 var selectorL = selectorLink.draw(); 133 var url = Html.edit({name: 'url'}); 134 var description = Html.textarea({name: 'description'}); 135 var statusSelection = Html.input('hidden', {name: 'statusSelection'}); 136 var visibility = Html.input('hidden', {name: 'visibility'}); 137 var password = Html.input('hidden', {name: 'password'}); 138 var userList = Html.input('hidden', {name: 'userList'}); 139 140 uploadType.set('link'); 141 142 //pm.add(selectorL, 'text', false); 143 pm.add(url, 'text', false); 144 pm.add(description, 'text', true); 145 146 //make request and save it 147 this._makeProtectionRequest(self.args.materialIdsList.get(selectorLink.getSelectBox().get())); 148 149 selectorLink.getSelectBox().observe(function(value){ 150 //make request and save it 151 self._makeProtectionRequest(self.args.materialIdsList.get(value)); 152 } 153 ) 154 155 return Html.div({}, 156 IndicoUtil.createFormFromMap( 157 [ 158 [$T('Type'),selectorL], 159 [$T('URL'), url], 160 [$T('Description'), description] 161 ]), 162 uploadType, 163 statusSelection, 164 visibility, 165 password, 166 userList, 167 Html.div({style: {'textAlign': 'center'}}, 168 Widget.button(command( 169 function() { 170 if (pm.check()) { 171 self.killProgress = IndicoUI.Dialogs.Util.progress(); 172 self.uploading = true; 173 174 userList.set(Json.write(self.userList.getUsers())); 175 statusSelection.set(self.protectionLabel.get('statusSelection').get()); 176 visibility.set(self.protectionLabel.get('visibility')); 177 password.set(self.protectionLabel.get('password')); 178 self.form.dom.submit(); 179 180 //if we are adding a custom type and it's not in the list already, then we add it 181 if(!selectorLink.isSelect() && !contains(self.types, selectorLink.get())){ 182 self.customTypes.append(selectorLink.get()); 183 } 184 } 185 }, $T("Upload"))))); 186 }, 293 protectionPane); 294 295 }, 296 297 _upload: function() { 298 299 var check = this.pm.check(); 300 301 if (check) { 302 this.killProgress = IndicoUI.Dialogs.Util.progress(); 303 304 this.uploading = true; 305 306 this.formDict.userList.set(Json.write(this.userList.getUsers())); 307 308 this.formDict.statusSelection.set(this.protectionStatus.get('statusSelection')); 309 310 this.formDict.visibility.set(this.protectionStatus.get('visibility')); 311 this.formDict.password.set(this.protectionStatus.get('password')); 312 this.formDict.uploadType.set(this.uploadType.get()); 313 314 // depending on whether we are selecting a material from the list 315 // or adding a new one, we'll send either an id or a name 316 317 this.formDict.materialId.set(this.typeSelector.get()); 318 319 this.form.dom.submit(); 320 321 } 322 }, 323 187 324 188 325 _drawWidget: function() { 189 326 var self = this; 190 327 328 this.formDict = {}; 191 329 this.frameId = Html.generateId(); 192 330 … … 203 341 this.tabWidget.draw()); 204 342 343 each(['statusSelection', 'visibility', 'password', 'userList', 'uploadType', 'materialId'], 344 function(fieldName) { 345 var elem = Html.input('hidden', {name: fieldName}); 346 self.formDict[fieldName] = elem; 347 self.form.append(elem); 348 }); 349 205 350 var loadFunc = function() { 206 351 if (self.uploading) { … … 213 358 214 359 if (Browser.IE) { 215 // cof! cof!216 360 iframe.dom.onreadystatechange = loadFunc; 217 361 } else { … … 224 368 }); 225 369 226 return Html.div({}, this.form, iframe); 227 228 }, 229 230 draw: function() { 231 var self = this; 232 233 self.newMaterial = $O(); 234 235 var visibility = Html.select( 236 {}, 237 Html.option({value: 0},$T('Visible for unauth. users')), 238 Html.option({value: 1},$T('Hidden from unauth. users')) 239 ); 240 241 var password = Html.input('password',{}); 242 243 self.userList = new UserListField('ShortPeopleListDiv', 370 return Html.div({}, 371 this.form, 372 iframe); 373 374 }, 375 376 postDraw: function() { 377 378 var selection = "slides"; 379 380 // We're not sure that the type "Slides" 381 // will have a "standard" id 382 for (i in this.types) { 383 if (this.types[i][1] == "Slides") { 384 selection = this.types[i][0]; 385 } 386 } 387 388 this.typeSelector.set(selection); 389 this.ButtonBarExclusivePopup.prototype.postDraw.call(this); 390 }, 391 392 _drawProtectionDiv: function() { 393 this.visibility = new RadioFieldWidget([ 394 [0, Html.span({}, $T("This resource is visible to everyone"))], 395 [1, $T("Only people who can access the resource can see it")]]); 396 397 this.password = Html.input('password',{}); 398 399 this.userList = new UserListField('ShortPeopleListDiv', 244 400 'PluginPeopleList', 245 self.allowedUsers,401 this.allowedUsers, 246 402 null, 247 403 null, … … 249 405 userListNothing, userListNothing, userListNothing, true); 250 406 251 self.privateInfoDiv = Html.div( 252 {style:{padding:pixels(2)}}, 253 Html.div({}, 254 Html.label({}, $T('Allowed users')), 255 self.userList.draw()), 256 Html.div({style:{marginTop: pixels(8)}}, 257 Html.label({}, $T('Visibility: ')), 258 visibility), 259 Html.div({style:{marginTop: pixels(5)}}, 260 Html.label({}, $T('Access Key: ')), 261 password) 262 ); 263 264 var statusSelection = Widget.select( 265 $L({ 266 0:(self.args.parentProtected?$T('Private'):$T('Public'))+' '+$T('(from parent)'), 267 1:$T('Private (by itself)'), 268 '-1':$T('Public (by itself)') 269 }) 270 ); 271 272 self.protectionLabel.accessor("statusSelection").observe(function(value) { 273 if (value.get() == 0 && self.args.parentProtected || value.get() == 1) { 274 self.privateInfoDiv.show(); 275 } 276 else { 277 self.privateInfoDiv.hide(); 278 } 279 }); 280 281 $B(statusSelection, self.protectionLabel.accessor("statusSelection")); 282 $B(self.protectionLabel.accessor("visibility"), visibility); 283 $B(self.protectionLabel.accessor("password"), password); 284 285 286 if ( !self.args.parentProtected) 287 self.privateInfoDiv.hide(); 288 289 var protectionDiv = Html.div( 290 {style: {marginTop: pixels(5)}}, 291 Html.div({}, 292 Html.label({},$T("Status: ")), 293 statusSelection 294 ), 295 self.privateInfoDiv); 296 297 this.tabWidget = new TabWidget([[$T('Upload File'), this._drawFileUpload()], 298 [$T('Add Link'), this._drawLinkUpload()], 299 [$T("Protection") , protectionDiv]], 407 // Bind fields to data structure 408 $B(this.protectionStatus.accessor('visibility'), this.visibility); 409 $B(this.protectionStatus.accessor('password'), this.password); 410 411 this.visibility.set(0); 412 this.password.set(''); 413 414 var privateInfoDiv = IndicoUtil.createFormFromMap( 415 [ 416 [ 417 $T('Allowed users and groups'), 418 this.userList.draw() 419 ], 420 [ 421 $T('Visibility'), 422 this.visibility.draw() 423 ], 424 [ 425 $T('Access key'), 426 this.password 427 ] 428 ]); 429 430 return privateInfoDiv; 431 }, 432 433 draw: function() { 434 var self = this; 435 436 self.newMaterial = $O(); 437 438 var protectionDiv = this._drawProtectionDiv(); 439 440 this.tabWidget = new TabWidget([[$T('Upload'), this._drawUpload()], 441 [$T("Protection"), protectionDiv]], 300 442 400, 300); 301 443 302 return this. ExclusivePopup.prototype.draw.call(this,444 return this.ButtonBarExclusivePopup.prototype.draw.call(this, 303 445 this._drawWidget()); 304 }, 305 306 307 }, function(args, list, types, customTypes, uploadAction, onUpload) { 446 } 447 448 449 }, function(args, list, types, uploadAction, onUpload) { 450 308 451 var self = this; 309 452 this.list = list; 310 this.customTypes = customTypes; 311 this.types = $L(concat(types, customTypes.allItems())); 453 this.types = types; 312 454 this.uploadAction = uploadAction; 313 455 this.uploading = false; … … 317 459 // this.args.materialId = material; 318 460 319 this.protectionLabel = $O(); 320 321 this.ExclusivePopup($T("Upload Material"), 461 this.protectionStatus = $O(); 462 this.uploadType = new WatchValue(); 463 464 this.ButtonBarExclusivePopup($T("Upload Material"), 322 465 function() { 323 466 self.close(); … … 345 488 params.materialInfo = this.newMaterial; 346 489 this.newMaterial.set('userList', this.userList.getUsers()); 490 491 // get a list of material titles 492 var matTitles = translate(this.list, 493 function(mat){ 494 return mat.get('title'); 495 }); 496 497 // look for one with the same name 498 var i = -1; 499 for (var j in matTitles) { 500 if (matTitles[i] == params.materialInfo.get('title')) { 501 i = j; 502 } 503 } 504 505 if (i < 0) { 506 this.types.push([params.materialInfo.get('id'), params.materialInfo.get('title')]); 507 } 508 347 509 this.request(params); 348 349 if(this.customTypes.indexOf(this.material.title.get()) != null){350 //it was in the custom types list, so we just change its name351 this.customTypes.remove(this.material.title.get());352 this.customTypes.append(params.materialInfo.get('title'));353 }354 else{355 //it was a predefined material, so we add the new one356 this.customTypes.append(params.materialInfo.get('title'));357 }358 510 }, 359 511 … … 377 529 378 530 statusSelection.observe(function(value) { 379 if (value == =0 && self.material.get('protectedOwner') ||531 if (value == 0 && self.material.get('protectedOwner') || 380 532 value == 1) { 381 533 self.privateInfoDiv.show(); … … 414 566 self.newMaterial.accessor('accessKey'))) 415 567 ); 416 if ( !self.material.get('protectedOwner')) 568 if ( !self.material.get('protectedOwner')) { 417 569 self.privateInfoDiv.hide(); 570 } 418 571 419 572 var protectionDiv = Html.div( … … 430 583 var description = Html.textarea({name:'description',style: {width: '250px'}}); 431 584 var descDiv = Widget.block([Widget.block(Html.label({},"Description: ")),description]); 585 432 586 var buttonDiv = Widget.block([ 433 587 Widget.button(command(function() { … … 442 596 $B(description, self.newMaterial.accessor('description')); 443 597 598 statusSelection.notifyObservers(); 599 444 600 var tabControl = new TabWidget([ 445 601 [$T("Information"), Widget.block([titleDiv,descDiv])], 446 [$T("Protection") , protectionDiv]], 300,300 , 0);602 [$T("Protection") , protectionDiv]], 300,300); 447 603 448 604 return this.ExclusivePopup.prototype.draw.call( … … 454 610 }, 455 611 456 function(args, material, list, customTypes, title) {612 function(args, types, material, list, title) { 457 613 this.material = material; 458 614 this.materialId = this.material.get('id'); 615 this.types = types; 459 616 this.list = list; 460 this.customTypes = customTypes;461 617 462 618 args = clone(args); … … 553 709 ); 554 710 555 statusSelection.observe(function(value) { 556 if (value == 0 && isFatherProtected || value == 1) { 557 self.privateInfoDiv.show(); 558 } 559 else { 560 self.privateInfoDiv.hide(); 561 } 562 }); 711 statusSelection.observe(function(value) { 712 713 if (value == 0 && isFatherProtected || value == 1) { 714 self.privateInfoDiv.show(); 715 } 716 else { 717 self.privateInfoDiv.hide(); 718 } 719 }); 563 720 564 721 self.privateInfoDiv = Html.div( … … 567 724 Html.label({}, $T('Allowed users')), 568 725 self.userList.draw())); 569 if ( !isFatherProtected) 726 727 if ( !isFatherProtected) { 570 728 self.privateInfoDiv.hide(); 571 729 } 572 730 573 731 var protectionDiv = Html.div( … … 580 738 var tabControl = new TabWidget([ 581 739 [$T("Information"), Widget.block([nameDiv,this.resource.type=='stored'?[]:urlDiv,descDiv])], 582 [$T("Protection") , protectionDiv]], 300,200 , 0);740 [$T("Protection") , protectionDiv]], 300,200); 583 741 tabControl.options = $L([$T("Information"), $T("Protection")]); 584 742 tabControl.selected.set($T("Information")); 743 744 statusSelection.notifyObservers(); 745 585 746 586 747 return this.ExclusivePopup.prototype.draw.call( … … 686 847 self.set(resourceId, null); 687 848 //if it's in the custom material list and it's the last resource in it, we delete it 688 self.customTypes.remove(self.materialName);689 849 killProgress(); 690 850 } … … 763 923 } 764 924 765 }, function(resources, matParams, customTypes,materialTitle) {925 }, function(resources, matParams, materialTitle) { 766 926 this.matParams = matParams; 767 927 this.resources = resources; 768 this.customTypes = customTypes;769 928 this.materialName = materialTitle; 770 929 this.ListWidget(); … … 819 978 self.set(materialId, null); 820 979 //if it's in the custom material list, we delete it 821 self.customTypes.remove(material.get('title'));822 980 killProgress(); 823 981 } … … 846 1004 IndicoUI.Dialogs.Material.editMaterial( 847 1005 self.args, 1006 self.types, 848 1007 material, 849 self.customTypes,850 1008 self); 851 1009 }, … … 870 1028 } 871 1029 872 args ['materialProtection']= material.get('protection');873 var matWidget = new ResourceListWidget(material.get('resources'), args, self.customTypes,material.get('title'));1030 args.materialProtection = material.get('protection'); 1031 var matWidget = new ResourceListWidget(material.get('resources'), args, material.get('title')); 874 1032 875 1033 // check whenever a material gets empty (no resources) and delete it … … 937 1095 }, 938 1096 1097 _updateMaterialList: function(material) { 1098 // add type to custom list, if not there 1099 var i = -1; 1100 1101 for (var j in this.types) { 1102 if (this.types[i][1] == material.get('title')) { 1103 i = j; 1104 break; 1105 } 1106 } 1107 1108 var newElement = [material.get('id'), material.get('title')]; 1109 1110 if (i >= 0) { 1111 this.types[i] = newElement; 1112 } else { 1113 this.types.push(newElement); 1114 } 1115 }, 1116 939 1117 _loadMaterial: function(id) { 940 1118 var self = this; … … 946 1124 947 1125 source.state.observe(function(state) { 1126 948 1127 if (state == SourceState.Loaded) { 949 1128 var material = $O($O(source).getAll()); … … 954 1133 material); 955 1134 1135 self._updateMaterialList(material); 956 1136 957 1137 } … … 968 1148 }); 969 1149 1150 var materialLoadFunction = function(info) { 1151 if (self.get(info.material)) { 1152 self.get(info.material).get('resources').append(watchize(info)); 1153 } else { 1154 self._loadMaterial(info.material); 1155 } 1156 }; 1157 970 1158 var link = Widget.link(command(function(){ 971 1159 … … 973 1161 self, 974 1162 self.types, 975 self.customTypes,976 1163 self.uploadAction, 977 function(info) { 978 if (self.get(info.material)) { 979 self.get(info.material).get('resources').append(watchize(info)); 980 } else { 981 self._loadMaterial(info.material); 982 } 983 }); 1164 materialLoadFunction); 984 1165 }, $T("Add Material"))); 985 1166 return Html.div( … … 992 1173 }, 993 1174 994 function(args, types, customTypes,uploadAction, width, height) {1175 function(args, types, uploadAction, width, height) { 995 1176 var self = this; 996 1177 this.width = width; … … 998 1179 this.args = args; 999 1180 this.types = types; 1000 this.customTypes = customTypes;1001 1181 this.uploadAction = uploadAction; 1002 1182 this.ListWidget("materialList"); … … 1007 1187 ); 1008 1188 1009 type("MaterialEditorDialog", ["ExclusivePopup"], { 1189 type("MaterialEditorDialog", ["ButtonBarExclusivePopup"], { 1190 1191 _drawButtons: function() { 1192 1193 var self = this; 1194 var buttonDiv = Html.div({}, 1195 Widget.button(command(function() { 1196 self.close(); 1197 window.location.reload(true); 1198 }, $T("Close")))); 1199 1200 return buttonDiv; 1201 }, 1202 1203 1010 1204 draw: function() { 1011 1205 var self = this; … … 1017 1211 'sessionId': intToStr(this.sessId), 1018 1212 'contribId': intToStr(this.contId), 1019 'subContId': intToStr(this.subContId) 1213 'subContId': intToStr(this.subContId), 1214 'parentProtected': this.parentProtected 1020 1215 }; 1021 1216 … … 1027 1222 }); 1028 1223 1029 var mlist = new MaterialListWidget(args, this.types, this. customTypes, this.uploadAction, this.width, this.height);1030 1031 return this. ExclusivePopup.prototype.draw.call(1224 var mlist = new MaterialListWidget(args, this.types, this.uploadAction, this.width, this.height); 1225 1226 return this.ButtonBarExclusivePopup.prototype.draw.call( 1032 1227 this, 1033 1228 Html.div({style: {width: pixels(this.width), 1034 1229 height: pixels(this.height+50)}}, 1035 mlist.draw(), 1036 Widget.button(command(function() { 1037 self.close(); 1038 window.location.reload(true); 1039 }, $T("Close"))))); 1230 mlist.draw())); 1040 1231 } 1041 1232 }, 1042 1233 1043 function(confId, sessId, contId, subContId, types, uploadAction, title, width, height, refresh, customTypes) {1234 function(confId, sessId, contId, subContId, parentProtected, types, uploadAction, title, width, height, refresh) { 1044 1235 this.confId = confId; 1045 1236 this.sessId = sessId; … … 1047 1238 this.subContId = subContId; 1048 1239 this.types = types; 1049 this.customTypes = customTypes;1050 1240 this.uploadAction = uploadAction; 1051 1241 this.width = width; 1052 1242 this.height = height; 1053 1243 this.refresh = refresh; 1054 this.ExclusivePopup(title); 1244 this.parentProtected = parentProtected; 1245 this.ButtonBarExclusivePopup(title); 1055 1246 }); 1056 1247 1057 1248 IndicoUI.Dialogs.Material = { 1058 1249 1059 add: function(args, list, types, customTypes,uploadAction, onUpload) {1060 var dialog = new AddMaterialDialog(args, list, types, customTypes,uploadAction, onUpload);1250 add: function(args, list, types, uploadAction, onUpload) { 1251 var dialog = new AddMaterialDialog(args, list, types, uploadAction, onUpload); 1061 1252 dialog.open(); 1062 1253 }, 1063 editMaterial: function(args, material, customTypes, list) {1064 var dialog = new EditMaterialDialog(args, material, list, customTypes, $T("Edit Material"));1254 editMaterial: function(args, types, material, list) { 1255 var dialog = new EditMaterialDialog(args, types, material, list, $T("Edit Material")); 1065 1256 dialog.execute(); 1066 1257 }, … … 1071 1262 }, 1072 1263 1073 editor: function(confId, sessId, contId, subContId, types, uploadAction, refresh, customTypes) {1074 var dialog = new MaterialEditorDialog(confId, sessId, contId, subContId, types, uploadAction, $T("Edit Materials"), 400, 300, refresh, customTypes);1264 editor: function(confId, sessId, contId, subContId, parentProtected, types, uploadAction, refresh) { 1265 var dialog = new MaterialEditorDialog(confId, sessId, contId, subContId, parentProtected, types, uploadAction, $T("Edit Materials"), 400, 300, refresh); 1075 1266 dialog.open(); 1076 1267 } -
indico/htdocs/js/indico/Timetable/Base.js
r68f9a3 r64729b 300 300 301 301 _followArgs_interval: function(hash, data) { 302 302 303 var m = hash.match(/#(\d{8})(?:\.(s\d+l\d+))?/); 303 304 304 305 if (m) { 305 306 this.currentDay = m[1];307 306 308 307 if (m[2]) { … … 319 318 var m = hash.match(/#(\d{8}|all)(?:\.(s\d+l\d+))?/); 320 319 321 if (m) { 322 323 this.currentDay = m[1]; 324 325 var tab = 0; 326 327 for (k in this.sortedKeys) { 328 if (this.sortedKeys[k] == this.currentDay) { 329 return tab; 330 } 331 tab++; 332 } 333 return -1; 334 } 320 var currentDay = m ? m[1] : null; 321 322 return exists(data[currentDay]) ? currentDay : null; 335 323 }, 336 324 … … 364 352 switchToTopLevel : function() { 365 353 this.enable(); 366 this.set (this.currentDay);367 this. canvas.set(Widget.block(this));354 this.setSelectedTab(this.currentDay); 355 this._drawContent(); 368 356 this.menu.dom.style.display = 'block'; 369 357 this.timetableDrawer.redraw(); … … 396 384 var todayStr = IndicoUtil.formatDate2(today); 397 385 386 var originalHash = window.location.hash; 387 398 388 // parse "command line" arguments 399 var initialTab = this._followArgs_day( window.location.hash, data);389 var initialTab = this._followArgs_day(originalHash, data); 400 390 401 391 // if nothing is found 402 if (initialTab == -1) {392 if (initialTab === null) { 403 393 // look for today 404 while (exists(data[todayStr])) { 405 today.setDate(today.getDate()-1); 406 todayStr = IndicoUtil.formatDate2(today); 407 initialTab++; 394 if (exists(data[todayStr])) { 395 initialTab = todayStr; 396 } else { 397 // otherwise use the default 398 initialTab = keys(data)[0]; 408 399 } 409 400 } 410 401 411 // if today not found, set initial tab to the first one 412 if (initialTab == -1) { 413 initialTab = 0; 414 } 402 this.currentDay = initialTab; 415 403 416 404 this.LookupTabWidget( translate(this.sortedKeys, function(key) { 405 417 406 return [key, function() { 418 407 self.currentDay = key; … … 437 426 }), this.width, 100, initialTab, this._functionButtons(), this.canvas); 438 427 439 this._followArgs_interval( window.location.hash, data);428 this._followArgs_interval(originalHash, data); 440 429 441 430 }); … … 715 704 716 705 _retrieveHistoryState: function(hash) { 717 this._followArgs_day(hash, this.data);718 this.setSelectedTab( this.currentDay);706 var currentDay = this._followArgs_day(hash, this.data); 707 this.setSelectedTab(currentDay); 719 708 } 720 709 … … 861 850 862 851 _retrieveHistoryState: function(hash) { 863 this._followArgs_day(hash, this.data);852 var currentDay = this._followArgs_day(hash, this.data) || keys(this.data)[0]; 864 853 if (!this._followArgs_interval(hash, this.data)) { 865 854 this.switchToTopLevel(); 866 this.setSelectedTab( this.currentDay);855 this.setSelectedTab(currentDay); 867 856 } 868 857 }
Note: See TracChangeset
for help on using the changeset viewer.
