├── .editorconfig ├── .gitignore ├── .jshintrc ├── .travis.yml ├── CONTRIBUTING.md ├── Gruntfile.js ├── README.md ├── bower.json ├── karma.conf.js ├── package.json ├── src └── disqusApi.js └── test ├── .jshintrc └── spec └── disqusApi.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bower_components/ 2 | /node_modules/ 3 | 4 | .DS_Store 5 | /dist 6 | /.idea 7 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "browser": true, 4 | "esnext": true, 5 | "bitwise": true, 6 | "camelcase": true, 7 | "curly": false, 8 | "eqeqeq": true, 9 | "immed": true, 10 | "indent": 2, 11 | "latedef": true, 12 | "newcap": true, 13 | "noarg": true, 14 | "quotmark": "single", 15 | "regexp": true, 16 | "undef": true, 17 | "unused": false, 18 | "strict": true, 19 | "globalstrict": true, 20 | "trailing": true, 21 | "smarttabs": true, 22 | "predef": [ 23 | "angular" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.10' 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ## Important notes 4 | Please don't edit files in the `dist` subdirectory as they are generated via Grunt. You'll find source code in the `src` subdirectory! 5 | 6 | ### Code style 7 | Regarding code style like indentation and whitespace, **follow the conventions you see used in the source already.** 8 | 9 | ### PhantomJS 10 | While Grunt can run the included unit tests via [PhantomJS](http://phantomjs.org/), this shouldn't be considered a substitute for the real thing. Please be sure to test the `test/*.html` unit test file(s) in _actual_ browsers. 11 | 12 | ## Modifying the code 13 | First, ensure that you have the latest [Node.js](http://nodejs.org/) and [npm](http://npmjs.org/) installed. 14 | 15 | Test that Grunt's CLI and Bower are installed by running `grunt --version` and `bower --version`. If the commands aren't found, run `npm install -g grunt-cli bower`. For more information about installing the tools, see the [getting started with Grunt guide](http://gruntjs.com/getting-started) or [bower.io](http://bower.io/) respectively. 16 | 17 | 1. Fork and clone the repo. 18 | 1. Run `npm install` to install all build dependencies (including Grunt). 19 | 1. Run `bower install` to install the front-end dependencies. 20 | 1. Run `grunt` to grunt this project. 21 | 22 | Assuming that you don't see any red, you're ready to go. Just be sure to run `grunt` after making any changes, to ensure that nothing is broken. 23 | 24 | ## Submitting pull requests 25 | 26 | 1. Create a new branch, please don't work in your `master` branch directly. 27 | 1. Add failing tests for the change you want to make. Run `grunt` to see the tests fail. 28 | 1. Fix stuff. 29 | 1. Run `grunt` to see if the tests pass. Repeat steps 2-4 until done. 30 | 1. Open `test/*.html` unit test file(s) in actual browser to ensure tests pass everywhere. 31 | 1. Update the documentation to reflect any changes. 32 | 1. Push to your fork and submit a pull request. 33 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | // Generated on 2014-09-18 using generator-angular-component 0.2.3 2 | 'use strict'; 3 | 4 | module.exports = function(grunt) { 5 | 6 | // Configurable paths 7 | var yoConfig = { 8 | livereload: 35729, 9 | src: 'src', 10 | dist: 'dist', 11 | name: 'disqusApi' 12 | }; 13 | 14 | // Livereload setup 15 | var lrSnippet = require('connect-livereload')({port: yoConfig.livereload}); 16 | var mountFolder = function (connect, dir) { 17 | return connect.static(require('path').resolve(dir)); 18 | }; 19 | 20 | // Load all grunt tasks 21 | require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks); 22 | 23 | // Project configuration 24 | grunt.initConfig({ 25 | pkg: grunt.file.readJSON('package.json'), 26 | yo: yoConfig, 27 | meta: { 28 | banner: '/**\n' + 29 | ' * <%= pkg.name %>\n' + 30 | ' * @version v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' + 31 | ' * @link <%= pkg.homepage %>\n' + 32 | ' * @author <%= pkg.author.name %> <<%= pkg.author.email %>>\n' + 33 | ' * @license MIT License, http://www.opensource.org/licenses/MIT\n' + 34 | ' */\n' 35 | }, 36 | open: { 37 | server: { 38 | path: 'http://localhost:<%= connect.options.port %>' 39 | } 40 | }, 41 | clean: { 42 | dist: { 43 | files: [{ 44 | dot: true, 45 | src: [ 46 | '.tmp', 47 | '<%= yo.dist %>/*', 48 | '!<%= yo.dist %>/.git*' 49 | ] 50 | }] 51 | }, 52 | server: '.tmp' 53 | }, 54 | watch: { 55 | gruntfile: { 56 | files: '<%= jshint.gruntfile.src %>', 57 | tasks: ['jshint:gruntfile'] 58 | }, 59 | less: { 60 | files: ['<%= yo.src %>/{,*/}*.less'], 61 | tasks: ['less:dist'] 62 | }, 63 | app: { 64 | files: [ 65 | '<%= yo.src %>/{,*/}*.html', 66 | '{.tmp,<%= yo.src %>}/{,*/}*.css', 67 | '{.tmp,<%= yo.src %>}/{,*/}*.js' 68 | ], 69 | options: { 70 | livereload: yoConfig.livereload 71 | } 72 | }, 73 | test: { 74 | files: '<%= jshint.test.src %>', 75 | tasks: ['jshint:test', 'qunit'] 76 | } 77 | }, 78 | connect: { 79 | options: { 80 | port: 9000, 81 | hostname: '0.0.0.0' // Change this to '0.0.0.0' to access the server from outside. 82 | }, 83 | livereload: { 84 | options: { 85 | middleware: function (connect) { 86 | return [ 87 | lrSnippet, 88 | mountFolder(connect, '.tmp'), 89 | mountFolder(connect, yoConfig.src) 90 | ]; 91 | } 92 | } 93 | } 94 | }, 95 | less: { 96 | options: { 97 | // dumpLineNumbers: 'all', 98 | paths: ['<%= yo.src %>'] 99 | }, 100 | dist: { 101 | files: { 102 | '<%= yo.src %>/<%= yo.name %>.css': '<%= yo.src %>/<%= yo.name %>.less' 103 | } 104 | } 105 | }, 106 | jshint: { 107 | gruntfile: { 108 | options: { 109 | jshintrc: '.jshintrc' 110 | }, 111 | src: 'Gruntfile.js' 112 | }, 113 | src: { 114 | options: { 115 | jshintrc: '.jshintrc' 116 | }, 117 | src: ['<%= yo.src %>/{,*/}*.js'] 118 | }, 119 | test: { 120 | options: { 121 | jshintrc: 'test/.jshintrc' 122 | }, 123 | src: ['test/**/*.js'] 124 | } 125 | }, 126 | karma: { 127 | options: { 128 | configFile: 'karma.conf.js', 129 | browsers: ['PhantomJS'] 130 | }, 131 | unit: { 132 | singleRun: true 133 | }, 134 | server: { 135 | autoWatch: true 136 | } 137 | }, 138 | ngmin: { 139 | options: { 140 | banner: '<%= meta.banner %>' 141 | }, 142 | dist: { 143 | src: ['<%= yo.src %>/<%= yo.name %>.js'], 144 | dest: '<%= yo.dist %>/<%= yo.name %>.js' 145 | } 146 | }, 147 | concat: { 148 | options: { 149 | banner: '<%= meta.banner %>', 150 | stripBanners: true 151 | }, 152 | dist: { 153 | src: ['<%= yo.src %>/<%= yo.name %>.js'], 154 | dest: '<%= yo.dist %>/<%= yo.name %>.js' 155 | } 156 | }, 157 | uglify: { 158 | options: { 159 | banner: '<%= meta.banner %>' 160 | }, 161 | dist: { 162 | src: '<%= concat.dist.dest %>', 163 | dest: '<%= yo.dist %>/<%= yo.name %>.min.js' 164 | } 165 | } 166 | }); 167 | 168 | grunt.registerTask('test', [ 169 | 'jshint', 170 | 'karma:unit' 171 | ]); 172 | 173 | grunt.registerTask('build', [ 174 | 'clean:dist', 175 | 'less:dist', 176 | 'ngmin:dist', 177 | 'uglify:dist' 178 | ]); 179 | 180 | grunt.registerTask('release', [ 181 | 'test', 182 | 'bump-only', 183 | 'dist', 184 | 'bump-commit' 185 | ]); 186 | 187 | grunt.registerTask('default', ['build']); 188 | 189 | }; 190 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | angular-disqus-api [![Build Status](https://travis-ci.org/brandon-barker/angular-disqus-api.svg?branch=master)](https://travis-ci.org/brandon-barker/angular-disqus-api) 2 | ================== 3 | 4 | A Disqus API wrapper for AngularJS featuring helpful directives for easily adding widgets to your pages 5 | 6 | ## Installation 7 | 8 | #### via bower: 9 | 10 | ``` 11 | $ bower install angular-disqus-api 12 | ``` 13 | 14 | ## Usage 15 | 16 | 1. Include **angular-disqus-api** as a dependency for your app 17 | 18 | ```js 19 | angular.module('myApp', ['ngDisqusApi']) 20 | ``` 21 | 22 | 2. Configure component via **$disqusApiProvider** 23 | 24 | ```js 25 | angular.module('myApp').config(function ($disqusApiProvider) { 26 | // Set our API key for Disqus 27 | $disqusApiProvider.setApiKey('123456789'); 28 | 29 | // Set our forum name for Disqus 30 | $disqusApiProvider.setForumName('mycoolforum'); 31 | } 32 | ``` 33 | 34 | ## Service 35 | 36 | You will have access to a ```disqusApi``` service which you can inject into your controllers and use to retrieve data from the API. 37 | 38 | #### Methods 39 | 40 | * ```get(category, method, params)``` 41 | 42 | > A generic method supporting all GET requests to the Disqus API (```api_key``` and ```forum``` always passed by default, all other parameters are optional) 43 | 44 | ##### Params 45 | 46 | * ```category```: The Disqus API category, eg: `forum` 47 | * ```method```: The Disqus API method to call, eg: `listPosts` 48 | * ```params```: All supported parameters detailed in the [Disqus API](https://disqus.com/api/docs/) 49 | 50 | #### Example 51 | 52 | ```js 53 | angular.module('myApp').controller('myCtrl', ['$scope', 'disqusApi', function ($scope, disqusApi) { 54 | // Pass through any additional parameters to the API 55 | var params = { 56 | limit: 5, 57 | related: 'thread' 58 | } 59 | 60 | disqusApi.get('forums', 'listPosts', params).then(function (comments) { 61 | $scope.comments = comments; 62 | console.log(comments); 63 | }); 64 | }]); 65 | ``` 66 | 67 | ## Directives 68 | 69 | There is also a helpful directive included for displaying recent comments across your forum, for example on your home page or in a news feed of some kind. This was created due to the Recent Comments widget being discontinued by Disqus. 70 | 71 | #### Example 72 | 73 | ##### As an element 74 | 75 | ``` 76 | 77 | ``` 78 | 79 | ##### As an attribute 80 | 81 | ``` 82 |
83 | ``` 84 | 85 | > You can pass through any params accepted by the Disqus API, either as an inline object in your HTML or as an object on ```$scope```. This directive uses the ```listPosts``` method on the ```forum``` category in the [Disqus API](https://disqus.com/api/docs/forums/listPosts/) 86 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-disqus-api", 3 | "version": "0.1.0", 4 | "authors": [ 5 | "Brandon Barker " 6 | ], 7 | "description": "A Disqus API wrapper for AngularJS featuring helpful directives for easily adding widgets to your pages", 8 | "main": "src/disqusApi.js", 9 | "keywords": [ 10 | "disqus", 11 | "api" 12 | ], 13 | "license": "MIT", 14 | "ignore": [ 15 | "**/.*", 16 | "node_modules", 17 | "bower_components", 18 | "test", 19 | "tests" 20 | ], 21 | "dependencies": { 22 | }, 23 | "devDependencies": { 24 | "angular": "latest", 25 | "angular-mocks": "latest", 26 | "jquery": "latest" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | 3 | // base path, that will be used to resolve files and exclude 4 | basePath = ''; 5 | 6 | // list of files / patterns to load in the browser 7 | files = [ 8 | JASMINE, 9 | JASMINE_ADAPTER, 10 | 'bower_components/angular/angular.js', 11 | 'bower_components/jquery/jquery.js', 12 | 'bower_components/angular-mocks/angular-mocks.js', 13 | 'src/*.js', 14 | 'test/spec/*.js' 15 | ]; 16 | 17 | // list of files to exclude 18 | exclude = []; 19 | 20 | // test results reporter to use 21 | // possible values: dots || progress || growl 22 | reporters = ['progress']; 23 | 24 | // web server port 25 | port = 8080; 26 | 27 | // cli runner port 28 | runnerPort = 9100; 29 | 30 | // enable / disable colors in the output (reporters and logs) 31 | colors = true; 32 | 33 | // level of logging 34 | // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG 35 | logLevel = LOG_INFO; 36 | 37 | // enable / disable watching file and executing tests whenever any file changes 38 | autoWatch = false; 39 | 40 | // Start these browsers, currently available: 41 | // - Chrome 42 | // - ChromeCanary 43 | // - Firefox 44 | // - Opera 45 | // - Safari (only Mac) 46 | // - PhantomJS 47 | // - IE (only Windows) 48 | browsers = ['Chrome']; 49 | 50 | // If browser does not capture in given timeout [ms], kill it 51 | captureTimeout = 5000; 52 | 53 | // Continuous Integration mode 54 | // if true, it capture browsers, run tests and exit 55 | singleRun = false; 56 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-disqus-api", 3 | "version": "0.1.2", 4 | "description": "angular-disqus-api", 5 | "keywords": [ 6 | "angular", 7 | "disqus", 8 | "api" 9 | ], 10 | "homepage": "https://github.com/brandon-barker/angular-disqus-api", 11 | "bugs": "https://github.com/brandon-barker/angular-disqus-api/issues", 12 | "author": { 13 | "name": "Brandon Barker", 14 | "email": "skinty@gmail.com", 15 | "url": "https://github.com/brandon-barker" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/brandon-barker/angular-disqus-api.git" 20 | }, 21 | "licenses": [ 22 | { 23 | "type": "MIT" 24 | } 25 | ], 26 | "devDependencies": { 27 | "grunt": "~0.4.1", 28 | "grunt-contrib-jshint": "~0.6.4", 29 | "grunt-contrib-concat": "~0.3.0", 30 | "grunt-contrib-uglify": "~0.2.4", 31 | "grunt-contrib-watch": "~0.5.3", 32 | "grunt-contrib-clean": "~0.5.0", 33 | "grunt-contrib-connect": "~0.5.0", 34 | "grunt-contrib-less": "~0.7.0", 35 | "connect-livereload": "~0.3.0", 36 | "grunt-open": "~0.2.2", 37 | "grunt-karma": "~0.6.2", 38 | "grunt-ngmin": "0.0.3", 39 | "grunt-bump": "0.0.11", 40 | "matchdep": "~0.1.2", 41 | "karma-html2js-preprocessor": "~0.1.0", 42 | "karma-jasmine": "~0.1.3", 43 | "karma-coffee-preprocessor": "~0.1.0", 44 | "karma": "~0.10.2" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/disqusApi.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular.module('ngDisqusApi', []); 5 | 6 | /* 7 | * ngDisqus Provider 8 | */ 9 | 10 | angular.module('ngDisqusApi').provider('$disqusApi', disqusApiProvider); 11 | 12 | /*jshint validthis: true */ 13 | function disqusApiProvider() { 14 | var forumName; 15 | var disqusApiKey; 16 | var disqusApiBaseUrl = 'https://disqus.com/api/3.0/'; 17 | 18 | this.setForumName = function (name) { 19 | forumName = name; 20 | }; 21 | 22 | this.setApiKey = function (apiKey) { 23 | disqusApiKey = apiKey; 24 | }; 25 | 26 | this.getApiKey = function () { 27 | return disqusApiKey; 28 | }; 29 | 30 | this.getApiUrl = function () { 31 | return disqusApiBaseUrl; 32 | }; 33 | 34 | this.getForumName = function () { 35 | return forumName; 36 | }; 37 | 38 | this.$get = function () { 39 | return { 40 | setForumName: this.setForumName, 41 | setApiKey: this.setApiKey, 42 | getApiKey: this.getApiKey, 43 | getApiUrl: this.getApiUrl, 44 | getForumName: this.getForumName 45 | }; 46 | }; 47 | } 48 | 49 | /* 50 | * disqusApi Service 51 | */ 52 | angular.module('ngDisqusApi').factory('disqusApi', disqusApiService); 53 | 54 | disqusApiService.$inject = ['$http', '$q', '$log', '$disqusApi']; 55 | 56 | function disqusApiService($http, $q, $log, $disqusApi) { 57 | // Get required values from provider 58 | var apiKey = $disqusApi.getApiKey(); 59 | var apiUrl = $disqusApi.getApiUrl(); 60 | var forumName = $disqusApi.getForumName(); 61 | 62 | var requiredParams = { 63 | forum: forumName, 64 | api_key: apiKey 65 | }; 66 | 67 | var service = { 68 | get: getRequest 69 | }; 70 | 71 | return service; 72 | 73 | function getRequest(category, method, params) { 74 | var deferred = $q.defer(); 75 | 76 | $http({ 77 | method: 'GET', 78 | url: apiUrl + '/' + category + '/' + method + '.json', 79 | params: angular.extend(requiredParams, params) 80 | }).success(function (data) { 81 | deferred.resolve(data.response); 82 | }).error(function (error) { 83 | deferred.reject(error); 84 | }); 85 | 86 | return deferred.promise; 87 | } 88 | } 89 | 90 | /* 91 | * Recent Comments Directive 92 | */ 93 | angular.module('ngDisqusApi').directive('recentComments', recentCommentsDirective); 94 | 95 | function recentCommentsDirective() { 96 | return { 97 | restrict: 'EA', 98 | replace: true, 99 | template: '
' + 100 | '
' + 101 | '' + 102 | '
' + 103 | '
' + 104 | '{{comment.author.name}} - {{comment.createdAt | date:"medium"}}' + 105 | '
' + 106 | '{{comment.raw_message}}' + 107 | '
' + 108 | '
' + 109 | '' + 110 | '
' + 111 | '
' + 112 | '
Posted on {{comment.thread.title}}

' + 113 | '
', 114 | scope: { 115 | params: '=' 116 | }, 117 | controller: ['$scope', 'disqusApi', function ($scope, disqusApi) { 118 | var params = $scope.params || {}; 119 | 120 | disqusApi.get('forums', 'listPosts', params).then(function (comments) { 121 | $scope.comments = comments; 122 | console.log(comments); 123 | }); 124 | }] 125 | }; 126 | } 127 | })(); 128 | -------------------------------------------------------------------------------- /test/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "browser": true, 4 | "esnext": true, 5 | "bitwise": true, 6 | "camelcase": false, 7 | "curly": false, 8 | "eqeqeq": true, 9 | "immed": true, 10 | "indent": 2, 11 | "latedef": true, 12 | "newcap": true, 13 | "noarg": true, 14 | "quotmark": "single", 15 | "regexp": true, 16 | "undef": true, 17 | "unused": false, 18 | "strict": true, 19 | "globalstrict": true, 20 | "trailing": true, 21 | "smarttabs": true, 22 | "predef": [ 23 | "$", 24 | "angular", 25 | "describe", 26 | "beforeEach", 27 | "afterEach", 28 | "inject", 29 | "it", 30 | "expect" 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /test/spec/disqusApi.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Module: disqusApi', function () { 4 | var scope, $sandbox, $compile, $timeout; 5 | 6 | // load the controller's module 7 | beforeEach(module('disqusApi')); 8 | 9 | beforeEach(inject(function ($injector, $rootScope, _$compile_, _$timeout_) { 10 | scope = $rootScope; 11 | $compile = _$compile_; 12 | $timeout = _$timeout_; 13 | 14 | $sandbox = $('
').appendTo($('body')); 15 | })); 16 | 17 | afterEach(function() { 18 | $sandbox.remove(); 19 | scope.$destroy(); 20 | }); 21 | 22 | var templates = { 23 | 'default': { 24 | scope: {}, 25 | element: '
' 26 | } 27 | }; 28 | 29 | function compileDirective(template) { 30 | template = template ? templates[template] : templates['default']; 31 | angular.extend(scope, template.scope || templates['default'].scope); 32 | var $element = $(template.element).appendTo($sandbox); 33 | $element = $compile($element)(scope); 34 | scope.$digest(); 35 | return $element; 36 | } 37 | 38 | it('should correctly display hello world', function () { 39 | var elm = compileDirective(); 40 | expect('hello world').toBe('hello world'); 41 | }); 42 | 43 | }); 44 | --------------------------------------------------------------------------------