有最喜欢的自定义Grails标记吗?
我一直在我的项目中使用标签。我在grails.org上浏览自定义标记,为我的库找到一些新标记 我想知道StackOverflow社区中的人是否有一个最喜欢的自定义标记,他们想分享。我有一个“fmt:relDate”标记,它可以给你类似Twitter的相对日期“3天前”、“不到30秒前”等,并以实时作为工具提示有最喜欢的自定义Grails标记吗?,grails,Grails,我一直在我的项目中使用标签。我在grails.org上浏览自定义标记,为我的库找到一些新标记 我想知道StackOverflow社区中的人是否有一个最喜欢的自定义标记,他们想分享。我有一个“fmt:relDate”标记,它可以给你类似Twitter的相对日期“3天前”、“不到30秒前”等,并以实时作为工具提示 当前的实现基本上是一个巨大的if/then语句链,具有我喜欢的边界。基于二进制搜索的算法会更好(从“更高效”的意义上讲),而当前的实现将我的个人偏好编码在其中,因此我不愿意共享标记。我有
当前的实现基本上是一个巨大的if/then语句链,具有我喜欢的边界。基于二进制搜索的算法会更好(从“更高效”的意义上讲),而当前的实现将我的个人偏好编码在其中,因此我不愿意共享标记。我有一个远程分页选项卡,可以帮助我通过ajax对结果进行分页。这是对默认选项卡的改进,并接受自定义参数 代码如下:
class CustomRemotePaginateTagLib {
static namespace = 'myTagLib'
/** * Creates next/previous links to support pagination for the current controller * * <g:paginate total="$ { Account.count() } " /> */
def remotePaginate = {attrs ->
def writer = out
if (attrs.total == null) throwTagError("Tag [remotePaginate] is missing required attribute [total]")
if (attrs.update == null) throwTagError("Tag [remotePaginate] is missing required attribute [update]")
def locale = RequestContextUtils.getLocale(request)
def total = attrs.total.toInteger()
def update = attrs.update
def action = (attrs.action ? attrs.action : (params.action ? params.action : "list"))
def controller = (attrs.controller ? attrs.controller : params.controller)
def offset = params.offset?.toInteger()
def max = params.max?.toInteger()
def maxsteps = (attrs.maxsteps ? attrs.maxsteps.toInteger() : 10)
if (!offset) offset = (attrs.offset ? attrs.offset.toInteger() : 0)
if (!max) max = (attrs.max ? attrs.max.toInteger() : 10)
def linkParams = [offset: offset - max, max: max]
if (params.sort) linkParams.sort = params.sort
if (params.order) linkParams.order = params.order
if (attrs.params) linkParams.putAll(attrs.params)
linkParams['action'] = action
linkParams['controller'] = controller
def linkTagAttrs = [url: "#"]
if (attrs.controller) { linkTagAttrs.controller = attrs.controller }
if (attrs.id != null) { linkTagAttrs.id = attrs.id }
// determine paging variables
def steps = maxsteps > 0
int currentstep = (offset / max) + 1
int firststep = 1
int laststep = Math.round(Math.ceil(total / max))
// display previous link when not on firststep
if (currentstep > firststep) {
linkTagAttrs.class = 'prevLink'
def prevOffset = linkParams.offset
def params = attrs.params ?: []
params.'offset' = prevOffset
linkTagAttrs.onclick = g.remoteFunction(update: update, action: linkParams.action, controller: linkParams.controller, params: params)
writer << link(linkTagAttrs.clone()) {
(attrs.prev ? attrs.prev : g.message(code: 'default.paginate.prev', default: 'Previous'))
}
}
// display steps when steps are enabled and laststep is not firststep
if (steps && laststep > firststep) {
linkTagAttrs.class = 'step'
// determine begin and endstep paging variables
int beginstep = currentstep - Math.round(maxsteps / 2) + (maxsteps % 2)
int endstep = currentstep + Math.round(maxsteps / 2) - 1
if (beginstep < firststep) {
beginstep = firststep
endstep = maxsteps
}
if (endstep > laststep) {
beginstep = laststep - maxsteps + 1
if (beginstep < firststep) {
beginstep = firststep
}
endstep = laststep
}
// display firststep link when beginstep is not firststep
if (beginstep > firststep) {
linkParams.offset = 0
def params = attrs.params ?: []
params['offset'] = linkParams.offset
linkTagAttrs.onclick = g.remoteFunction(update: update, action: linkParams.action, controller: linkParams.controller, params: params)
writer << link(linkTagAttrs.clone()) { firststep.toString() }
writer << '<span class="step">..</span>'
}
// display paginate steps
(beginstep..endstep).each {i ->
if (currentstep == i) {
writer << "<span class=\"currentStep\">${i}</span>"
} else {
linkParams.offset = (i - 1) * max
def params = attrs.params ?: []
params['offset'] = linkParams.offset
linkTagAttrs.onclick = g.remoteFunction(update: update, action: linkParams.action, controller: linkParams.controller, params: params)
writer << link(linkTagAttrs.clone()) { i.toString() }
}
}
// display laststep link when endstep is not laststep
if (endstep < laststep) {
writer << '<span class="step">..</span>'
linkParams.offset = (laststep - 1) * max
def params = attrs.params ?: []
params['offset'] = linkParams.offset
linkTagAttrs.onclick = g.remoteFunction(update: update, action: linkParams.action, controller: linkParams.controller, params: params)
writer << link(linkTagAttrs.clone()) { laststep.toString() }
}
}
// display next link when not on laststep
if (currentstep < laststep) {
linkTagAttrs.class = 'nextLink'
linkParams.offset = offset + max
def params = attrs.params ?: []
params['offset'] = linkParams.offset
linkTagAttrs.onclick = g.remoteFunction(update: update, action: linkParams.action, controller: linkParams.controller, params: params)
writer << link(linkTagAttrs.clone()) {
(attrs.next ? attrs.next : g.message(code: 'default.paginate.next', default: 'Next'))
}
}
}
类CustomRemotePaginateTagLib{
静态命名空间='myTagLib'
/***创建下一个/上一个链接以支持当前控制器的分页***/
def remotePaginate={attrs->
def writer=out
如果(attrs.total==null)throwTagError(“标记[remotePaginate]缺少必需的属性[total]”)
如果(attrs.update==null)throwTagError(“标记[remotePaginate]缺少必需的属性[update]”)
def locale=RequestContextUtils.getLocale(请求)
def total=attrs.total.toInteger()
def update=attrs.update
def action=(attrs.action?attrs.action:(params.action?params.action:“列表”))
def控制器=(attrs.controller?attrs.controller:params.controller)
def offset=参数offset?.toInteger()
def max=params.max?.toInteger()
def maxsteps=(attrs.maxsteps?attrs.maxsteps.toInteger():10)
如果(!offset)offset=(attrs.offset?attrs.offset.toInteger():0)
如果(!max)max=(attrs.max?attrs.max.toInteger():10)
def linkParams=[offset:offset-max,max:max]
if(params.sort)linkParams.sort=params.sort
if(params.order)linkParams.order=params.order
if(attrs.params)linkParams.putAll(attrs.params)
linkParams['action']=操作
linkParams['controller']=控制器
def linkTagAttrs=[url:#“]
如果(attrs.controller){linkTagAttrs.controller=attrs.controller}
如果(attrs.id!=null){linkTagAttrs.id=attrs.id}
//确定分页变量
def steps=maxsteps>0
int currentstep=(偏移量/最大值)+1
int firststep=1
int laststep=Math.round(Math.ceil(总计/最大))
//不在第一步时显示上一个链接
如果(当前步骤>第一步){
linkTagAttrs.class='prevLink'
def prevOffset=linkParams.offset
def params=attrs.params?:[]
参数'offset'=prevOffset
linkTagAttrs.onclick=g.remoteFunction(更新:更新,操作:linkParams.action,控制器:linkParams.controller,参数:params)
(第一步){
linkTagAttrs.class='step'
//确定开始和结束步骤分页变量
int beginstep=currentstep-Math.round(maxsteps/2)+(maxsteps%2)
int endstep=currentstep+Math.round(最大步长/2)-1
如果(开始步骤<第一步){
开始=第一步
endstep=maxsteps
}
如果(结束步骤>最后步骤){
beginstep=laststep-maxsteps+1
如果(开始步骤<第一步){
开始=第一步
}
结束步骤=最后一步
}
//当beginstep不是第一步时显示第一步链接
如果(开始步骤>第一步){
linkParams.offset=0
def params=attrs.params?:[]
params['offset']=linkParams.offset
linkTagAttrs.onclick=g.remoteFunction(更新:更新,操作:linkParams.action,控制器:linkParams.controller,参数:params)
作家
如果(currentstep==i){
writer我找到DecimalFormat类(以及Grails的formatNumber扩展标记)对于某些用例来说有点不透明,我仍然没有找到一种合理的方法来使用它进行一些非常基本的格式化,而不需要一些丑陋的预处理来生成适当的格式字符串。几个月前,我创建了一个简单的数字格式化标记,它基本上构造了一个格式字符串,并对该字符串进行了一些最小的处理数字本身
它不像我所希望的那样通用或优雅(这是我们当时所需要的一切——它是超基本的,但它仍然保留了GSP中一些丑陋的处理),但它应该易于阅读,并且显然可以在哪些方面进行细微的改进(即,如果elseif slop,使缩放迭代而不是简单,允许用户传入自定义缩放标记,允许自定义数字验证器作为参数等)
//将数字格式设置为3位有效数字,并附加适当的比例标记
//(k、m、b、t等)。定义var允许您使用字符串表示
//在标记体中任何需要的格式化编号,以及
//还提供比例(以防突出显示或其他特殊格式
//基于比例(需要)。
def formatNumberScaled={attrs,body->//数字,前缀,后缀,无效,变量
双号
字符串数字字符串
弦音阶
试一试{
number=attrs.number'.toDouble()
}捕获(例外e){
数字=Double.NaN
}
if(number.isNaN()| | number.isInfinite()){
numberString=scale=attrs.“无效”?:“不适用”
}否则{
布尔负=数字<0d
数字=负数?-数字:数字
如果(数量<1000d){
比例=“”
}否则如果(数量<10000000000d){
比例='k'
数量/=1000d
}否则如果(数量<1000000000d){
比例='m'
数量/=10000000000d
}否则如果(数量<10000000000d){
比例='b'
数量/=1000000000d
}否则,如果(数量<1000
// Formats a number to 3 significant digits, appending appropriate scale marker
// (k, m, b, t, etc.). Defining var allows you to use a string representation
// of the formatted number anywhere you need it within the tag body, and
// provides the scale as well (in case highlighting or other special formatting
// based upon scale is desired).
def formatNumberScaled = {attrs, body -> // number, prefix, suffix, invalid, var
Double number
String numberString
String scale
try {
number = attrs.'number'.toDouble()
} catch (Exception e) {
number = Double.NaN
}
if (number.isNaN() || number.isInfinite()) {
numberString = scale = attrs.'invalid' ?: "N/A"
} else {
Boolean negative = number < 0d
number = negative ? -number : number
if (number < 1000d) {
scale = ''
} else if (number < 1000000d) {
scale = 'k'
number /= 1000d
} else if (number < 1000000000d) {
scale = 'm'
number /= 1000000d
} else if (number < 1000000000000d) {
scale = 'b'
number /= 1000000000d
} else if (number < 1000000000000000d) {
scale = 't'
number /= 1000000000000d
}
String format
if (number < 10d) {
format = '#.00'
} else if (number < 100d) {
format = '##.0'
} else {
format = '###'
}
format = "'${attrs.'prefix' ?: ''}'${format}'${scale} ${attrs.'suffix' ?: ''}'"
numberString = g.formatNumber('number': negative ? -number : number, 'format': format)
}
// Now, either print the number or output the tag body with
// the appropriate variables set
if (attrs.'var') {
out << body((attrs.'var'): numberString, 'scale': scale)
} else {
out << numberString
}
}