commit 42efc47e2f2ff04dfdea79f5b802152f740fe2ee Author: シモン Date: Mon May 1 16:40:19 2017 +0900 Basic first setup (JS and CSS - 2 themes) diff --git a/README.md b/README.md new file mode 100644 index 0000000..501b273 --- /dev/null +++ b/README.md @@ -0,0 +1,53 @@ + +# Mastodon.widget + +The idea of this little script is to allow users to display their Mastodon timeline on their blog/website. + +## Requirements + + - jQuery + - access token from the mastodon instance you want to display the timeline from + +To help you create a token, we'll soon provide a page on our website that will guide you through the requiered steps. + +## Installation + +1) Download the required files (only one JS and one CSS). + +2) Simply paste the code bellow in you website: + + + + + + +In the sample above, you have to replace the folowing: + + - [MASTODON INSTANCE] => i.e : https://mastodon.technology + - [ACCESS TOKEN] => token you created for your app and linked with your Mastodon instance account + - [ACCOUNT ID] => your user ID on Mastodon instance + +3) Add a container for your timeline where you want in the body of your website: + +
+ +## Customization + +You have the choice between 2 basic themes: + + - mastodon-timeline-light + - mastodon-timeline-dark + +Or you can create your own. Please have a look in the CSS file for more details. diff --git a/mastodon.widget.css b/mastodon.widget.css new file mode 100644 index 0000000..0b5e8a7 --- /dev/null +++ b/mastodon.widget.css @@ -0,0 +1,136 @@ +/* main container >>> */ +.mastodon-timeline { + box-shadow: 0 0 2px rgba(0, 0, 0, 0.5); + font-family: sans-serif; + margin-bottom: 1em; +} + +.mt-header, +.mt-footer { + padding: 10px 10px; +} + +.mastodon-timeline a:link, +.mastodon-timeline a:active, +.mastodon-timeline a { + text-decoration: none; + font-weight: normal; +} + +.mt-header { + font-weight: bold; + border-bottom: 1px solid purple; +} + +.mt-header h4 { + display: inline-block; +} + +.mt-body { + height: 250px; + overflow-y: auto; +} + +.mt-loading { + padding: 10px; + text-align: center; +} + +.mt-footer { + text-align: center; +} + +/* toots -messages */ +.mt-toot { + margin: 5px; + padding: 5px 5px 5px 65px; + position: relative; + min-height: 60px; +} + +.mt-footer, +.mt-toot:nth-child(n+2) { + border-top: 1px solid purple; +} + +.mt-toot p:last-child { + margin-bottom: 0; +} + +.mt-date { + text-align: right; +} + +.mt-avatar { + position: absolute; + top: 5px; + left: 5px; + /*margin: 0 10px 5px 0;*/ + width: 50px; + height: 50px; + border-radius: 5px; + box-shadow: 0 0 2px rgba(0, 0, 0, 0.5); +} +/* <<< */ + +/* light theme >>> */ +.mastodon-timeline-light { + background: #fafafa; + color: #555; +} + +.mastodon-timeline-light .mt-footer, +.mastodon-timeline-light .mt-header { + background: #eee; +} + +.mastodon-timeline-light a:link, +.mastodon-timeline-light a:active, +.mastodon-timeline-light a { + color: #26afff; +} + +.mastodon-timeline-light .mt-header { + border-bottom-color: lightgrey; +} + +.mastodon-timeline-light .mt-footer, +.mastodon-timeline-light .mt-toot:nth-child(n+2) { + border-top-color: lightgrey; +} + +.mastodon-timeline-light .mt-date a { + color: lightgrey; +} +/* <<< */ + +/* dark theme >>> */ +.mastodon-timeline-dark { + background: #393f4f; + color: white; +} + +.mastodon-timeline-dark .mt-footer, +.mastodon-timeline-dark .mt-header { + background: #313543; +} + +.mastodon-timeline-dark a:link, +.mastodon-timeline-dark a:active, +.mastodon-timeline-dark a { + color: #2b90d9; +} + +.mastodon-timeline-dark .mt-header { + border-bottom-color: #606984; +} + +.mastodon-timeline-dark .mt-footer, +.mastodon-timeline-dark .mt-toot:nth-child(n+2) { + border-top-color: #606984; +} + +.mastodon-timeline-dark .mt-date a { + color: #606984; +} +/* <<< */ diff --git a/mastodon.widget.js b/mastodon.widget.js new file mode 100644 index 0000000..8c5fd5e --- /dev/null +++ b/mastodon.widget.js @@ -0,0 +1,154 @@ +/** + * Mastodon User Timeline Widget + * + * @author Azet + * @param object params_ + * instance_uri : the instance to fetch messages from + * access_token : widget's application access token (can be generated from http://azet.jp/mastodon-usertimeline-widget/) + * account_id : user account id to fetch messages of + * target_selector : HTML node selector (jquery/css style) + */ +var MastodonApi = function(params_) { + + // endpoint access settings + this.INSTANCE_URI = params_.instance_uri; + this.ACCESS_TOKEN = params_.access_token; + this.ACCOUNT_ID = params_.account_id; + // optional parameters + this.toots_limit = params_.toots_limit || 20; + + // display target element + this.widget = $(params_.target_selector); + + // build the basic widget + this.makeWidget(); + this.listStatuses(); +} + + +/** + * build timeline widget + */ +MastodonApi.prototype.makeWidget = function() { + this.widget.addClass('mastodon-timeline'); + this.widget.append($('

Toots

by
')); + this.widget.append($('
loading...
')); + this.widget.append($('')); +}; + + +/** + * listing function + */ +MastodonApi.prototype.listStatuses = function() { + var mapi = this; + + // get request + $.ajax({ + url: this.INSTANCE_URI+'/api/v1/accounts/'+this.ACCOUNT_ID+'/statuses' + ,headers: { + Authorization : 'Bearer '+this.ACCESS_TOKEN + } + ,method : 'GET' + ,dataType: 'json' + ,data : { + limit : this.toots_limit + } + ,success: function(data_) { + // clear the loading message + $('.mt-body', mapi.widget).html(""); + //console.log( data_ ); + + // add posts + for(var i in data_) { + if(i==0) { + // update user link only at first post + var account = data_[i].account; + setHeaderUserLink.call(mapi, account); + setFooterLink.call(mapi, account); + } + appendStatus.call(mapi, data_[i]); + } + + // fix content link target + $('a', this.widget).attr('target', '_blank'); + } + }); + + + /** + * add user link + * @param object account_ + */ + var setHeaderUserLink = function(account_) { + // set user name and link + $('.user-link', this.widget).append("@"+account_.username+""); + }; + + + /** + * add user link + * @param object account_ + */ + var setFooterLink = function(account_) { + var domain = this.INSTANCE_URI.replace(/https?:\/\//, ''); + $('.mt-footer', this.widget).append("View on "+domain+""); + }; + + + /** + * inner function to add each message in container + * @param object status_ + */ + var appendStatus = function(status_) { + //console.log( status_ ); + var content = $(status_.content); + + var date = prepareDateDisplay(status_.created_at); + var timestamp = $(""); + + // status container + var toot = $("
"); + // avatar + var avatar = $("
"); + avatar.css({ + 'background' : "white url('"+status_.account.avatar+"') 50% 50% no-repeat" + ,'background-size' : 'contain' + }); + // user name and url + var user = $(""); + + // add to HTML + toot.append( avatar ); + toot.append( user ); + toot.append( timestamp ); + toot.append( content ); + $('.mt-body', this.widget).append(toot); + }; + + + /** + * display toot time + * + * @author Azet + * @param StringDate date_ (standard time format) + * @return String + */ + var prepareDateDisplay = function(date_) { + var displayTime = ""; + + //var now = new Date(); + var date = new Date( date_ ); + + displayTime = date.getFullYear() + +"/"+(date.getMonth()+1) + +"/"+date.getDate() + +" "+date.getHours() + +":"+("0"+date.getMinutes()).replace(/0(\d{2})/, "$1") + ; + + return displayTime; + } + +}; +