//import org.apache.commons.validator.UrlValidator import org.codehaus.groovy.grails.validation.routines.UrlValidator import org.codehaus.groovy.grails.validation.routines.RegexValidator /** * General use custom tags. * Some are taken from http://www.grails.org/Contribute+a+Tag#checkBoxList */ class CustomTagLib { static namespace = 'custom' def resources = { attrs -> ///@todo: should include our javascript and do setup here. } /** * Checkbox list that can be used as a more user-friendly alternative to a multiselect list box. * Usage: * To map the selected ids to corresponding domain objects, * an additional set method is required in the containing domain class: * // This additional setter is used to convert the checkBoxList string or string array * // of ids selected to the corresponding domain objects. * public void setAssetSubItemsFromCheckBoxList(ids) { * def idList = [] * if(ids instanceof String) { * if(ids.isInteger()) * idList << ids.toInteger() * } * else { * ids.each() { * if(it.isInteger()) * idList << it.toInteger() * } * } * this.assetSubItems = idList.collect { AssetSubItem.get( it ) } * } * * Then a line in the controller: * assetInstance.setAssetSubItemsFromCheckBoxList(params.assetSubItems) * * Fields: * name - the property name. * from - the list to select from. * value - the current value. * optionKey - the key to use. * sortBy - (optional) the attribute to sort the from list by. * displayFields - (optional) defaults to the objects toString() * displayFieldsSeparator - (optional) defaults to a space. * linkController - (optional, requires linkAction.) the controller to use for a link to the objects in the checkBoxList. * linkAction - (optional, requires linkController.) the action to use for a link to the objects in the checkBoxList. * * Example: * * */ def checkBoxList = {attrs, body -> def from = attrs.from def value = attrs.value def cname = attrs.name def isChecked, ht, wd, style, html def sortBy = attrs.sortBy def displayFields = attrs.displayFields def displayFieldsSeparator = attrs.displayFieldsSeparator ?: ' ' def linkController = attrs.linkController def linkAction = attrs.linkAction def displayValue = " " // sets the style to override height and/or width if either of them // is specified, else the default from the CSS is taken style = "style='" if(attrs.height) style += "height:${attrs.height};" if(attrs.width) style += "width:${attrs.width};" if(style.length() == "style='".length()) style = "" else style += "'" // closing single quote html = "" } // checkBoxList def sortableColumnWithImg = { attrs, body -> def writer = out if(!attrs.property) throwTagError("Tag [sortableColumn] is missing required attribute [property]") // if(!attrs.title && !attrs.titleKey) // throwTagError("Tag [sortableColumn] is missing required attribute [title] or [titleKey]") def property = attrs.remove("property") def action = attrs.action ? attrs.remove("action") : (actionName ?: "list") def defaultOrder = attrs.remove("defaultOrder") if(defaultOrder != "desc") defaultOrder = "asc" // current sorting property and order def sort = params.sort def order = params.order // add sorting property and params to link params def linkParams = [:] if(params.id) linkParams.put("id",params.id) if(attrs.params) linkParams.putAll(attrs.remove("params")) linkParams.sort = property // determine and add sorting order for this column to link params attrs.class = (attrs.class ? "${attrs.class} sortable" : "sortable") if(property == sort) { attrs.class = attrs.class + " sorted " + order if(order == "asc") linkParams.order = "desc" else linkParams.order = "asc" } else linkParams.order = defaultOrder // determine column title // def title = attrs.remove("title") // def titleKey = attrs.remove("titleKey") // if(titleKey) { // if(!title) title = titleKey // def messageSource = grailsAttributes.getApplicationContext().getBean("messageSource") // def locale = RCU.getLocale(request) // // title = messageSource.getMessage(titleKey, null, title, locale) // } // Image. def img = " if(v) img += "${k}=\"${v.encodeAsHTML()}\" " } img += "/>" writer << " writer << "${k}=\"${v.encodeAsHTML()}\" " } writer << ">${link(action:action, params:linkParams) { img } }" writer << "" } // sortableColumnWithImg /** * Customised version of jasperButton as found in jaser plugin. * custom:jasperButtons is intended to be wrapped by g:jasperForm */ def jasperButtons = {attrs -> if(!attrs['format']){throw new Exception(message(code:"jasper.taglib.missingAttribute", args:'format'))} if(!attrs['jasper']){throw new Exception(message(code:"jasper.taglib.missingAttribute", args:'jasper'))} String jasper = attrs['jasper'] String buttonClass = attrs['class'] ?: "jasperButton" String format = attrs['format'].toUpperCase() String text = attrs['text'] String heightAttr = attrs['height'] ? ' height="' + attrs['height'] + '"' : '' // leading space on purpose String imgSrc = '' String delimiter = attrs['delimiter'] ?: "|" String delimiterBefore = attrs['delimiterBefore'] ?: delimiter String delimiterAfter = attrs['delimiterAfter'] ?: delimiter out << ''' ''' out << delimiterBefore attrs['format'].toUpperCase().split(",").eachWithIndex { it, i -> if (i > 0) out << delimiter imgSrc = g.resource(plugin:"jasper", dir:'images/icons', file:"${it.trim()}.gif") def fmt = it.trim() out << """ """ } out << delimiterAfter } // jasperButtons /** * Easily create a link from a hopeful url string. * If the supplied url is not considered a valid url the string is simply displayed. * * Fields: * url - String url to use. * body - If no body is supplied in the GSP then url.encodeAsHTML() is displayed. * * Example: * */ def easyUrl = {attrs, body -> def url = attrs.url def html body = body() if(!body) body = url.encodeAsHTML() html = "${body}" if(isURLValid(url)) { html = """ ${html} """ } out << html } /** * Get a list of the machines assigned on a taskProcedureRevision. * * Fields: * taskProcedureRevision - TaskProcedureRevision to use. * * Example: * */ def taskProcedureMachines = {attrs -> def taskProcedureRevision = attrs.taskProcedureRevision def machines = taskProcedureRevision.maintenanceActions.collect {it.assetSubItem.parentItem}.unique() out << machines.encodeAsHTML() } /** * Determine if a supplied string is considered a url or not. * The scheme/protocol can be adjusted, file:// has been excluded here. * A domainValidator regex is used to allow localhost domain. * A Grails branched version of commons.validator is used, this should * be compatible with the apache 1.4 version release. * See: http://jira.codehaus.org/browse/GRAILS-1692 for more on Grails url validation. */ private Boolean isURLValid(url) { def schemes = ["http","https", "ftp"] as String[] //def domainValidator = new RegexValidator("localhost(:(\\d{1,5}))?") def domainValidator = new RegexValidator(".*(:(\\d{1,5}))?") // Any domain, incl user@host:port def validator = new UrlValidator(schemes, domainValidator, UrlValidator.ALLOW_2_SLASHES) return validator.isValid(url) } } // end class