ldx-widgets
Version:
widgets
181 lines (140 loc) • 4.49 kB
text/coffeescript
React = require 'react'
_ = require 'lodash'
{Flux} = require 'delorean'
PvrInfoItem = require './pvr_info_item'
animationMixin = require '../mixins/animation_mixin'
{div} = React.DOM
###
Popover Props
@props.items
array of objects containing at minimum a label and value attribute
optionally a subLabel property can be passed
@props.height
height of the pvr, 'auto' and it will grow to size of list
@props.width
width of the pvr
@props.styleMixin
object containing any style properties to mixin with and/or overrride the defaults
note that width height are passed separately so they can have defaults and auto settings
passing widt/height in this object could cause issues
@props.optionHeight
the height of each item row
@props.element
pass e.currentTarget element through to enable auto-positioning
if this isn't passed, you'll have to manually configure positioning with styleMixin or CSS
@props.offsetTop
set a value to add to the auto-calculated top value for custom positioning
@props.offsetLeft
set a value to add to the auto-calculated left value for custom positioning
@props.headerTitle
optional title String for popover header
###
PvrInfoList = React.createClass
displayName: 'PvrInfoList'
mixins: [animationMixin, Flux.mixins.storeListener]
watchStores: ['popoverModal']
enterStateStart:
scale: .9
enterStateEnd:
scale: 1
enterEasing: 'easeOutElastic'
enterDuration: 600
getDefaultProps: ->
{
items: []
height: 'auto'
width: 250
styleMixin: {}
itemHeight: 30
position: 'bottom'
offsetTop: 0
offsetLeft: 0
showNib: yes
}
componentWillMount: ->
window.addEventListener("resize", @updateDimensions)
componentWillUnmount: ->
window.removeEventListener("resize", @updateDimensions)
updateDimensions: ->
@forceUpdate()
render: ->
{width, height, styleMixin, items, itemHeight, position, element, offsetTop, offsetLeft, headerTitle, showNib} = @props
{scale} = @state
@hasHeader = headerTitle?
if items?
height = items.length * itemHeight + (items.length - 1) if height is 'auto'
if @hasHeader
height += 34
elPos = if element then element.getBoundingClientRect() else {}
# Set the styles
style =
height: height + 20
width: width
top: (elPos.top or 0) + offsetTop
left: (elPos.left or 0) + offsetLeft
transform: "scale(#{scale})"
WebkitTransform: "scale(#{scale})"
msTransform: "scale(#{scale})"
# Handle the auto-positioning based on the element's screen position
if element
left = (->
if width < element.clientWidth then (element.clientWidth - width) / 2
else if width > element.clientWidth then -((width / 2) - (element.clientWidth / 2))
else 0
)()
# Adjust the position if it is off-screen
calcLeft = elPos.left + offsetLeft
if width + calcLeft > window.outerWidth
leftAdjust = window.outerWidth - (width + calcLeft)
style.left += leftAdjust
if calcLeft < 0
leftAdjust = calcLeft
style.left = 8
# Adjust the position of the nib to account for the offscreen adjustment
nibLeft = (element.clientWidth / 2) + Math.abs(leftAdjust)
# Change the position of the popover
switch position
when 'bottom'
style.top += element.clientHeight + 5
style.left += left
_.assign style, styleMixin
itemRows = []
if items?
for item in items
itemRows.push PvrInfoItem {
hasSubLabel: item.subLabel?
item: item
itemHeight: itemHeight
key: item.key
}
if itemRows.length is 0
itemRows = div {className: 'no-items'}, t 'No information to display'
nibClass = "nib"
if @hasHeader
nibClass += " headerNib"
div {
className: "plain-pvr #{position}"
style: style
}, [
div {
key: 'nib'
className: nibClass
style:
left: nibLeft or '50%'
} if showNib
div {
key: 'inner'
className: 'inner'
}, [
if @hasHeader
div {
key: 'header'
className: 'header plain-pvr-content-item'
}, headerTitle
div {
key: 'inner-rows'
className: 'inner-rows'
}, itemRows
]
]
module.exports = PvrInfoList