Skip to content

Instantly share code, notes, and snippets.

@nl5887
Last active August 29, 2015 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nl5887/41ab4d44d5279755fcb2 to your computer and use it in GitHub Desktop.
Save nl5887/41ab4d44d5279755fcb2 to your computer and use it in GitHub Desktop.
mod.directive('mjGridArticle', ['$state', '$location', '$timeout', function($state, $location, $timeout) {
return {
restrict: 'EA',
priority: 0,
scope: false,
link: function (scope, element, attrs) {
var render = function() {
var toRender = {scope:scope, state: $state, location: $location, attrs: attrs };
React.renderComponent(window.GridArticle( {scope:scope, state: $state, location: $location, attrs: attrs }), element[0]);
};
$timeout(function() {
render();
});
}
};
}]);
window.GridArticle = React.createClass({displayName: 'GridArticle',
render: function() {
var likeHandler = this.props.scope.$apply.bind(this.props.scope, this.props.scope.like.bind(null, this.props.scope.item));
var addToPocketHandler = this.props.scope.$apply.bind(this.props.scope, this.props.scope.addToPocket.bind(null, this.props.scope.item));
var favoriteHandler = this.props.scope.$apply.bind(this.props.scope, this.props.scope.favorite.bind(null, this.props.scope.item));
var pinHandler = this.props.scope.$apply.bind(this.props.scope, this.props.scope.pin.bind(null, this.props.scope.item));
var $state = this.props.state;
var $location = this.props.location;
var scope = this.props.scope;
var cx = React.addons.classSet;
var likeClasses = cx({'fa': true, 'fa-thumbs-up': this.props.scope.item.liked, 'fa-thumbs-o-up': !this.props.scope.item.liked});
var favoriteClasses = cx({'fa': true, 'fa-star': this.props.scope.item.favorite, 'fa-star-o': !this.props.scope.item.favorite});
var pinClasses = cx({'fa': true, 'fa-plus': true, 'active': this.props.scope.item.collections.length > 0, 'show-admin': true});
var publisherLogoStyles = {
'background-image': 'url('+this.props.scope.item.channel.thumbnail+')'
};
var item = this.props.scope.item;
var childNodes = React.DOM.div( {},
React.DOM.div( {className:'articleHeader'},
React.DOM.div( {className:'publisherLine'},
React.DOM.a( {'ui-sref':'kiosk:channel({channel_key:item.channel.key})', className:'publisherLogo', style:publisherLogoStyles}),
React.DOM.a( {'ui-sref':'kiosk:channel({channel_key:item.channel.key})', className:'publisherName'}, this.props.scope.item.highlight.channel),
React.DOM.a( {'ui-sref':'kiosk:channel({channel_key:item.channel.key, category_key:item.category.key})', className:'articleCategory'}, this.props.scope.item.highlight.category)
),
new Thumbnail( {scope: scope, state:$state, item:item}),
React.DOM.a( {className:'gridTitle', 'ui-sref':'article({channel_key: item.channel.key, article_key: item.key, buy: false})', dangerouslySetInnerHTML:{ __html: this.props.scope.item.highlight.title }})
),
React.DOM.div( {className:'articleMeta'},
React.DOM.span( {className:'date'}, this.timeAgo(this.props.scope.item.date) ),
React.DOM.span( {className:'articleAuthor'}, ' | ', this.translate('By:'), ' ',
React.DOM.a( {'ui-sref':'all({author:item.author})'}, this.props.scope.item.author)
)
),
React.DOM.p( {dangerouslySetInnerHTML:{ __html: this.props.scope.item.highlight.description }}),
React.DOM.span( {className:'reading-time'},
React.DOM.i({className:'fa fa-clock-o'}),' ',
React.DOM.b(null, this.readingTime(this.props.scope.item.words))
),
React.DOM.div( {className:'gridbox-icons pull-left hover'},
React.DOM.a( {className:'gridbox-icon favorite', tooltip: this.translate('Add to favorites'), 'mj-restricted-action':'user,admin', onClick:favoriteHandler},
React.DOM.i( {className:favoriteClasses})
),
React.DOM.a( {className:'hidden-no-pocket gridbox-icon pocket', tooltip: this.translate('Read later in Pocket'), onClick:addToPocketHandler},
React.DOM.i( {'aria-hidden':'true', className:'grands grands-icon-Pocket'})
)
),
React.DOM.button( {className:'btn btn-primary buy-button', 'mj-open-article-sref':'item' },
React.DOM.span({className:'buy'}, React.DOM.span(null, this.translate('Read')),
React.DOM.span( {className:'lineLeft'}, this.pluralize( this.props.scope.item.credits, {'0': this.translate('Gratis'), '1': this.translate('1 credit'), 'other': this.translate('{} credits')}))),
React.DOM.span({ className:'coupon'}, this.translate('In Subscription') ),
React.DOM.span({className:'channel-owner'}, this.translate('Read (own article)') ),
React.DOM.span({className:'read'}, this.translate('Read (past)') )
)
);
React.addons.myjour.walk(childNodes, function(el){
var newHref;
if (angular.isDefined(el.props['mj-open-article-sref'])) {
newHref = $state.href('article', { channel_key: item.channel.key, article_key: item.key }, {});
el.props.href = newHref;
el.props.target = 'self';
el.props.onClick=function(e) {
e.preventDefault();
e.stopPropagation();
scope.$apply(function() {
scope.openArticle(item);
});
};
}
if (angular.isDefined(el.props['ui-sref'])) {
var ref = React.addons.myjour.parseStateRef(el.props['ui-sref'], $state.current);
var params = scope.$eval(ref.paramExpr);
newHref = $state.href(ref.state, params, {});
el.props.href = newHref;
el.props.target = 'self';
el.props.onClick=function(e) {
e.preventDefault();
e.stopPropagation();
scope.$apply(function() {
$state.go(ref.state, params);
});
};
}
if (angular.isDefined(el.props['mj-restricted-action'])) {
var role = scope.user.role;
var allowedRoles = el.props['mj-restricted-action'].split(',');
if (allowedRoles.indexOf(role) < 0){
el.className = el.className + ' disabled';
}
var oldOnClick = el.props.onClick;
el.props.onClick = function(e) {
if (allowedRoles.indexOf(role) < 0){
e.preventDefault();
e.stopPropagation();
scope.$apply(function() {
$location.hash('login');
});
}else{
oldOnClick(e);
}
return(false);
};
}
if (angular.isDefined(el.props.tooltip)) {
el.props.onMouseEnter = function() {
};
el.props.onMouseLeave = function() {
};
}
});
return (childNodes);
},
readingTime: function(words)
{
return (words >= 220? Math.ceil(words / 220) + ' min.': '30 sec.');
},
pluralize: function(count, where)
{
if (count === 0) {
return (where['0']);
} else if (count === 1) {
return (where['1']);
} else {
return (where.other.replace('{}', count));
}
},
timeAgo: function(date) {
var momentDate = moment(date);
if (momentDate.diff (Date.now(), 'days') < -7) {
return(momentDate.format('LL'));
} else {
return(momentDate.fromNow());
}
},
translate: function(text) {
return (text);
}
});
React.addons.myjour = {
walk: function walk(el, process, root) {
root = root || el;
var nodes = el.props.children || [];
var nextNode = null;
if (typeof(nodes.length) === 'undefined') {
nextNode=nodes;
if (nextNode==null) {
return;
}
if (typeof nextNode.props === 'undefined') {
return;
}
walk(nextNode, process, root);
}
for (var i=0; i<nodes.length; i++) {
nextNode=nodes[i];
if (nextNode==null) {
continue;
}
if (typeof nextNode.props === 'undefined') {
continue;
}
walk(nextNode, process, root);
}
process(el);
},
parseStateRef: function parseStateRef(ref, current) {
var preparsed = ref.match(/^\s*({[^}]*})\s*$/);
if (preparsed) { ref = current + '(' + preparsed[1] + ')'; }
var parsed = ref.replace(/\n/g, ' ').match(/^([^(]+?)\s*(\((.*)\))?$/);
if (!parsed || parsed.length !== 4) { throw new Error('Invalid state ref "' + ref + '"'); }
return { state: parsed[1], paramExpr: parsed[3] || null };
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment