📢 The commenting platform for ft.com, the app, interactive graphics & alphaville is currently being replaced. Please speak to the Comments team if you intend to start using this component or wish to make any changes to it.
A fully featured commenting client integrated with FT's membership systems. If you simply wish to add comments or a comment count to some content this is the component to use.
Use the following markup to enable comments:
<div data-o-component="o-comments"
id="{idOfTheElement}"
data-o-comments-auto-init="true|false"
data-o-comments-config-article-id="{article-id}"
data-o-comments-config-title="{article-title}"
data-o-comments-config-url="{page-url}">
<div class="o--if-no-js">To participate in this chat, you need to upgrade to a newer web browser. <a href="http://help.ft.com/tools-services/browser-compatibility/">Learn more.</a></div>
</div>
data-o-comments-config-title
the title of your article/post/thingdata-o-comments-config-article-id
a unique id for your content, ideally a UUID for FT contentdata-o-comments-config-url
The canonical URL for your article/page/thingdata-o-comments-config-livefyre--{key}
for Livefyre specific Conv
configuration mentioned here: http://answers.livefyre.com/developers/app-integrations/comments/#convConfigObject.data-o-comments-config-{key}
for any other configuration. {key}
has the following rule: --
means new object level, -
means camel case. Example: data-o-comments-config-livefyre--data-format--absolute="value"
is transformed to: {"livefyre": {"dataFormat": {"absolute": "value"}}}
data-o-comments-auto-init="false"
a module which has this attribute with a false
value will not be initialized on the o.DOMContentLoaded
event. This allows you to defer component initialisation.id
preferable to be set, but if missing it will be generatedThose elements which don't have the data-o-comments-auto-init="false"
attribute will be automatically initialized on the o.DOMContentReady
event.
If you defer initialising oComments by using data-o-comments-auto-init="false"
then you can initialise the component whenever you want by calling
oComments.init();
The init function may take an optional parameter: a context (this could be DOM element or a valid selector). The search would be performed only inside of this context element. If none is specified, it defaults to document.body.
Use the following markup to enable comments:
<div data-o-component="o-comments"
- id="{idOfTheElement}"
+ data-o-comments-count
data-o-comments-auto-init="true|false"
data-o-comments-config-article-id="{article-id}"
- data-o-comments-config-title="{article-title}"
- data-o-comments-config-url="{page-url}"
+ data-o-comments-config-template="{count} Comment{plural}">
- <div class="o--if-no-js">To participate in this chat, you need to upgrade to a newer web browser. <a href="http://help.ft.com/tools-services/browser-compatibility/">Learn more.</a></div>
+ <div class="o--if-no-js">0 Comments</div>
For the full list of configuration, see the available configurations.
Create an instance of the comment component with the parameters that are available:
var oComments = new oComments(document.querySelector('.comments'), {
title: document.title,
url: document.location.href,
articleId: 'article-id',
livefyre: {
datetimeFormat: {
minutesUntilAbsoluteTime: -1,
absoluteFormat: 'MMM dd hh:mm a'
}
}
});
The widget is automatically initialized, unless you specify in the configuration autoInit: false
. In this case you can initialize this particular object at a later time by calling the following:
oComments.init();
The configuration object which is passed to the contructor can/should have the following fields:
init
method on the instance when you want to initialize it.Create an instance of the comment count component with the parameters that are available:
var oComments = new oComments(document.querySelector('.comments-count'), {
articleId: 'article-id'
});
The configuration object which is passed to the contructor can/should have the following fields:
{count}
will be replaced with the count, and {plural}
will be replaced with blank for a count of 0 or 1, and with 's' for a count > 1.Users need to have a valid FT session in order to post comments. The default behavior for a user without a valid session is to redirect to the FT's login page (https://accounts.ft.com/login). However you may wish to integrate with your product's authentication process for a slicker UX in which case you can override the default behaviour.
auth.loginRequiredDefaultBehavior
functionoComments.auth.loginRequiredDefaultBehavior = function (callback) {
// do login in a nicer way
if (success) {
callback();
} else {
callback(new Error("Failed")); // provide an error as parameter
}
}
Important: if the log in needs a page reload, don't call the callback at all (there's no success/failure, it's still pending)!
Example:
oComments.on('auth.loginRequired', function (evt) {
// the user is not logged in, but an action was performed within the comment widget that requires the user to be logged in
login();
if (loggedIn) {
evt.detail.callback();
} else if (loginRefused) {
evt.detail.callback(new Error("Refused")); // provide an error as parameter
} else if (loginFailure) {
evt.detail.callback(new Error("Failed")); // provide an error as parameter
}
evt.stopImmediatePropagation();
});
Important: if the log in needs a page reload, don't call the failure function!
These events are triggered on the instance's DOM element.
All events have a payload of data which helps getting the ID of the instance and the instance object itself:
{
detail: {
id: "idOfTheComponent",
instance: componentInstance,
data: {...} //data specific to the event
}
}
Triggered when loading the widget exceeded a given time.
Error while loading the initialization data and the comments.
Event detail data: error object/message.
Triggered when any error appear (triggered together with the above mentioned error events).
Event detail data: error object/message.
Loaded when the initialization is finished and the necessary data is obtained.
Event detail data: initialization data in the following form:
{
"articleId": "e8cc08c6-cf4f-11e2-be7b-00144feab7de",
"el": "commentWidget",
"siteId": "359898",
"collectionMeta": "eyJhbGciOiJIUzI1NiJ9.eyJjaGVja3N1bSI6ImUwZDA4MTFmNTM0ODY2NWYwODlkZjI2ZGM0MGZkZTFiIiwiYXJ0aWNsZUlkIjoiZThjYzA4YzYtY2Y0Zi0xMWUyLWJlN2ItMDAxNDRmZWFiN2RlIiwidGl0bGUiOiJMaXZlZnlyZSB0ZXN0IHBhZ2UgLSBGVC5jb20iLCJ1cmwiOiJodHRwOi8vd3d3LmZ0LmNvbS9jbXMvcy8wL2U4Y2MwOGM2LWNmNGYtMTFlMi1iZTdiLTAwMTQ0ZmVhYjdkZS5odG1sIiwidHlwZSI6ImxpdmVjb21tZW50cyIsInN0cmVhbV90eXBlIjoibGl2ZWNvbW1lbnRzIiwidGFncyI6WyJzZWN0aW9ucy5HcmVhdCBKb3VybmV5cyIsInNlY3Rpb25zLkxpZmUgXHUwMDI2IEFydHMiLCJzZWN0aW9ucy5UcmF2ZWwiLCJzZWN0aW9ucy5FdXJvcGVhbiBkZXN0aW5hdGlvbnMiXX0.dvYd1K0FJAL6wmmTAlQ8peTyFP9M2GORoN7ZO9PvEYE",
"checksum": "e0d0811f5348665f089df26dc40fde1b"
}
The first time the auth object is loaded, it is broadcasted using this event. Event detail data: authentication and user detail data in the following form:
{
"token": "eyJhbGciOiJIUzI1NiJ9.eyJkb21haW4iOiJmdC0xLmZ5cmUuY28iLCJleHBpcmVzIjoxNDE3MTE2Nzk5LCJ1c2VyX2lkIjoiODk0ODc0MzkiLCJkaXNwbGF5X25hbWUiOiJyb2xpIG1haW4ifQ.maN1bKWvDQLA-mvgNp9lSKdI9Izj9rmX3XrEaVwUTNY",
"expires": 1417116799,
"displayName": "user pseudonym",
"settings": {
"emailcomments": "never",
"emailreplies": "never",
"emaillikes": "never",
"emailautofollow": "off"
}
}
The widget is ready to be rendered, the initialization process has finished.
The Livefyre widget has loaded the necessary data and created a Livefyre widget
instance, but not yet rendered it. The handler receives the Livefyre widget object as a parameter, access it using detail.data.lfWidget
.
The UI is fully rendered.
A comment is posted.
Event detail data: (evt.detail.data)
{
lfEventData: {
authorId: "89488565@ft-1.fyre.co",
bodyHtml: "<p>test123</p>",
parent: "",
sharedToFacebook: false,
sharedToTwitter: false
},
siteId: 359898
}
A comment is recommended.
Event detail data: (evt.detail.data)
{
lfEventData: {
targetId: "245625" // The ID of the comment that was liked
targetAuthorId: "i_am_author@livefyre.com" // The ID of the author of the comment that was liked
},
siteId: 359898
}
A comment is shared.
Event detail data: (evt.detail.data)
{
lfEventData: {
targetId: "256255" // The ID of the comment that was shared
sharedToFacebook: false // Whether the comment was shared to Facebook
sharedToTwitter: true // Whether the comment was shared to Twitter
},
siteId: 359898
}
A user sent a social mention through a comment.
Event detail data: (evt.detail.data)
{
lfEventData: {
id: '111111@fb.gw.livefyre.com' // ID of the mentioned user
displayName: 'testUser' // Display name of mentioned user
message: "@testUser Wow, I can't believe it either!" // Message that was sent to the particular user
provider: 'twitter' // Provider to which the mention was shared
},
siteId: 359898
}
These events are triggered on the body
element and are relevant to all oComments components on a page. They have the same format as the component level events: oComments.nameOfTheEvent
.
The payload data consists only of event specific data:
{
detail: {...} // event specific data
}
The events are the following:
Triggered when a user is successfully logged in.
Payload is the jwt token with which the user is logged in.
Triggered when a user is logged out.
Triggered on any activity which explicitly requires a logged in status. This could mean from the product perspective that the user is not logged in, or his/her login status expired (e.g. session expire).
The payload data contains an object with a callback function. Based on the outcome of the login process, one of these should be called by the handler.
Important: if the log in needs a page reload, don't call the callback at all (there's no success/failure, it's still pending)!
oComments.on('auth.loginRequired', function (evt) {
if (logInSuccess) {
evt.detail.callback();
}
if (logInFails || logInRefused) {
evt.detail.callback(new Error("Failed or cancelled."));
}
});
Triggered when the core Livefyre resource file (e.g. Livefyre's core JS library) couldn't be loaded.
Event detail data: error object/message.
This module uses global configuration. These are related configurations for Livefyre.
The default configuration is the production one:
{
"loginUrl": "https://accounts.ft.com/login",
"livefyre": {
"network": "ft.fyre.co",
"domain": "ft.auth.fyre.co",
"resourceDomainBase": "//cdn.livefyre.com/"
},
"resourceUrls": {
"livefyreJs": "Livefyre.js"
},
"emailNotifications": true
}
In order to change to the settings of the TEST environment, then this configuration should be used:
{
"loginUrl": "https://accounts-test.ft.com/login",
"livefyre": {
"network": "ft-1.fyre.co",
"domain": "ft-1.auth.fyre.co"
}
}
There are two ways for changing the environment:
In order to change the configuration, you can add a script tag in your page source with the format in the example below:
<script data-o-comments-config type="application/json">
{
"loginUrl": "https://accounts-test.ft.com/login",
"livefyre": {
"network": "ft-1.fyre.co",
"domain": "ft-1.auth.fyre.co"
}
}
</script>
This configuration will be loaded on the o.DOMContentLoaded
event.
**Also, don't forget to also add the configuration for o-comment-api
(http://registry.origami.ft.com/components/o-comment-api#configuration).**
The configuration can be changed be using the setConfig
static method. Calling this method with an object will merge the current configuration with the object specified (deep merge, primitive type values of the same key will be overwritten).
Example:
oComments.setConfig({
"loginUrl": "https://accounts-test.ft.com/login",
"livefyre": {
"network": "ft-1.fyre.co",
"domain": "ft-1.auth.fyre.co"
}
});
As on the event o.DOMContentLoaded
the widgets declared in the DOM are automatically initialized, it is preferred to call this function before the o.DOMContentLoaded
event is triggered.
**Also, don't forget to also add the configuration for o-comment-api
(http://registry.origami.ft.com/components/o-comment-api#configuration).**
The API of o-comment-api is available by using oComments.dataService
.
You can override the messages shown to a user in various parts of the UI:
An object with the following messages:
commentTombstone: "This comment has been removed"
errorLikeOwnComment: "You cannot recommend your own comment"
featuredCommentsTitlePlural: "Editor's picks"flagButton: "Report"
flagCommentTooltip: "Report"
flagConfirmationMessage: "Report %s's comment as %s?"
flagSubtitle: "Report as"
flagSuccessMsg: "Comment has been reported."
flagTitle: "Report %s's comment"
likeButton: "Recommend"
moderator: "Moderator"
postAsButton: "Submit Comment"
postButton: "Submit Comment"
postReplyAsButton: "Submit Comment"
postReplyButton: "Submit Comment"
shareDefaultText: "Read %s's comment on FT.com"
showMore: "Show more comments"
sortBackButton: "Back to active discussions"
sortHotThreads: "Active discussions"
sortTopComments: "Most recommended"
topCommentsContentNotFoundMsg: "There aren't any recommendations yet."
unlikeButton: "Unrecommend"
Logging can be enabled for debugging purposes. It logs using the global 'console' if available (if not, nothing happens and it degrades gracefully).
By default logging is disabled.
This method enables logging of the module.
This method disables logging of the module.
This method sets the logging level. This could be a number from 0 to 4 (where 0 is debug, 4 is error), or a string from the available methods of 'console' (debug, log, info, warn, error).
Default is 3 (warn).
There is a default font-family set for o-comments: MetricWeb, sans-serif
Please note that the font itself is not loaded by this module, this should be done by the product.
In order to override the default font, set a value for the following variable:
$o-comments-font-family: font1, font2;
In order to suppress downloading the web fonts set the following variable
$o-comments-include-fonts: false;
Works in accordance with our support policy.