framework7-vue
Version:
Build full featured iOS & Android apps using Framework7 & Vue
489 lines (432 loc) • 14.1 kB
JavaScript
import Utils from '../utils/utils';
import F7ListItemContent from './list-item-content';
import Mixins from '../utils/mixins';
import __vueComponentTransformJSXProps from '../runtime-helpers/vue-component-transform-jsx-props.js';
import __vueComponentSetState from '../runtime-helpers/vue-component-set-state.js';
import __vueComponentDispatchEvent from '../runtime-helpers/vue-component-dispatch-event.js';
import __vueComponentProps from '../runtime-helpers/vue-component-props.js';
export default {
name: 'f7-list-item',
props: Object.assign({
id: [String, Number],
title: [String, Number],
text: [String, Number],
media: String,
subtitle: [String, Number],
header: [String, Number],
footer: [String, Number],
link: [Boolean, String],
target: String,
noFastclick: Boolean,
noFastClick: Boolean,
after: [String, Number],
badge: [String, Number],
badgeColor: String,
mediaItem: Boolean,
mediaList: Boolean,
divider: Boolean,
groupTitle: Boolean,
swipeout: Boolean,
swipeoutOpened: Boolean,
sortable: Boolean,
accordionItem: Boolean,
accordionItemOpened: Boolean,
smartSelect: Boolean,
smartSelectParams: Object,
noChevron: Boolean,
chevronCenter: Boolean,
checkbox: Boolean,
radio: Boolean,
checked: Boolean,
defaultChecked: Boolean,
name: String,
value: [String, Number, Array],
readonly: Boolean,
required: Boolean,
disabled: Boolean,
virtualListIndex: Number
}, Mixins.colorProps, Mixins.linkRouterProps, Mixins.linkActionsProps),
data() {
const props = __vueComponentProps(this);
const state = (() => {
return {
isMedia: props.mediaItem || props.mediaList,
isSortable: props.sortable,
isSimple: false
};
})();
return {
state
};
},
render() {
const _h = this.$createElement;
const self = this;
let linkEl;
let itemContentEl;
const props = self.props;
const {
id,
style,
className,
title,
text,
media,
subtitle,
header,
footer,
link,
href,
target,
noFastclick,
noFastClick,
after,
badge,
badgeColor,
mediaItem,
mediaList,
divider,
groupTitle,
swipeout,
accordionItem,
accordionItemOpened,
smartSelect,
checkbox,
radio,
checked,
defaultChecked,
name,
value,
readonly,
required,
disabled,
sortable,
noChevron,
chevronCenter,
virtualListIndex
} = props;
const isMedia = mediaItem || mediaList || self.state.isMedia;
const isSortable = sortable || self.state.isSortable;
const isSimple = self.state.isSimple;
if (!isSimple) {
const needsEvents = !(link || href || accordionItem || smartSelect);
itemContentEl = _h(F7ListItemContent, {
on: needsEvents ? {
click: self.onClick,
change: self.onChange
} : undefined,
attrs: {
title: title,
text: text,
media: media,
subtitle: subtitle,
after: after,
header: header,
footer: footer,
badge: badge,
badgeColor: badgeColor,
mediaList: isMedia,
accordionItem: accordionItem,
checkbox: checkbox,
checked: checked,
defaultChecked: defaultChecked,
radio: radio,
name: name,
value: value,
readonly: readonly,
required: required,
disabled: disabled
}
}, [this.$slots['content-start'], this.$slots['content'], this.$slots['content-end'], this.$slots['media'], this.$slots['inner-start'], this.$slots['inner'], this.$slots['inner-end'], this.$slots['after-start'], this.$slots['after'], this.$slots['after-end'], this.$slots['header'], this.$slots['footer'], this.$slots['before-title'], this.$slots['title'], this.$slots['after-title'], this.$slots['subtitle'], this.$slots['text'], swipeout || accordionItem ? null : self.$slots.default]);
if (link || href || accordionItem || smartSelect) {
const linkAttrs = Utils.extend({
href: link === true || accordionItem || smartSelect ? '#' : link || href,
target
}, Mixins.linkRouterAttrs(props), Mixins.linkActionsAttrs(props));
const linkClasses = Utils.classNames({
'item-link': true,
'no-fastclick': noFastclick || noFastClick,
'smart-select': smartSelect
}, Mixins.linkRouterClasses(props), Mixins.linkActionsClasses(props));
linkEl = _h('a', __vueComponentTransformJSXProps(Object.assign({
ref: 'linkEl',
class: linkClasses
}, linkAttrs)), [itemContentEl]);
}
}
const liClasses = Utils.classNames(className, {
'item-divider': divider,
'list-group-title': groupTitle,
'media-item': isMedia,
swipeout,
'accordion-item': accordionItem,
'accordion-item-opened': accordionItemOpened,
disabled: disabled && !(radio || checkbox),
'no-chevron': noChevron,
'chevron-center': chevronCenter
}, Mixins.colorClasses(props));
if (divider || groupTitle) {
return _h('li', {
ref: 'el',
style: style,
class: liClasses,
attrs: {
id: id,
'data-virtual-list-index': virtualListIndex
}
}, [_h('span', [this.$slots['default'] || [title]])]);
}
if (isSimple) {
return _h('li', {
ref: 'el',
style: style,
class: liClasses,
attrs: {
id: id,
'data-virtual-list-index': virtualListIndex
}
}, [title, this.$slots['default']]);
}
const linkItemEl = link || href || smartSelect || accordionItem ? linkEl : itemContentEl;
return _h('li', {
ref: 'el',
style: style,
class: liClasses,
attrs: {
id: id,
'data-virtual-list-index': virtualListIndex
}
}, [this.$slots['root-start'], swipeout ? _h('div', {
class: 'swipeout-content'
}, [linkItemEl]) : linkItemEl, isSortable && _h('div', {
class: 'sortable-handler'
}), (swipeout || accordionItem) && self.$slots.default, this.$slots['root'], this.$slots['root-end']]);
},
watch: {
'props.swipeoutOpened': function watchSwipeoutOpened(opened) {
const self = this;
if (!self.props.swipeout) return;
const el = self.$refs.el;
if (opened) {
self.$f7.swipeout.open(el);
} else {
self.$f7.swipeout.close(el);
}
}
},
created() {
Utils.bindMethods(this, ['onClick', 'onChange', 'onSwipeoutOpen', 'onSwipeoutOpened', 'onSwipeoutClose', 'onSwipeoutClosed', 'onSwipeoutDelete', 'onSwipeoutDeleted', 'onSwipeoutOverswipeEnter', 'onSwipeoutOverswipeExit', 'onSwipeout', 'onAccBeforeOpen', 'onAccOpen', 'onAccOpened', 'onAccBeforeClose', 'onAccClose', 'onAccClosed']);
},
mounted() {
const self = this;
const {
el,
linkEl
} = self.$refs;
if (!el) return;
const {
link,
href,
smartSelect,
swipeout,
swipeoutOpened,
accordionItem,
smartSelectParams,
routeProps
} = self.props;
const needsEvents = !(link || href || accordionItem || smartSelect);
if (!needsEvents && linkEl) {
linkEl.addEventListener('click', self.onClick);
}
if (linkEl && routeProps) {
linkEl.f7RouteProps = routeProps;
}
self.$listEl = self.$$(el).parents('.list, .list-group').eq(0);
if (self.$listEl.length) {
self.setState({
isMedia: self.$listEl.hasClass('media-list'),
isSimple: self.$listEl.hasClass('simple-list'),
isSortable: self.$listEl.hasClass('sortable')
});
}
if (swipeout) {
el.addEventListener('swipeout:open', self.onSwipeoutOpen);
el.addEventListener('swipeout:opened', self.onSwipeoutOpened);
el.addEventListener('swipeout:close', self.onSwipeoutClose);
el.addEventListener('swipeout:closed', self.onSwipeoutClosed);
el.addEventListener('swipeout:delete', self.onSwipeoutDelete);
el.addEventListener('swipeout:deleted', self.onSwipeoutDeleted);
el.addEventListener('swipeout:overswipeenter', self.onSwipeoutOverswipeEnter);
el.addEventListener('swipeout:overswipeexit', self.onSwipeoutOverswipeExit);
el.addEventListener('swipeout', self.onSwipeout);
}
if (accordionItem) {
el.addEventListener('accordion:beforeopen', self.onAccBeforeOpen);
el.addEventListener('accordion:open', self.onAccOpen);
el.addEventListener('accordion:opened', self.onAccOpened);
el.addEventListener('accordion:beforeclose', self.onAccBeforeClose);
el.addEventListener('accordion:close', self.onAccClose);
el.addEventListener('accordion:closed', self.onAccClosed);
}
self.$f7ready(f7 => {
if (smartSelect) {
const ssParams = Utils.extend({
el: el.querySelector('a.smart-select')
}, smartSelectParams || {});
self.f7SmartSelect = f7.smartSelect.create(ssParams);
}
if (swipeoutOpened) {
f7.swipeout.open(el);
}
});
},
updated() {
const self = this;
const {
$listEl
} = self;
const {
linkEl
} = self.$refs;
const {
routeProps
} = self.props;
if (linkEl && routeProps) {
linkEl.f7RouteProps = routeProps;
}
if (!$listEl || $listEl && $listEl.length === 0) return;
const isMedia = $listEl.hasClass('media-list');
const isSimple = $listEl.hasClass('simple-list');
const isSortable = $listEl.hasClass('sortable');
if (isMedia !== self.state.isMedia) {
self.setState({
isMedia
});
}
if (isSimple !== self.state.isSimple) {
self.setState({
isSimple
});
}
if (isSortable !== self.state.isSortable) {
self.setState({
isSortable
});
}
},
beforeDestroy() {
const self = this;
const {
el,
linkEl
} = self.$refs;
const {
link,
href,
smartSelect,
swipeout,
accordionItem
} = self.props;
const needsEvents = !(link || href || accordionItem || smartSelect);
if (linkEl) {
if (!needsEvents) {
linkEl.removeEventListener('click', self.onClick);
}
delete linkEl.f7RouteProps;
}
if (el) {
if (swipeout) {
el.removeEventListener('swipeout:open', self.onSwipeoutOpen);
el.removeEventListener('swipeout:opened', self.onSwipeoutOpened);
el.removeEventListener('swipeout:close', self.onSwipeoutClose);
el.removeEventListener('swipeout:closed', self.onSwipeoutClosed);
el.removeEventListener('swipeout:delete', self.onSwipeoutDelete);
el.removeEventListener('swipeout:deleted', self.onSwipeoutDeleted);
el.removeEventListener('swipeout:overswipeenter', self.onSwipeoutOverswipeEnter);
el.removeEventListener('swipeout:overswipeexit', self.onSwipeoutOverswipeExit);
el.removeEventListener('swipeout', self.onSwipeout);
}
if (accordionItem) {
el.removeEventListener('accordion:beforeopen', self.onAccBeforeOpen);
el.removeEventListener('accordion:open', self.onAccOpen);
el.removeEventListener('accordion:opened', self.onAccOpened);
el.removeEventListener('accordion:beforeclose', self.onAccBeforeClose);
el.removeEventListener('accordion:close', self.onAccClose);
el.removeEventListener('accordion:closed', self.onAccClosed);
}
}
if (smartSelect && self.f7SmartSelect) {
self.f7SmartSelect.destroy();
}
},
methods: {
onClick(event) {
const self = this;
if (event.target.tagName.toLowerCase() !== 'input') {
self.dispatchEvent('click', event);
}
},
onSwipeoutOverswipeEnter(event) {
this.dispatchEvent('swipeout:overswipeenter swipeoutOverswipeEnter', event);
},
onSwipeoutOverswipeExit(event) {
this.dispatchEvent('swipeout:overswipeexit swipeoutOverswipeExit', event);
},
onSwipeoutDeleted(event) {
this.dispatchEvent('swipeout:deleted swipeoutDeleted', event);
},
onSwipeoutDelete(event) {
this.dispatchEvent('swipeout:delete swipeoutDelete', event);
},
onSwipeoutClose(event) {
this.dispatchEvent('swipeout:close swipeoutClose', event);
},
onSwipeoutClosed(event) {
this.dispatchEvent('swipeout:closed swipeoutClosed', event);
},
onSwipeoutOpen(event) {
this.dispatchEvent('swipeout:open swipeoutOpen', event);
},
onSwipeoutOpened(event) {
this.dispatchEvent('swipeout:opened swipeoutOpened', event);
},
onSwipeout(event) {
this.dispatchEvent('swipeout', event);
},
onAccBeforeClose(event) {
this.dispatchEvent('accordion:beforeclose accordionBeforeClose', event, event.detail.prevent);
},
onAccClose(event) {
this.dispatchEvent('accordion:close accordionClose', event);
},
onAccClosed(event) {
this.dispatchEvent('accordion:closed accordionClosed', event);
},
onAccBeforeOpen(event) {
this.dispatchEvent('accordion:beforeopen accordionBeforeOpen', event, event.detail.prevent);
},
onAccOpen(event) {
this.dispatchEvent('accordion:open accordionOpen', event);
},
onAccOpened(event) {
this.dispatchEvent('accordion:opened accordionOpened', event);
},
onChange(event) {
this.dispatchEvent('change', event);
},
onInput(event) {
this.dispatchEvent('input', event);
},
dispatchEvent(events, ...args) {
__vueComponentDispatchEvent(this, events, ...args);
},
setState(updater, callback) {
__vueComponentSetState(this, updater, callback);
}
},
computed: {
props() {
return __vueComponentProps(this);
}
}
};