react-pinterest
Version:
Collection of embeddable Pinterest buttons and widgets
460 lines (395 loc) • 17.8 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _PinterestBase2 = require('./PinterestBase');
var _PinterestBase3 = _interopRequireDefault(_PinterestBase2);
var _PinterestAnchor = require('./PinterestAnchor');
var _PinterestAnchor2 = _interopRequireDefault(_PinterestAnchor);
var _PinConst = require('../util/PinConst');
var _i18n = require('../util/i18n');
var _i18n2 = _interopRequireDefault(_i18n);
var _PinUtil = require('../util/PinUtil');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
/**
* This is a Pinterest Pin widget.
*
* <PinterestPinWidget pin="356417757988637350" />
*
* @prop {string} pin - the id of the Pin to display
* @prop {string} size - enum of { small, medium, large }: default: small
* @prop {string} lang - language code for Pin: default: en
* @state {Object} pin - the remote Pin data
* @state {boolean} showingMenu - should we show the dropdown menu?
* @state {boolean} playingGIF - should the GIF be playing?
*/
var PinterestPinWidget = function (_PinterestBase) {
_inherits(PinterestPinWidget, _PinterestBase);
function PinterestPinWidget(props) {
_classCallCheck(this, PinterestPinWidget);
var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(PinterestPinWidget).call(this, props));
_this.logCount(_PinConst.COUNT_TYPES['PIN_' + props.size.toUpperCase()]);
_this.state = { pin: null, showingMenu: false, playingGIF: false };
(0, _PinUtil.bind)(_this, 'handleToggleMenu', 'handleToggleGIF', 'handlePinit');
return _this;
}
/**
* On mount, we fetch the remote Pin data for rendering
*/
_createClass(PinterestPinWidget, [{
key: 'componentDidMount',
value: function componentDidMount() {
var _this2 = this;
var url = _PinConst.URL.PIN + ('?base_scheme=http&pin_ids=' + this.props.pin);
(0, _PinUtil.fetch)(url, function (response) {
if (response && response.data && response.data[0]) {
_this2.setState({ pin: response.data[0] });
} else {
console.error('Error in fetching Pin:', response);
}
});
}
/**
* Handle toggling visibility of the dropdown "copyright" menu
*/
}, {
key: 'handleToggleMenu',
value: function handleToggleMenu() {
this.setState({ showingMenu: !this.state.showingMenu });
}
/**
* Handle playing/pausing a GIF
*/
}, {
key: 'handleToggleGIF',
value: function handleToggleGIF(evt) {
evt.preventDefault();
this.setState({ playingGIF: !this.state.playingGIF });
}
/**
* Handle the clicking of the Pin It button to open the
* Pin create popup form
*/
}, {
key: 'handlePinit',
value: function handlePinit(evt) {
evt.preventDefault();
var href = 'https://www.pinterest.com/pin/' + this.state.pin.id + '/repin/x/?guid=' + _PinConst.GUID;
window.open(href, 'pin' + new Date().getTime(), POPUP_OPTIONS.PIN_CREATE);
log({ type: 'embed_pin_repin' + this.logSize, href: href });
}
/**
* Get the url for the correctly sized remote image
* @returns {string} image url
*/
}, {
key: 'getPinImage',
value: function getPinImage() {
var url = this.state.pin.images['237x'].url;
switch (this.props.size) {
case 'large':
return url.replace('237x', '600x');
case 'medium':
return url.replace('237x', '345x');
default:
return url;
}
}
/**
* Get the url for the correct Pin It button image
* @returns {string} image url
*/
}, {
key: 'getButtonImage',
value: function getButtonImage() {
var base = 'https://s-passets.pinimg.com/images/pidgets/';
var resolution = (0, _PinUtil.getResolution)();
var url = void 0;
if (this.props.lang === 'ja') {
url = 'pinit_bg_ja_rect_red_20_' + resolution + '.png';
} else {
var size = this.props.size === 'small' ? 'small' : 'medium';
url = 'repin_' + size + '_' + resolution + '.png';
}
return { backgroundImage: 'url(' + (base + url) + ')' };
}
/**
* Render helper when attribution is available
*/
}, {
key: 'renderAttribution',
value: function renderAttribution() {
var attr = this.state.pin.attribution;
var shouldRender = attr && attr.url && attr.author_name && attr.provider_icon_url;
return shouldRender && _react2.default.createElement(
'span',
{ className: 'pin-widget-attrib' },
_react2.default.createElement('img', { className: 'pin-widget-attrib-icon', src: attr.provider_icon_url }),
_react2.default.createElement(
'span',
{ className: 'pin-widget-attrib' },
_react2.default.createElement(
'a',
{ className: 'pin-widget-attrib-anchor', href: attr.url, target: '_blank' },
attr.author_name
)
)
);
}
/**
* Render helper for the description block, including optional
* attribution and stats counts for non-large Pin widget
*/
}, {
key: 'renderDescription',
value: function renderDescription() {
var pin = this.state.pin;
return _react2.default.createElement(
'span',
{ className: 'pin-widget-description' },
pin.description,
this.renderAttribution(),
this.props.size !== 'large' && this.renderStats()
);
}
/**
* Render helper for the menu button and the optional dropdown menu
* for ability to report copyright infringement
*/
}, {
key: 'renderMenu',
value: function renderMenu() {
var resolution = (0, _PinUtil.getResolution)();
var image = 'url(https://s-passets.pinimg.com/images/pidgets/menu_' + resolution + '.png)';
return _react2.default.createElement(
'span',
null,
_react2.default.createElement('a', { className: 'pin-widget-menu', style: { backgroundImage: image }, onClick: this.handleToggleMenu }),
this.state.showingMenu && _react2.default.createElement(
'span',
{ className: 'pin-widget-menu-dropdown' },
_react2.default.createElement(
_PinterestAnchor2.default,
{ href: 'https://www.pinterest.com/about/copyright/dmca-pin/', log: 'embed_pin_report' },
_i18n2.default.translate("Copyright issue")
)
)
);
}
/**
* Render helper for rich metadata with fallback to the Pin's domain
*/
}, {
key: 'renderMeta',
value: function renderMeta() {
var pin = this.state.pin;
var provider = pin.rich_metadata ? pin.rich_metadata.site_name : pin.domain;
var metadata = pin.rich_metadata;
return _react2.default.createElement(
'span',
{ className: 'pin-widget-meta' },
metadata && _react2.default.createElement(
'span',
null,
_react2.default.createElement(
_PinterestAnchor2.default,
{ className: 'pin-widget-meta-anchor', href: metadata.url, log: 'embed_pin_domain' + this.logSize },
_react2.default.createElement('img', { src: metadata.favicon_link, alt: pin.rich_metadata.site_name, title: pin.rich_metadata.site_name })
),
_react2.default.createElement(
_PinterestAnchor2.default,
{ className: 'pin-widget-meta-anchor', href: metadata.url, log: 'embed_pin_domain' + this.logSize },
_i18n2.default.translate("from <b>$1</b>", provider)
)
),
!metadata && _react2.default.createElement(
_PinterestAnchor2.default,
{ className: 'pin-widget-meta-anchor', href: 'https://' + pin.domain, log: 'embed_pin_domain' + this.logSize },
_i18n2.default.translate("from <b>$1</b>", provider)
),
this.renderMenu()
);
}
/**
* Render helper for an embedded GIF
*/
}, {
key: 'renderGIF',
value: function renderGIF(pin, image) {
var text = this.state.playingGIF ? 'II GIF' : '▶ GIF';
var src = this.state.playingGIF ? image.replace(/(237x|345x|600x)/, 'originals') : image;
return _react2.default.createElement(
_PinterestAnchor2.default,
{ className: 'pin-widget-pin-link', href: 'https://www.pinterest.com/pin/' + pin.id + '/', log: 'embed_pin_img' + this.logSize },
_react2.default.createElement('img', { className: 'pin-widget-pin-link-img', alt: pin.description, 'data-pin-nopin': 'true', src: src, width: '100%' }),
_react2.default.createElement(
'i',
{ className: 'pin-widget-gif', onClick: this.handleToggleGIF },
text
)
);
}
/**
* Render helper for an embedded video
*/
}, {
key: 'renderVideo',
value: function renderVideo(pin, image) {
var ratio = Math.floor(pin.images['237x'].height * 100 / pin.images['237x'].width);
var style = { paddingBottom: ratio + '%' };
return _react2.default.createElement(
'a',
{ className: 'pin-widget-pin-link', href: '//www.pinterest.com/pin/' + pin.id + '/repin/x/' },
_react2.default.createElement(
'span',
{ className: 'pin-widget-link-iframe', style: style },
_react2.default.createElement('iframe', { src: pin.embed.src.replace(/autoplay=/, "nerfAutoPlay="), frameBorder: '0' })
)
);
}
/**
* Render helper for a Pin image
*/
}, {
key: 'renderImage',
value: function renderImage(pin, image) {
return _react2.default.createElement(
_PinterestAnchor2.default,
{ className: 'pin-widget-pin-link', href: 'https://www.pinterest.com/pin/' + pin.id + '/', log: 'embed_pin_img' + this.logSize },
_react2.default.createElement('img', { className: 'pin-widget-pin-link-img', alt: pin.description, 'data-pin-nopin': 'true', src: image, width: '100%' })
);
}
/**
* Render helper for image/video/GIF type media.
*/
}, {
key: 'renderMedia',
value: function renderMedia() {
var pin = this.state.pin;
var image = this.getPinImage();
if (pin.embed) {
if (pin.embed.type === 'gif') {
return this.renderGIF(pin, image);
} else {
return this.renderVideo(pin, image);
}
} else {
return this.renderImage(pin, image);
}
}
/**
* Render helper for showing likes/repins only if the count is not zero
*/
}, {
key: 'renderStats',
value: function renderStats() {
var pin = this.state.pin;
return _react2.default.createElement(
'span',
{ className: 'pin-widget-stats' },
pin.repin_count !== 0 && _react2.default.createElement(
'span',
{ className: 'pin-widget-repin-count' },
pin.repin_count
),
pin.like_count !== 0 && _react2.default.createElement(
'span',
{ className: 'pin-widget-like-count' },
pin.like_count
)
);
}
/**
* Render helper when attribution is available
*/
}, {
key: 'renderHeader',
value: function renderHeader() {
return this.props.size === 'large' && _react2.default.createElement(
'span',
{ className: 'pin-widget-header' },
this.renderStats()
);
}
/**
* Render helper for the footer
*/
}, {
key: 'renderFooter',
value: function renderFooter() {
var pin = this.state.pin;
var isJapan = this.props.lang === 'ja';
return _react2.default.createElement(
'span',
{ className: 'pin-widget-footer' },
_react2.default.createElement(
_PinterestAnchor2.default,
{ href: pin.pinner.profile_url, log: 'embed_pin_pinner' + this.logSize },
_react2.default.createElement('img', { className: 'pin-widget-avatar', alt: pin.pinner.full_name, title: pin.pinner.full_name, src: pin.pinner.image_small_url })
),
_react2.default.createElement(
'span',
null,
_react2.default.createElement(
_PinterestAnchor2.default,
{ className: 'pin-widget-footer-text', href: pin.pinner.profile_url, log: 'embed_pin_pinner' + this.logSize },
_react2.default.createElement(
'b',
null,
pin.pinner.full_name
)
),
_react2.default.createElement(
_PinterestAnchor2.default,
{ className: 'pin-widget-footer-text', href: '//www.pinterest.com' + pin.board.url, log: 'embed_pin_board' + this.logSize },
pin.board.name
)
)
);
}
/**
* Render helper for the entire Pin once the remote fetch has finished
*/
}, {
key: 'renderPin',
value: function renderPin() {
this.logSize = this.props.size === 'small' ? '' : '_' + this.props.size;
return _react2.default.createElement(
'span',
{ className: 'pinterest-widget--pin pin-widget--' + this.props.size, style: this.props.style },
_react2.default.createElement('i', { className: 'pin-widget-repin', style: this.getButtonImage(), onClick: this.handlePinit }),
this.renderHeader(),
this.renderMedia(),
this.renderMeta(),
this.renderDescription(),
this.renderFooter()
);
}
/**
* Render method.
*/
}, {
key: 'render',
value: function render() {
return this.state.pin && this.renderPin();
}
}]);
return PinterestPinWidget;
}(_PinterestBase3.default);
exports.default = PinterestPinWidget;
PinterestPinWidget.propTypes = {
pin: _react2.default.PropTypes.string.isRequired,
lang: _react2.default.PropTypes.string,
size: _react2.default.PropTypes.oneOf(['small', 'medium', 'large'])
};
PinterestPinWidget.defaultProps = {
pin: undefined,
size: 'small',
lang: 'en'
};